Reputation:
A single space affects the value returned by *
:
rand * 10 #=> 2.7177010707339146
rand *10 #=> 1
I tried to use Ripper to check the tokens produced by those two expressions.
Ripper.lex 'rand *10'
#=> [[[1, 0], :on_ident, "rand", EXPR_CMDARG],
# [[1, 4], :on_sp, " ", EXPR_CMDARG],
# [[1, 5], :on_op, "*", EXPR_BEG],
# [[1, 6], :on_int, "10", EXPR_END|EXPR_ENDARG]]
Ripper.lex 'rand * 10'
#=> [[[1, 0], :on_ident, "rand", EXPR_CMDARG],
# [[1, 4], :on_sp, " ", EXPR_CMDARG],
# [[1, 5], :on_op, "*", EXPR_BEG],
# [[1, 6], :on_sp, " ", EXPR_BEG],
# [[1, 7], :on_int, "10", EXPR_END|EXPR_ENDARG]]
Except for the second to the fourth element, I see no differences. I thought that the constants on the right would change somehow.
Now with sexp
:
Ripper.sexp 'rand *10'
#=> [:program,
# [[:command,
# [:@ident, "rand", [1, 0]],
# [:args_add_block, [:args_add_star, [], [:@int, "10", [1, 6]]], false]]]]
Ripper.sexp 'rand * 10'
#=> [:program,
# [[:binary, [:vcall, [:@ident, "rand", [1, 0]]], :*, [:@int, "10", [1, 7]]]]]
One can see there is a big difference.
How and why is it that the expressions return a different value?
Upvotes: 1
Views: 258
Reputation: 96934
The *
in *10
is the unary splat operator, whereas in * 10
it is an overridable binary operator (in this case resolving to Float#*
). We can see from the AST as well that, adding parenthesis, the expressions’ equivalencies are:
rand *10
is the same as rand(*10)
is the same as rand(10)
.rand * 10
is the same as (rand) * (10)
is the same as rand.*(10)
.This can also be confirmed at runtime:
def args(*args); p args; end
args *10 # prints [10]
args * 10 # prints []
Upvotes: 3