2

I am new to Ruby and a bit confused about how the ternary operator, ?:, works.

According to the book Engineering Software as a Service: An Agile Approach Using Cloud Computing:

every operation is a method call on some object and returns a value.

In this sense, if the ternary operator represents an operation, it is a method call on an object with two arguments. However, I can't find any method of which the ternary operator represents in Ruby's documentation. Does a ternary operator represent an operation in Ruby? Is the above claim made by the book mentioned wrong? Is the ternary operator in Ruby really just a syntactic sugar for if ... then ... else ... end statements?

Please note: My question is related to How do I use the conditional operator (? :) in Ruby? but not the same as that one. I know how to use the ternary operator in the way described in that post. My question is about where ternary operator is defined in Ruby and if the ternary operator is defined as a method or methods.

Stefan
  • 96,300
  • 10
  • 122
  • 186
Isaac To
  • 537
  • 2
  • 11
  • 1
    Possible duplicate of [How do I use the conditional operator (? :) in Ruby?](https://stackoverflow.com/questions/4252936/how-do-i-use-the-conditional-operator-in-ruby) – Elliott Frisch Aug 26 '18 at 03:26
  • @ElliottFrisch My question is related to that one but not the same as that one. I know how to use the `ternary operator` in the way described in that post. My question is about where `ternary operator` is defined in Ruby and if the `ternary operator` is defined as a method or methods. – Isaac To Aug 26 '18 at 03:34
  • 1
    This table may be useful. Not all operators in Ruby are methods on an object. https://www.techotopia.com/index.php/Ruby_Operator_Precedence#Operator_Precedence_Table – Marc Baumbach Aug 26 '18 at 03:44
  • @MarcBaumbach According to that table, the ternary operator is not implemented as a method. I guess the claim in the book I read is wrong. What do you think? Do you think I interpreted the claim in the book incorrectly? – Isaac To Aug 26 '18 at 03:50
  • 1
    I don't think you're interpreting it incorrectly, I think the book is incorrect or not specific enough. Generally speaking, Ruby does treat nearly everything as an object where other languages typically don't. `nil` being a great example. – Marc Baumbach Aug 26 '18 at 04:06
  • @candleindark as opposed to the other operators, `?:` doesn't have a receiver. Which object should implement that method? – Stefan Aug 27 '18 at 07:42
  • @Stefan That's actually part of my question. I didn't know if `?:` is implemented as a method, and if it is, which class(es) the method is defined in. – Isaac To Aug 27 '18 at 20:26

2 Answers2

8

Is the ternary operator in Ruby really just a syntactic sugar for if ... then ... else ... end statements?

Yes.

From doc/syntax/control_expressions.rdoc

You may also write a if-then-else expression using ? and :. This ternary if:

input_type = gets =~ /hello/i ? "greeting" : "other"

Is the same as this if expression:

input_type =
  if gets =~ /hello/i
    "greeting"
  else
    "other"
  end

"According to this book, "every operation is a method call on some object and returns a value." In this sense, if the ternary operator represents an operation, it is a method call on an object with two arguments."

if, unless, while, and until are not operators, they are control structures. Their modifier versions appear in the operator precedence table because they need to have precedence in order to be parsed. They simply check if their condition is true or false. In Ruby this is simple, only false and nil are false. Everything else is true.

Operators are things like !, +, *, and []. They are unary or binary. You can see a list of them by calling .methods.sort on various objects. For example...

2.4.3 :004 > 1.methods.sort
 => [:!, :!=, :!~, :%, :&, :*, :**, :+, :+@, :-, :-@, :/, :<, :<<, :<=, :<=>, :==, :===, :=~, :>, :>=, :>>, :[], :^, :__id__, :__send__, etc...

Note that in Smalltalk, from which Ruby borrows heavily, everything really is a method call. Including the control structures.

Schwern
  • 127,817
  • 21
  • 150
  • 290
  • The Smalltalk origins and link are very interesting and much appreciated. – Sagar Pandya Aug 26 '18 at 13:38
  • 1
    It's debatable whether `__send__` is an operator. I'd say it's just a method. – Stefan Aug 27 '18 at 09:36
  • @Stefan It seems you're correct. I thought all method calls invoked `__send__`. – Schwern Aug 27 '18 at 19:33
  • @Schwern Thank you for the answer. Now, I know that `?:` is not implemented by a method. However, I am a bit confused about the last part of your post. Isn't `?:` an operator in Ruby though it is not implemented by a method? `.methods` on an object returns a list consisting only of entities that are implemented as a method. – Isaac To Aug 27 '18 at 21:02
  • @candleindark ["Operators"](https://en.wikipedia.org/wiki/Operator_(computer_programming)) are basically function calls with special syntax. While it's called the ternary "operator", `?:` fits the definition of ["control structure"](https://en.wikipedia.org/wiki/Control_flow) better; it controls which code is executed next. Adding to the terminology confusion, since Ruby's `if` returns a value (this is unusual) it is an ["expression"](https://en.wikipedia.org/wiki/Expression_(computer_science)) like `?:`. – Schwern Aug 27 '18 at 22:02
  • 1
    @Schwern I agree with you that `?:` is a good fit for control structure in Ruby. However, after learning much from you and the others in this post, I would still regard `?:` as an operator for two reasons. 1. The fact that `?:` controls the flow of execution shouldn't disqualify it as an operation. (`||` does as well in Ruby; `?:` and `||` do as well in C.) 2. `?:` has a precedence in relation to other operators in Ruby. Our disagreement is really just terminological. Thank you for the help. – Isaac To Aug 27 '18 at 23:13
  • @IsaacTo operators and methods are different things. There are operators which result in method calls like `+`, `< – Stefan Aug 28 '18 at 07:11
3

Is the ternary operator in Ruby really just a syntactic sugar for if ... then ... else ... end statements?

(another) yes.

Here's the parse tree for a ? b : c:

$ ruby --dump=parsetree -e 'a ? b : c'
###########################################################
## Do NOT use this node dump for any purpose other than  ##
## debug and research.  Compatibility is not guaranteed. ##
###########################################################

# @ NODE_SCOPE (line: 1)
# +- nd_tbl: (empty)
# +- nd_args:
# |   (null node)
# +- nd_body:
#     @ NODE_PRELUDE (line: 1)
#     +- nd_head:
#     |   (null node)
#     +- nd_body:
#     |   @ NODE_IF (line: 1)
#     |   +- nd_cond:
#     |   |   @ NODE_VCALL (line: 1)
#     |   |   +- nd_mid: :a
#     |   +- nd_body:
#     |   |   @ NODE_VCALL (line: 1)
#     |   |   +- nd_mid: :b
#     |   +- nd_else:
#     |       @ NODE_VCALL (line: 1)
#     |       +- nd_mid: :c
#     +- nd_compile_option:
#         +- coverage_enabled: false

Here's the parse tree for if a then b else c end:

$ ruby --dump=parsetree -e 'if a then b else c end'
###########################################################
## Do NOT use this node dump for any purpose other than  ##
## debug and research.  Compatibility is not guaranteed. ##
###########################################################

# @ NODE_SCOPE (line: 1)
# +- nd_tbl: (empty)
# +- nd_args:
# |   (null node)
# +- nd_body:
#     @ NODE_PRELUDE (line: 1)
#     +- nd_head:
#     |   (null node)
#     +- nd_body:
#     |   @ NODE_IF (line: 1)
#     |   +- nd_cond:
#     |   |   @ NODE_VCALL (line: 1)
#     |   |   +- nd_mid: :a
#     |   +- nd_body:
#     |   |   @ NODE_VCALL (line: 1)
#     |   |   +- nd_mid: :b
#     |   +- nd_else:
#     |       @ NODE_VCALL (line: 1)
#     |       +- nd_mid: :c
#     +- nd_compile_option:
#         +- coverage_enabled: false

They are identical.

In many languages ?: is an expression whereas if-then-else is a statement. In Ruby, both are expressions.

Stefan
  • 96,300
  • 10
  • 122
  • 186