¡Qué pasa! significa en ruby?


Me pregunto qué !! está en Ruby.

 125
Author: Andrew Marshall, 2009-02-08

7 answers

No no. Se utiliza para convertir un valor a un booleano:

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

Generalmente no es necesario usar, ya que los únicos valores falsos para Ruby son nil y false, por lo que generalmente es mejor dejar que esa convención permanezca.

Piensa en ello como

!(!some_val)

Una cosa para la que se utiliza legítimamente es evitar que se devuelva una gran cantidad de datos. Por ejemplo, es probable que no desee devolver 3 MB de datos de imagen en su método has_image?, o es posible que no desee devolver objeto de usuario completo en el método logged_in?. Usando !! convierte estos objetos a un simple true/false.

 151
Author: Alex Wayne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-29 13:29:46

Devuelve true si el objeto de la derecha no es nil y no false, false si es nil o false

def logged_in?   
  !!@current_user
end
 29
Author: RichH,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-08 14:25:16

! significa negar estado booleano, dos ! s no es nada especial, aparte de una doble negación.

!true == false
# => true

Se usa comúnmente para forzar que un método devuelva un booleano. Detectará cualquier tipo de verdad, como cadena, enteros y lo que no, y lo convertirá en un booleano.

!"wtf"
# => false

!!"wtf"
# => true

Un caso de uso más real:

def title
  "I return a string."
end

def title_exists?
  !!title
end

Esto es útil cuando desea asegurarse de que se devuelve un booleano. En mi humilde opinión, sin embargo, no tiene sentido, ya que tanto if 'some string' como if true es el exacto el mismo flujo, pero algunas personas encuentran útil devolver explícitamente un booleano.

 14
Author: August Lilleaas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-08 14:25:58

Tenga en cuenta que este modismo existe también en otros lenguajes de programación. C no tenía un tipo intrínseco bool, por lo que todos los booleanos se escribieron como int en su lugar, con valores canónicos de 0 o 1. Toma este ejemplo (paréntesis añadidos para mayor claridad):

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

La sintaxis "not-not" convierte cualquier entero distinto de cero a 1, el valor booleano verdadero canónico.

En general, sin embargo, me parece mucho mejor poner en una comparación razonable que utilizar este poco común idioma:

int x = 1234;
if (!!x); // wtf mate
if (x != 0); // obvious
 6
Author: Tom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-07 22:56:44

Es útil si necesitas hacer una exclusiva o. Copiando de la respuesta de Matt Van Horn con ligeras modificaciones:

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

!!1 ^ !!true
=> false

Lo utilicé para asegurar que dos variables fueran nil, o ambas no nil.

raise "Inconsistency" if !!a ^ !!b
 3
Author: Andrew Grimm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:29

Es "doble negativa", pero la práctica está siendo desalentada. Si está utilizando rubocop , verá que se queja de dicho código con una violación Style/DoubleNegation.

El fundamento establece:

Como esto es críptico y generalmente redundante, debe evitarse [entonces parafraseando:] Cambiar !!something a !something.nil?

 3
Author: Micah Elliott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-20 16:39:14

Comprender cómo funciona puede ser útil si necesita convertir, por ejemplo, una enumeración en un booleano. Tengo un código que hace exactamente eso, usando la gema 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

Luego en el código de servicio tengo, por ejemplo:

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

Efectivamente el operador bangbang se ha convertido en lo que de otra manera podría haber escrito como un método llamado to_bool.

 0
Author: inopinatus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-16 03:42:38