2009-02-07 45 views

Trả lời

145

Không. Nó được sử dụng để chuyển đổi một giá trị cho một boolean:

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

Nó thường không cần thiết phải sử dụng mặc dù kể từ khi giá trị sai chỉ để Ruby là nilfalse, vì vậy nó thường là tốt nhất để cho rằng ước đứng.

nghĩ về nó như

!(!some_val) 

Một điều đó là nó được sử dụng cho hợp pháp đang ngăn được một lượng lớn dữ liệu khỏi bị trả lại. Ví dụ: có thể bạn không muốn trả lại 3MB dữ liệu hình ảnh theo phương pháp has_image? của mình hoặc bạn có thể không muốn trả lại toàn bộ đối tượng người dùng theo phương thức logged_in?. Sử dụng !! chuyển đổi các đối tượng này thành đơn giản true/false.

+3

Vì vậy, đó là một đôi tiêu cực? – Ross

+6

Nó không phải là một thực tế xấu để sử dụng này. Double bang thường được sử dụng trong các vị từ (các phương thức kết thúc bằng?) Để trả về một giá trị boolean rõ ràng. – Swanand

+6

Alex, bạn không thực sự cần phải lo lắng về việc trả về các đối tượng lớn, vì Ruby sẽ trả về một tham chiếu, không phải là một bản sao của đối tượng. – DSimon

28

Nó trả true nếu đối tượng ở bên phải không phải là nil và không false, false nếu nó là nil hoặc false

def logged_in? 
    [email protected]_user 
end 
+1

Rõ ràng là nó đến từ Restful_Auth ?! : D – Cameron

+0

Không chỉ nếu đó là số không. – womble

6

Lưu ý rằng thành ngữ này tồn tại trong ngôn ngữ lập trình khác nữa. C không có loại nội tại bool, vì vậy, tất cả các boolean được nhập là int thay vào đó, với các giá trị chuẩn là 0 hoặc 1. Đưa ví dụ này (ngoặc nói thêm cho rõ ràng):

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

Các "không-không phải là" cú pháp chuyển đổi bất kỳ khác không số nguyên để 1, boolean kinh điển giá trị true.

Nói chung, tuy nhiên, tôi thấy nó tốt hơn nhiều để đưa vào một so sánh hợp lý hơn để sử dụng thành ngữ phổ biến này:

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

Hoặc chỉ khi (x). !! rất hữu ích khi bạn cần nhận 0/1. Bạn có thể hoặc không thể xem xét (x)? 1: 0 rõ ràng hơn. – derobert

14

! phương tiện phủ nhận nhà nước boolean, hai ! s là không có gì đặc biệt, ngoại trừ một đôi phủ định.

!true == false 
# => true 

Nó thường được sử dụng để buộc phương thức trả về giá trị boolean. Nó sẽ phát hiện bất kỳ loại sự thật nào, chẳng hạn như chuỗi, số nguyên và cái gì không, và biến nó thành một boolean.

!"wtf" 
# => false 

!!"wtf" 
# => true 

Một trường hợp sử dụng thực tế hơn:

def title 
    "I return a string." 
end 

def title_exists? 
    !!title 
end 

này rất hữu ích khi bạn muốn chắc chắn rằng một boolean được trả về. IMHO nó là loại vô nghĩa, mặc dù, thấy rằng cả hai if 'some string'if true là chính xác cùng một dòng chảy, nhưng một số người tìm thấy nó hữu ích để trả lại một cách rõ ràng một boolean.

+0

có vẻ như với tôi chỉ là một cách nhanh hơn so với sử dụng một tuyên bố nếu hoặc một nhà điều hành ternary. Vì bạn không thể chỉ trả về 'tựa đề', cũng có thể làm điều gần nhất với nó ... Tôi giả sử –

3

Sẽ hữu ích nếu bạn cần thực hiện exclusive or.Sao chép từ câu trả lời của Matt Van Horn với những sửa đổi nhỏ:

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

!!1^!!true 
=> false 

Tôi đã sử dụng nó để đảm bảo hai biến số không phải là cả hai, hoặc không phải là không.

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

Hiểu cách hoạt động có thể hữu ích nếu bạn cần chuyển đổi, ví dụ: liệt kê thành boolean. Tôi có mã nào chính xác điều đó, bằng cách sử dụng classy_enum đá quý:

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 

Sau đó, trong mã dịch vụ tôi đã, ví dụ:

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

có hiệu quả các nhà điều hành bangbang đã trở thành những gì tôi lẽ ra đã viết như một phương thức gọi là to_bool.

3

Đó là "hai âm", nhưng thực tế không được khuyến khích. Nếu bạn đang sử dụng rubocop, bạn sẽ thấy nó khiếu nại trên mã như vậy với vi phạm Style/DoubleNegation.

Các rationale trạng thái:

Vì đây là cả hai khó hiểu và thường dư thừa, nó nên tránh [sau đó diễn giải:] Thay đổi !!something để !something.nil?

+0

Nhưng ... ' '' !! false # => false''' trong khi '' ' false.nil? # => true''' – Doug