代码之家  ›  专栏  ›  技术社区  ›  kikito

为什么Ruby有TrueClass和FalseClass而不是一个布尔类?

  •  70
  • kikito  · 技术社区  · 15 年前

    当我发现这个的时候,我正在序列化值。鲁比有一个 TrueClass FalseClass 类,但它没有 Boolean

    我认为使用 布尔值 ; 例如,字符串解析可以集中在它上面。

    OneClass 和一个 TwoClass Fixnum .

    8 回复  |  直到 13 年前
        1
  •  61
  •   Jörg W Mittag    15 年前

    类的目的是将相似的对象或具有相似行为的对象组合在一起。 1 2 他们非常相似,所以他们在同一个班级是完全有道理的。 true false 然而,我们 整点 他们就是 相反的

    你能举一个例子,说明你会在一个项目中实施什么样的常见行为吗 Boolean 上课?我什么都想不出来。

    TrueClass FalseClass have:确实有 恰恰相反

    下面是如何实现所有这些方法:

    class TrueClass
      def &(other)
        other
      end
    
      def |(_)
        self
      end
    
      def ^(other)
        !other
      end
    
      def to_s
        'true'
      end
    end
    

    class FalseClass
      def &(_)
        self
      end
    
      def |(other)
        other
      end
    
      def ^(other)
        other
      end
    
      def to_s
        'false'
      end
    end
    

    特级 假类 而是硬连接到解释器。比如 if && || ! . 然而,在Smalltalk中,Ruby借鉴了很多东西,包括 假类 特级 ,所有这些都实现为方法,您可以在Ruby中执行相同的操作:

    class TrueClass
      def if
        yield
      end
    
      def ifelse(then_branch=->{}, _=nil)
        then_branch.()
      end
    
      def unless
      end
    
      def unlesselse(_=nil, else_branch=->{})
        ifelse(else_branch, _)
      end
    
      def and
        yield
      end
    
      def or
        self
      end
    
      def not
        false
      end
    end
    

    反过来说:

    class FalseClass
      def if
      end
    
      def ifelse(_=nil, else_branch=->{})
        else_branch.()
      end
    
      def unless
        yield
      end
    
      def unlesselse(unless_branch=->{}, _=nil)
        ifelse(_, unless_branch)
      end
    
      def and
        self
      end
    
      def or
        yield
      end
    
      def not
        true
      end
    end
    

    几年前,我写这篇文章只是为了好玩 even published it the RubySpec conformance testsuite ported it over to my syntax 然后就过去了。

        2
  •  23
  •   kikito    15 年前

    mailing list message 2004年。

    我个人不同意这一点;前面提到的“字符串解析”就是一个例子。另一个问题是,当您根据变量的类型对其应用不同的处理方法时(例如,一个yml解析器),拥有一个“Boolean”类是很方便的—它会删除一个“if”。它看起来也更正确,但这是个人观点。

        3
  •  5
  •   the Tin Man    10 年前

    引用Matz on Ruby forum (2013)

    …没有真与假的共享,因此没有布尔类。 除此之外,在Ruby中,所有的行为都是布尔值。。。。

        4
  •  4
  •   Asher postmodern    15 年前

    true和false可以由一个包含多个值的布尔类来管理,但是class对象必须具有内部值,因此每次使用都必须取消引用。

    相反,Ruby将true和false视为长值(0和1),每个值对应于一种对象类(FalseClass和TrueClass)。通过使用两个类而不是一个布尔类,每个类不需要任何值,因此可以通过其类标识符(0或1)进行区分。我相信这可以转化为Ruby引擎内部的显著速度优势,因为在Ruby内部可以将TrueClass和FalseClass视为需要从其ID值进行零转换的长值,而布尔对象在计算之前必须取消引用。

        5
  •  3
  •   Slipp D. Thompson Jon Brooks    9 年前

    因为除了 false nil 在Ruby中,默认情况下求值为true,您只需要向字符串添加解析。

    class Object
    
      ## Makes sure any other object that evaluates to false will work as intended,
      ##     and returns just an actual boolean (like it would in any context that expect a boolean value).
      def trueish?; !!self; end
    
    end
    
    class String
    
      ## Parses certain strings as true; everything else as false.
      def trueish?
        # check if it's a literal "true" string
        return true if self.strip.downcase == 'true'
    
        # check if the string contains a numerical zero
        [:Integer, :Float, :Rational, :Complex].each do |t|
          begin
            converted_number = Kernel.send(t, self)
            return false if converted_number == 0
          rescue ArgumentError
            # raises if the string could not be converted, in which case we'll continue on
          end
        end
    
        return false
      end
    
    end
    

    puts false.trueish?   # => false
    puts true.trueish?    # => true
    puts 'false'.trueish? # => false
    puts 'true'.trueish?  # => true
    puts '0'.trueish?     # => false
    puts '1'.trueish?     # => true
    puts '0.0'.trueish?   # => false
    puts '1.0'.trueish?   # => true
    

    我相信Ruby背后的一个重要思想就是让你所希望的行为成为你程序的固有行为(例如布尔解析),而不是创建一个完全封装的类,它生活在自己的命名空间世界中(例如BooleanParser)。

        6
  •  1
  •   Mongus Pong    15 年前

    在Ruby中,nil和false都是假的,其他的都是真的。因此不需要特定的布尔类。

    你可以试试:

    if 5
      puts "5 is true"
    end
    

    5计算为真

    if nil
        puts "nil is true"
    else
        puts "nil is false"
    end
    

    将打印“nil is false”

        7
  •  1
  •   Chucky    12 年前

    主要原因很简单,这是一个事实,这是更快和更简单的实现布尔表达式,因为它是目前比布尔类,这意味着转换。

    正如Mongus Pong告诉你的,当你写“如果”时,你要求解释者评估 事情 然后是分支。如果有布尔类,就必须转换 事情 变成布尔值 之前 分支(多走一步)。

    记住,这样一个->布尔转换可以作为布尔类中的Ruby方法使用。然后可以像其他任何Ruby方法一样动态地更改这个方法,允许开发人员将事情完全搞砸(这确实不是那么严重),但是很明显,这不允许解释程序按其应该的方式优化测试。

    您是否意识到,它将用一个完整的方法调用代替一些CPU指令操作,这在Ruby中是昂贵的(记住“send”方法处理)。。。

        8
  •  -2
  •   Volte    8 年前

    class Boolean
      def self.new(bool)
        bool
      end
    
      def self.true
        true
      end
    
      def self.false
        false
      end
    end
    
    class FalseClass
      def is_a?(other)
        other == Boolean || super
      end
    
      def self.===(other)
        other == Boolean || super
      end
    end
    
    class TrueClass
      def is_a?(other)
        other == Boolean || super
      end
    
      def self.===(other)
        other == Boolean || super
      end
    end
    
    推荐文章