Nedir !! ruby demek?


134

Sadece !!Ruby'de ne olduğunu merak ediyorum .

Yanıtlar:


161

Değil. Bir değeri bir boole değerine dönüştürmek için kullanılır:

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

Ruby için tek yanlış değerler olduğu için genellikle kullanmak gerekli değildir nilve falsebu nedenle konvansiyonun ayakta kalmasına izin vermek en iyisidir.

Bir düşünün

!(!some_val)

Meşru olarak kullanılan bir şey, büyük miktarda veri döndürülmesini önlemektir. Örneğin, has_image?yönteminizde muhtemelen 3 MB resim verisi döndürmek istemezsiniz veya yöntemdeki tüm kullanıcı nesnesini döndürmek istemeyebilirsiniz logged_in?. Kullanarak !!bu nesneleri basit true/ false.


8
Bunu kullanmak kötü bir uygulama değildir. Çift patlama genellikle açık bir boole değeri döndürmek için tahminlerde (? İle biten yöntemler) kullanılır.
Swanand

6
Alex, Ruby'nin nesnenin bir kopyasını değil, bir referansı döndüreceği için büyük nesneleri döndürme konusunda endişelenmenize gerek yok.
DSimon

10
@Simon, bazen hata ayıklama sırasında bir değeri yazdırırken veya günlüğe kaydederken olduğu gibi büyük nesneler hakkında endişelenmeniz gerekir.
Wayne Conrad

Neden .nil?kullanmak yerine geri dönmüyorsunuz !!? Bir fark var mı?
ashes999

3
Değeriniz bir booelan olduğunda bir fark vardır. !!true #=> truevetrue.nil? #=> false
Alex Wayne

31

Bu döndüren truesağdaki nesne değilse nildeğil false, falseo ise nilveyafalse

def logged_in?   
  !!@current_user
end

1
Restful_Auth'dan geldiği belli miydi ?! : D
Cameron

14

!boolean durumunu olumsuzlamak anlamına gelir, iki !s çift bir olumsuzlama dışında özel bir şey değildir.

!true == false
# => true

Genellikle bir yöntemi bir boole döndürmeye zorlamak için kullanılır. Dize, tamsayılar ve ne gibi her türlü gerçeği algılar ve boole dönüştürür.

!"wtf"
# => false

!!"wtf"
# => true

Daha gerçek bir kullanım durumu:

def title
  "I return a string."
end

def title_exists?
  !!title
end

Bu, bir boole döndürüldüğünden emin olmak istediğinizde kullanışlıdır. IMHO görerek olsa da, nazik anlamsız olduğunu hem if 'some string've if trueaynı akış, ancak bazı insanlar bunun yararlı açıkça bir boolean dönmek bulabilirsiniz.


bana bir if ifadesini veya üçlü operatörü kullanmaktan daha hızlı bir yol gibi geliyor. Geri dönemeyeceğin için title, ona en yakın şeyi de yapabilirsin ... Sanırım
Carson Myers

6

Bu deyimin diğer programlama dillerinde de bulunduğunu unutmayın. C'nin kendine özgü bir booltürü yoktu , bu yüzden tüm booleanlar, intyerine 0veya değerlerinin kanonik değerleri ile yazıldı 1. Bu örneği alır (açıklık için parantez eklenmiştir):

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

"Not-not" sözdizimi, sıfır olmayan herhangi bir tamsayıyı 1standart boolean true değerine dönüştürür.

Genel olarak, ancak, bu nadir deyimi kullanmaktan daha makul bir karşılaştırma yapmak daha iyi buluyorum:

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

Ya da (x) ise. !! 0/1 elde etmeniz gerektiğinde kullanışlıdır. (X) 'i düşünebilir veya düşünmeyebilirsiniz? 1: 0 daha net.
derobert

3

Özel bir veya yapmanız gerekiyorsa yararlıdır . Matt Van Horn'un cevabından küçük değişikliklerle kopyalama:

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

!!1 ^ !!true
=> false

İki değişkenin ya sıfır ya da her ikisinin de nil olmadığından emin olmak için kullandım.

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

3

Bu "çift negatiftir", ancak uygulama önerilmez. Rubocop kullanıyorsanız , bu tür kodlardan bir Style/DoubleNegationihlale karşı şikayet edildiğini göreceksiniz .

Mantık durumları:

Bu şifreli ve genellikle gereksiz hem olduğundan, kaçınılmalıdır [sonra başka sözcüklerle:] Değişim !!somethingiçin!something.nil?


1
Ama ... !!false # => falsesüre!false.nil? # => true
Doug

@ Doug Boolean değeriniz olduğunu biliyorsanız, bu gereksizdir (sadece değeri kullanın). !(foo.nil? || foo == false)Kullanmazsanız, kullanabilirsiniz - daha ayrıntılı, evet, ama daha az şifreli.
David Moles

0

Bir numaralandırmayı bir boole dönüştürmeniz gerekiyorsa, bunun nasıl çalıştığını anlamak yararlı olabilir. Ben classy_enumgem kullanarak tam olarak bunu yapan bir kod var :

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

Sonra hizmet kodu var, örneğin:

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

Etkili bangbang operatör aksi takdirde to_bool denilen bir yöntem olarak yazmış olabilir ne oldu.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.