【问题标题】:What does !! mean in ruby?什么!!在红宝石中是什么意思?
【发布时间】:2010-10-06 04:42:44
【问题描述】:

只是想知道!! 在 Ruby 中是什么。

【问题讨论】:

    标签: ruby


    【解决方案1】:

    不是。

    用于将值转换为布尔值:

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

    通常没有必要使用它,因为 Ruby 的唯一错误值是 nilfalse,所以通常最好保持这种约定。

    把它想象成

    !(!some_val)
    

    它的合法用途之一是防止返回大量数据。例如,您可能不想在 has_image? 方法中返回 3MB 的图像数据,或者您可能不想在 logged_in? 方法中返回整个用户对象。使用!! 将这些对象转换为简单的true/false

    【讨论】:

    • 使用它并不是一个坏习惯。双 bang 常用于谓词(以 ? 结尾的方法)以返回显式布尔值。
    • Alex,您不必担心返回大对象,因为 Ruby 将返回引用,而不是对象的副本。
    • @DSimon,有时您确实需要担心大对象,例如在调试期间打印或记录值时。
    • 为什么不直接返回.nil? 而不是使用!!?有区别吗?
    • 当您的值是布尔值时会有所不同。 !!true #=> truetrue.nil? #=> false
    【解决方案2】:

    如果右边的对象不是nil而不是false,则返回true,如果是nilfalse,则返回false

    def logged_in?   
      !!@current_user
    end
    

    【讨论】:

    • 很明显它来自Restful_Auth吗?! :D
    【解决方案3】:

    ! 表示否定布尔状态,两个!s 没什么特别的,除了一个双重否定。

    !true == false
    # => true
    

    通常用于强制方法返回布尔值。它将检测任何类型的真实性,例如字符串、整数等,并将其转换为布尔值。

    !"wtf"
    # => false
    
    !!"wtf"
    # => true
    

    更真实的用例:

    def title
      "I return a string."
    end
    
    def title_exists?
      !!title
    end
    

    当您想确保返回一个布尔值时,这很有用。恕我直言,虽然if 'some string'if true 是完全相同的流程,但有些人发现显式返回布尔值很有用。

    【讨论】:

    • 在我看来,这只是比使用 if 语句或三元运算符更快的方法。既然你不能只返回title,不如做最接近它的事情......我想
    【解决方案4】:

    请注意,这个习语也存在于其他编程语言中。 C 没有固有的bool 类型,因此所有布尔值都被键入为int,而规范值为01。以这个例子为例(为清楚起见添加了括号):

    !(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 更清晰。
    【解决方案5】:

    如果您需要exclusive or,这很有用。复制 Matt Van Horn 的回答并稍作修改:

    1 ^ true
    TypeError: can't convert true into Integer
    
    !!1 ^ !!true
    => false
    

    我用它来确保两个变量要么都是 nil,要么都不是 nil。

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

    【讨论】:

      【解决方案6】:

      这是“双重否定”,但不鼓励这种做法。如果您使用的是rubocop,您会看到它在此类代码上抱怨Style/DoubleNegation 违规。

      rationale 声明:

      由于这既神秘又通常是多余的,因此应该避免 [然后解释:] 将 !!something 更改为 !something.nil?

      【讨论】:

      • 但是...!!false # => false!false.nil? # => true
      • @Doug 如果你知道你有一个布尔值,那就是多余的(只需使用该值)。如果你不这样做,你可以使用!(foo.nil? || foo == false)——更详细,是的,但不那么神秘。
      【解决方案7】:

      如果您需要将枚举转换为布尔值,那么了解它的工作原理会很有用。我有使用classy_enum gem 的代码:

      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 的方法。

      【讨论】:

        【解决方案8】:

        其他答案讨论了!! 的作用以及它是否是好的做法。

        但是,没有一个答案给出将值转换为布尔值的“标准 Ruby 方式”。

        true & variable
        

        TrueClass,Ruby值true的类,实现了一个方法&amp;,即documented,如下:

        如果objnilfalse,则返回false,否则返回true

        既然你已经涵盖了标准库,为什么还要使用肮脏的双重否定?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-27
          • 2014-10-22
          • 1970-01-01
          • 2015-07-14
          • 2011-09-09
          • 1970-01-01
          相关资源
          最近更新 更多