Câu trả lời:
Không không. Nó được sử dụng để chuyển đổi một giá trị thành boolean:
!!nil #=> false
!!"abc" #=> true
!!false #=> false
Thông thường không cần thiết phải sử dụng vì các giá trị sai duy nhất đối với Ruby là nil
và false
vì vậy, tốt nhất là để cho quy ước đó đứng vững.
Hãy nghĩ về nó như là
!(!some_val)
Một điều được sử dụng cho mục đích hợp pháp là ngăn chặn một khối dữ liệu khổng lồ được trả lại. Ví dụ: bạn có thể không muốn trả về 3 MB dữ liệu hình ảnh trong has_image?
phương thức của mình hoặc bạn có thể không muốn trả về toàn bộ đối tượng người dùng của mình trong logged_in?
phương thức. Sử dụng !!
chuyển đổi các đối tượng này thành đơn giản true
/ false
.
.nil?
thay vì sử dụng !!
? Có sự khác biệt?
!!true #=> true
vàtrue.nil? #=> false
!
có nghĩa là phủ định trạng thái boolean, hai !
s không có gì đặc biệt, ngoài một phủ định kép.
!true == false
# => true
Nó thường được sử dụng để buộc một phương thức trả về boolean. Nó sẽ phát hiện bất kỳ loại tính trung thực nào, chẳng hạn như chuỗi, số nguyên và những 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
Điều này rất hữu ích khi bạn muốn chắc chắn rằng boolean được trả về. IMHO là một điều vô nghĩa, mặc dù, thấy rằng cả hai if 'some string'
và if true
là cùng một dòng chảy, nhưng một số người thấy hữu ích khi trả lại một cách rõ ràng một boolean.
title
, cũng có thể làm điều gần gũi nhất với nó ... tôi cho rằng
Lưu ý rằng thành ngữ này cũng tồn tại trong các ngôn ngữ lập trình khác. C không có bool
kiểu nội tại , vì vậy tất cả các booleans được gõ int
thay vào đó, với các giá trị chính tắc là 0
hoặc 1
. Lấy ví dụ này (dấu ngoặc đơn được thêm cho rõ ràng):
!(1234) == 0
!(0) == 1
!(!(1234)) == 1
Cú pháp "không phải không" chuyển đổi bất kỳ số nguyên khác không 1
thành giá trị đúng boolean chính tắc.
Tuy nhiên, nói chung, tôi thấy tốt hơn nhiều khi đưa ra một so sánh hợp lý hơn là sử dụng thành ngữ không phổ biến này:
int x = 1234;
if (!!x); // wtf mate
if (x != 0); // obvious
Nó hữu ích nếu bạn cần làm độc quyền hoặc . 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 là cả hai hoặc không hoặc không.
raise "Inconsistency" if !!a ^ !!b
Đó là "tiêu cực kép", nhưng thực tế đang được khuyến khích. Nếu bạn đang sử dụng rubocop , bạn sẽ thấy nó phàn nàn về mã đó với Style/DoubleNegation
vi phạm.
Cơ sở lý luận nêu rõ:
Vì đây là cả mật mã và thường là dư thừa, nên tránh [sau đó diễn giải:] Thay đổi
!!something
thành!something.nil?
!!false # => false
trong khi!false.nil? # => true
!(foo.nil? || foo == false)
- dài dòng hơn, có, nhưng ít khó hiểu hơn.
Hiểu cách thức hoạt động của nó có thể hữu ích nếu bạn cần chuyển đổi, giả sử, liệt kê thành boolean. Tôi có mã thực hiện 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 có, ví dụ:
raise Application::Error unless !!object.link_status # => raises exception for "No" and "Denied" states.
Thực tế, toán tử bangbang đã trở thành cái mà tôi có thể đã viết như một phương thức gọi là to_bool.