• shagie@programming.dev
    link
    fedilink
    arrow-up
    2
    ·
    1 year ago

    In Ruby, foo?a:b parses differently than foo ?a:b and the first one isn’t parsed a ternary expression.

    Consider the following code snippets and execution:

    $ cat f1.rb 
    puts "foo".length
    puts 3?"stuff":"empty"
    $ ruby f1.rb 
    3
    stuff
    

    Nothing surprising there. Let’s replace that 3 with the call that returns 3.

    $ cat f2.rb 
    puts "foo".length?"stuff":"empty"
    $ ruby f2.rb 
    f2.rb:1:in `': undefined method `length?' for "foo":String (NoMethodError)
    Did you mean?  length
    

    But that parsed as "foo".length? and was looking for a method call because ruby methods can end in ? but couldn’t find the method so returned an error.

    Let’s put a space in there so that its the length method again without trying to become length?

    $ cat f3.rb
    puts "foo".length ?"stuff":"empty"
    $ ruby f3.rb 
    f3.rb:1: syntax error, unexpected tIDENTIFIER, expecting end-of-input
    puts "foo".length ?"stuff":"empty"
    

    It’s apparently expecting something with the "stuff". Lets put in more spaces.

    $ cat f4.rb
    puts "foo".length ? "stuff" : "empty"
    $ ruby f4.rb 
    stuff
    

    And this returned what was expected… but this needed a lot more spaces in a lot more places than the puts 3?"stuff":"empty" that worked in the first call.

      • shagie@programming.dev
        link
        fedilink
        arrow-up
        2
        ·
        1 year ago

        But why would 3?"stuff":"empty" work and foo?"stuff":"empty" not work?

        Syntactically significant whitespace is a nightmare to deal with.

        • jvisick@programming.dev
          link
          fedilink
          arrow-up
          3
          ·
          1 year ago

          I agree! I don’t think 3?”stuff”:”empty” should work at all because I think it’s an insane way to type a ternary :) I’m also very open to admitting that it’s just my own strongly worded opinion.

          I think that in most cases, syntactically significant whitespace is a horrible idea - the one exception being that you should have space between operators/identifiers/etc. I don’t care how much, and 4 spaces should have no more special meaning than 1, but I do think that using a space to indicate “this thing is a different thing than the thing before it” is important.

          • shagie@programming.dev
            link
            fedilink
            arrow-up
            2
            ·
            edit-2
            1 year ago

            Talking with a rubyist:

            • 3?"bar":"qux" only has the ternary expression as a valid parsing of ?
            • foo?"bar":"qux" fails because foo may be a method and foo? is also a valid method identifier.
            • foo ?"bar":"qux" fails because ?" uses the ? unary operator that makes the next character a string. So ?"bar" becomes the string " followed by what looks to be an identifier.

            And so…

            • ? character is a valid part of an identifier (but only at the end of a method name)
            • ?x unary operator to create a String from a character
            • expr?expr:expr ternary operator

            And so…

            puts "".empty? ? ?t:?f