diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/keywords.rdoc | 4 | ||||
-rw-r--r-- | doc/syntax/control_expressions.rdoc | 62 | ||||
-rw-r--r-- | doc/syntax/precedence.rdoc | 6 |
3 files changed, 67 insertions, 5 deletions
diff --git a/doc/keywords.rdoc b/doc/keywords.rdoc index 98bbd5e864..b2f72da272 100644 --- a/doc/keywords.rdoc +++ b/doc/keywords.rdoc @@ -76,7 +76,7 @@ for:: expressions}[rdoc-ref:syntax/control_expressions.rdoc] if:: - Used for +if+ and modifier +if+ expressions. See {control + Used for +if+ and modifier +if+ statements. See {control expressions}[rdoc-ref:syntax/control_expressions.rdoc] in:: @@ -137,7 +137,7 @@ undef:: See {modules and classes}[rdoc-ref:syntax/modules_and_classes.rdoc] unless:: - Used for +unless+ and modifier +unless+ expressions. See {control + Used for +unless+ and modifier +unless+ statements. See {control expressions}[rdoc-ref:syntax/control_expressions.rdoc] until:: diff --git a/doc/syntax/control_expressions.rdoc b/doc/syntax/control_expressions.rdoc index 65f7b431e3..f7e6d54924 100644 --- a/doc/syntax/control_expressions.rdoc +++ b/doc/syntax/control_expressions.rdoc @@ -144,7 +144,7 @@ expression. == Modifier +if+ and +unless+ +if+ and +unless+ can also be used to modify an expression. When used as a -modifier the left-hand side is the "then" expression and the right-hand side +modifier the left-hand side is the "then" statement and the right-hand side is the "test" expression: a = 0 @@ -164,7 +164,7 @@ This will print 1. This will print 0. While the modifier and standard versions have both a "test" expression and a -"then" expression, they are not exact transformations of each other due to +"then" statement, they are not exact transformations of each other due to parse order. Here is an example that shows the difference: p a if a = 0.zero? @@ -439,6 +439,64 @@ longer true, now you will receive a SyntaxError when you use +retry+ outside of a +rescue+ block. See {Exceptions}[rdoc-ref:syntax/exceptions.rdoc] for proper usage of +retry+. +== Modifier Statements + +Ruby's grammar differentiates between statements and expressions. All +expressions are statements (an expression is a type of statement), but +not all statements are expressions. Some parts of the grammar accept +expressions and not other types of statements, which causes code that +looks similar to be parsed differently. + +For example, when not used as a modifier, +if+, +else+, +while+, +until+, +and +begin+ are expressions (and also statements). However, when +used as a modifier, +if+, +else+, +while+, +until+ and +rescue+ +are statements but not expressions. + + if true; 1 end # expression (and therefore statement) + 1 if true # statement (not expression) + +Statements that are not expressions cannot be used in contexts where an +expression is expected, such as method arguments. + + puts( 1 if true ) #=> SyntaxError + +You can wrap a statement in parentheses to create an expression. + + puts((1 if true)) #=> 1 + +If you put a space between the method name and opening parenthesis, you +do not need two sets of parentheses. + + puts (1 if true) #=> 1, because of optional parentheses for method + +This is because this is parsed similar to a method call without +parentheses. It is equivalent to the following code, without the creation +of a local variable: + + x = (1 if true) + p x + +In a modifier statement, the left-hand side must be a statement and the +right-hand side must be an expression. + +So in <code>a if b rescue c</code>, because <code>b rescue c</code> is a +statement that is not an expression, and therefore is not allowed as the +right-hand side of the +if+ modifier statement, the code is necessarily +parsed as <code>(a if b) rescue c</code>. + +This interacts with operator precedence in such a way that: + + stmt if v = expr rescue x + stmt if v = expr unless x + +are parsed as: + + stmt if v = (expr rescue x) + (stmt if v = expr) unless x + +This is because modifier +rescue+ has higher precedence than <code>=</code>, +and modifier +if+ has lower precedence than <code>=</code>. + == Flip-Flop The flip-flop is a rarely seen conditional expression. It's primary use is diff --git a/doc/syntax/precedence.rdoc b/doc/syntax/precedence.rdoc index 515626c74f..f64691ab1f 100644 --- a/doc/syntax/precedence.rdoc +++ b/doc/syntax/precedence.rdoc @@ -49,10 +49,14 @@ Unary <code>+</code> and unary <code>-</code> are for <code>+1</code>, <code>-1</code> or <code>-(a + b)</code>. Modifier-if, modifier-unless, etc. are for the modifier versions of those -keywords. For example, this is a modifier-unless expression: +keywords. For example, this is a modifier-unless statement: a += 1 unless a.zero? +Note that <code>(a if b rescue c)</code> is parsed as <code>((a if b) rescue +c)</code> due to reasons not related to precedence. See {modifier +statements}[control_expressions_rdoc.html#label-Modifier+Statements]. + <code>{ ... }</code> blocks have priority below all listed operations, but <code>do ... end</code> blocks have lower priority. |