What's the difference of statement and expression in Ruby?
Asked Answered
L

4

12

I know in Ruby, almost everything is an expression. Even those in other language such as if-else statement, case statement, assignment statement, loop statement is an expression in Ruby.

So I want to know from the Ruby's point of view, what's the difference between statement and expression?

Lindbom answered 9/3, 2012 at 15:21 Comment(1)
As you noticed correctly, there are no statements in Ruby, so the question doesn't really make sense.Mireielle
H
5

There is no difference between expressions and statement is Ruby. Everything evaluates to a value so everything is an expression.

Haworth answered 9/3, 2012 at 15:31 Comment(2)
There is a difference. a if b is a statement, but (a if b) becomes an expression. The consequence is that puts(a if b) is a SyntaxError but puts((a if b)) is ok, because method arguments must be expressions.Gilges
Thanks fro the comment, @Gilges I wasn't aware of this subtlety.Haworth
B
3

From Ruby hacking guide:

Also, function and class definitions are typically statements however in languages such as Lisp and Scheme, since everything is an expression, they do not have statements in the first place. Ruby is close to Lisp’s design in this regard.

These are the statement's grammar rules, where you can see (sort of) what is a statement in the language implementation. Notice the expr rule that means that a stmnt could be an expr. An expr could not be a stmt.

stmt        : kALIAS fitem  fitem
            | kALIAS tGVAR tGVAR
            | kALIAS tGVAR tBACK_REF
            | kALIAS tGVAR tNTH_REF
            | kUNDEF undef_list
            | stmt kIF_MOD expr_value
            | stmt kUNLESS_MOD expr_value
            | stmt kWHILE_MOD expr_value
            | stmt kUNTIL_MOD expr_value
            | stmt kRESCUE_MOD stmt
            | klBEGIN ‘{’ compstmt ‘}’
            | klEND ‘{’ compstmt ‘}’
            | lhs ‘=’ command_call
            | mlhs ‘=’ command_call
            | var_lhs tOP_ASGN command_call
            | primary_value ‘[’ aref_args ‘]’ tOP_ASGN command_call
            | primary_value ‘.’ tIDENTIFIER tOP_ASGN command_call
            | primary_value ‘.’ tCONSTANT tOP_ASGN command_call
            | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
            | backref tOP_ASGN command_call
            | lhs '=' mrhs_basic
            | mlhs '=' mrhs
            | expr
Bendix answered 6/6, 2016 at 5:16 Comment(2)
I'm surprised to see assignment here, since 1+(a=2) appears to be valid (irb 0.9.6 and ruby 2.3.7p456).Hatband
Only assignments with a command_call, like x = foo 2, but x = foo(2) is not a statement.Gilges
G
3

There is a difference. It's a subtle but important one. An expression is a type of statement. All expressions are statements but not all statements are expressions.

Most notably, statements that are not expressions include:

stmt if expr
stmt unless expr
stmt while expr
stmt until expr
stmt rescue expr
var = method expr
x,y = expr

When used as a modifier, if, else, while, until and rescue become statements, not expressions. This means they cannot be used in contexts where an expression is expected, such as method arguments. Wrap with parentheses to create an expression.

  puts( 1 if true )      #=> SyntaxError
  puts((1 if true))      #=> 1
  puts (1 if true)       #=> 1, because of optional parentheses for method

  puts( 1 rescue true )  #=> SyntaxError
  puts((1 rescue true))  #=> 1
  puts (1 rescue true)   #=> 1, because of optional parentheses for method

The right-hand side of a modifier statement is also one of those contexts where an expression is expected. So in a if b rescue c, because b rescue c is a statement and therefore not allowed as the condition of the if statement, the code is necessarily parsed as (a if b) rescue c.

This interacts with operator precedence in such a way that:

 stmt if v = expr rescue x
 stmt if     expr rescue x
 stmt if v = expr unless x
 stmt if     expr unless x

are parsed as:

 stmt if v = (expr rescue x)
 (stmt if     expr) rescue x
 (stmt if v = expr) unless x
 (stmt if     expr) unless x
Gilges answered 9/8, 2019 at 19:11 Comment(0)
C
2

Think of the expressions as small parts of a sentence. Think of the statement as that completed sentence or thought. One line in your method or loop could be an expression, and the conglomeration of those expressions into a closed loop or method could be thought of as a statement.

This is more or less conceptually subjective. As Niklas B. correctly pointed out (and you correctly noticed).

Is there an issue that you are dealing directly that made you look into this?

You'll also hear people say "everything in ruby is an object" more than everything is an expression.

Chine answered 9/3, 2012 at 15:34 Comment(1)
I'd say that the main conceptual difference is whether the value of something is used or discarded.Mireielle

© 2022 - 2024 — McMap. All rights reserved.