อะไร !! หมายถึงทับทิม?


คำตอบ:


161

ไม่ไม่ ใช้เพื่อแปลงค่าเป็นบูลีน:

!!nil   #=> false
!!"abc" #=> true
!!false #=> false

โดยปกติแล้วไม่จำเป็นต้องใช้เนื่องจากค่าเท็จเพียงอย่างเดียวสำหรับ Ruby คือnilและfalseโดยปกติแล้วควรปล่อยให้การประชุมนั้นยืนอยู่ได้ดีที่สุด

คิดว่าเป็น

!(!some_val)

สิ่งหนึ่งที่ใช้เพื่อความถูกต้องคือการป้องกันไม่ให้มีการส่งคืนข้อมูลจำนวนมาก ตัวอย่างเช่นคุณอาจไม่ต้องการส่งคืนข้อมูลรูปภาพ 3MB ในhas_image?วิธีการของคุณหรือคุณอาจไม่ต้องการส่งคืนออบเจ็กต์ผู้ใช้ทั้งหมดของคุณในlogged_in?วิธีนี้ การใช้!!แปลงวัตถุเหล่านี้ให้เป็นแบบง่ายtrue/ false.


8
การใช้สิ่งนี้ไม่ใช่เรื่องเลวร้าย Double Bang มักใช้ในเพรดิเคต (วิธีการที่ลงท้ายด้วย?) เพื่อส่งคืนค่าบูลีนอย่างชัดเจน
Swanand

6
อเล็กซ์คุณไม่จำเป็นต้องกังวลเกี่ยวกับการส่งคืนวัตถุขนาดใหญ่เนื่องจาก Ruby จะส่งคืนข้อมูลอ้างอิงไม่ใช่สำเนาของวัตถุ
DSimon

10
@DSimon บางครั้งคุณไม่จำเป็นต้องกังวลเกี่ยวกับวัตถุขนาดใหญ่เช่นเมื่อพิมพ์หรือบันทึกค่าระหว่างการดีบัก
Wayne Conrad

ทำไมไม่เพียงส่งคืน.nil?แทนที่จะใช้!!? มีความแตกต่างหรือไม่?
ashes999

3
มีความแตกต่างเมื่อค่าของคุณคือ booelan !!true #=> trueและtrue.nil? #=> false
Alex Wayne

31

ก็จะส่งกลับtrueถ้าวัตถุด้านขวาไม่ได้nilและไม่ได้false, falseถ้ามันเป็นnilหรือfalse

def logged_in?   
  !!@current_user
end

1
เห็นได้ชัดว่ามาจาก Restful_Auth หรือไม่! : D
Cameron

14

!หมายถึงลบสถานะบูลีนสอง!วินาทีไม่มีอะไรพิเศษนอกจากการปฏิเสธสองครั้ง

!true == false
# => true

โดยทั่วไปจะใช้เพื่อบังคับให้เมธอดคืนค่าบูลีน มันจะตรวจจับความจริงประเภทใด ๆ เช่นสตริงจำนวนเต็มและสิ่งที่ไม่และเปลี่ยนเป็นบูลีน

!"wtf"
# => false

!!"wtf"
# => true

กรณีการใช้งานจริงเพิ่มเติม:

def title
  "I return a string."
end

def title_exists?
  !!title
end

สิ่งนี้มีประโยชน์เมื่อคุณต้องการให้แน่ใจว่ามีการส่งคืนบูลีน IMHO เป็นเรื่องที่ไม่มีจุดหมายแม้ว่าจะเห็นว่าทั้งสองอย่างif 'some string'และif trueเป็นขั้นตอนเดียวกัน แต่บางคนพบว่ามีประโยชน์ในการส่งคืนบูลีนอย่างชัดเจน


สำหรับฉันแล้วดูเหมือนว่าจะเป็นวิธีที่เร็วกว่าการใช้คำสั่ง if หรือตัวดำเนินการที่เกี่ยวข้อง เนื่องจากคุณไม่สามารถกลับมาtitleได้อาจทำสิ่งที่ใกล้เคียงที่สุดกับมันด้วยก็ได้ ... ฉันคิดว่า
Carson Myers

6

โปรดทราบว่าสำนวนนี้มีอยู่ในภาษาโปรแกรมอื่นเช่นกัน C ไม่ได้มีอยู่ภายในboolชนิดดังนั้น booleans ทั้งหมดถูกพิมพ์เป็นintแทนด้วยค่ายอมรับหรือ0 1นำตัวอย่างนี้ (เพิ่มวงเล็บเพื่อความชัดเจน):

!(1234) == 0
!(0) == 1
!(!(1234)) == 1

ไวยากรณ์ "not-not" จะแปลงจำนวนเต็มที่ไม่ใช่ศูนย์เป็น 1ที่แท้จริงของบูลีนที่ยอมรับได้

โดยทั่วไปแล้วฉันพบว่าการเปรียบเทียบที่สมเหตุสมผลดีกว่าการใช้สำนวนที่ผิดปกตินี้:

int x = 1234;
if (!!x); // wtf mate
if (x != 0); // obvious

หรือถ้า (x) !! มีประโยชน์เมื่อคุณต้องการรับ 0/1 คุณอาจพิจารณาหรือไม่ก็ได้ (x)? 1: 0 ชัดเจนขึ้น
derobert

3

จะมีประโยชน์หากคุณต้องการทำเอกสิทธิ์เฉพาะบุคคลหรือ . คัดลอกจากคำตอบของ Matt Van Horn โดยมีการปรับเปลี่ยนเล็กน้อย:

1 ^ true
TypeError: can't convert true into Integer

!!1 ^ !!true
=> false

ฉันใช้มันเพื่อให้แน่ใจว่าตัวแปรสองตัวเป็นทั้งสองศูนย์หรือทั้งคู่ไม่ใช่ศูนย์

raise "Inconsistency" if !!a ^ !!b

3

มันเป็น "ลบสองครั้ง" แต่การปฏิบัติกำลังท้อแท้ หากคุณใช้rubocopคุณจะเห็นว่ามีการบ่นเกี่ยวกับรหัสดังกล่าวด้วยไฟล์Style/DoubleNegationการละเมิด

เหตุผลฯ :

เนื่องจากเป็นทั้งแบบคลุมเครือและมักจะซ้ำซ้อนจึงควรหลีกเลี่ยง [แล้วถอดความ:] เปลี่ยน!!somethingเป็น!something.nil?


1
แต่ ... !!false # => falseในขณะที่!false.nil? # => true
Doug

@ Doug ถ้าคุณรู้ว่าคุณมีค่าบูลีนมันซ้ำซ้อน (แค่ใช้ค่า) หากไม่เป็นเช่นนั้นคุณสามารถใช้!(foo.nil? || foo == false)- ใช้คำละเอียดมากขึ้นใช่ แต่มีความคลุมเครือน้อยกว่า
David Moles

0

การทำความเข้าใจวิธีการทำงานจะมีประโยชน์หากคุณต้องการแปลงเช่นการแจงนับเป็นบูลีน ฉันมีรหัสที่ทำอย่างนั้นโดยใช้classy_enumอัญมณี:

class LinkStatus < ClassyEnum::Base
  def !
    return true
  end
end

class LinkStatus::No < LinkStatus
end

class LinkStatus::Claimed < LinkStatus
  def !
    return false
  end
end

class LinkStatus::Confirmed < LinkStatus
  def !
    return false
  end
end

class LinkStatus::Denied < LinkStatus
end

จากนั้นในรหัสบริการฉันมีตัวอย่างเช่น:

raise Application::Error unless !!object.link_status   # => raises exception for "No" and "Denied" states.

ตัวดำเนินการ bangbang อย่างมีประสิทธิภาพกลายเป็นสิ่งที่ฉันอาจเขียนเป็นวิธีการที่เรียกว่า to_bool


0

คำตอบอื่น ๆ ได้กล่าวถึงสิ่งที่!!ทำและการปฏิบัติที่ดีหรือไม่

อย่างไรก็ตามไม่มีคำตอบใดที่ให้ "วิธี Ruby มาตรฐาน" ในการส่งค่าเป็นบูลีน

true & variable

TrueClassคลาสของค่า Ruby trueใช้เมธอด&ซึ่งมีเอกสารดังนี้:

ผลตอบแทนfalseถ้าobjเป็นnilหรือfalse, trueมิฉะนั้น

เหตุใดจึงต้องใช้การลบล้างสองครั้งที่สกปรกเมื่อคุณครอบคลุมไลบรารีมาตรฐาน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.