Comment by jhbadger

Comment by jhbadger 20 hours ago

7 replies

If you are familiar with a true object-oriented language like Smalltalk (rather than the watered-down form of OO in C++, Java, etc.), an integer like 5 having methods makes sense because it (like everything else) is an object. Objects in Ruby aren't just window dressing -- they are its core.

ck45 20 hours ago

But then Ruby only goes half way, not unlike the "watered-down form" in your term. Why is `#times` a method of Integer, but `#if` (or `#ifTrue`) not a method of booleans like in Smalltalk? Ruby does the same cherry picking from Smalltalk like everybody else, just different cherries. When looking at Ruby, it feels like the simple examples are all nice and clean but then the weird details start to appear and the language feels more hacky than others (like Ned Flander's house in Simpsons S08E08).

  • chao- 20 hours ago

    #if and #ifTrue are yours if you want them:

      class TrueClass
        def if = true
        def ifTrue = true
      end
    
      class FalseClass
        def if = false
        def ifTrue = false
      end
    
      true.if
      # => true
      false.if
      # => false
    • wild_egg 19 hours ago

      In Smalltalk those methods don't return `true`. They take a block and evaluate it if the boolean receiving the message

          (a > b) ifTrue: [ "do something" ]
      
      EDIT: to clarify what's happening there, `>` is a message sent to `a` that will result in a boolean. The True class and False class both understand the ifTrue: message and `True>>ifTrue:` executes the block whereas `False>>ifTrue:` just throws it away.

      There's no `if` keyword in the language. Control flow is done purely through polymorphism.

      • chao- 19 hours ago

        I apologize for my lack of Smalltalk knowledge. As you can imagine, you can do similar in Ruby by defining ifTrue to accept a block, even adding ifTrue on other all objects and defining something similar:

          class TrueClass
            def ifTrue(&block) = block.call
          end
        
          class FalseClass
            def ifTrue(&block) = nil
          end
        
          class Object
            def ifTrue(&block) = block.call
          end
              
          class NilClass
            def ifTrue(&block) = nil
          end
        
        If ck45's core complaint was that this is not baked into the language, I will agree that it is less convenient for lack of a default.
      • oezi 19 hours ago

        Certainly possible: add ifTrue as a method to TrueClass and FalseClass.

        It just isn't very fast.

        • codesnik 17 hours ago

          problem is not with ifTrue, and not with it's performance, it's easy to do. it is "ifTrue:ifFalse:"

          also it is common to do assignments in the "if", and with actual method and blocks scope of the introduced variable would be different and everyone would be tripping on it all the time.

  • codesnik 17 hours ago

    basically it's because of "else" and "elsif". While ".each" works the same as "for .. in ...; end", it's harder to do "if else" as method which will also return value of the block inside the branch. Smalltalk can do it because "ifTrue:ifFalse:" is _one_ message, ruby didn't go that way syntactically.