Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
671 views
in Technique[技术] by (71.8m points)

syntax - In Ruby, why is a method invocation not able to be treated as a unit when "do" and "end" is used?

The following question is related to the question "Ruby Print Inject Do Syntax". My question is, can we insist on using do and end and make it work with puts or p?

This works:

a = [1,2,3,4]

b = a.inject do |sum, x|
  sum + x
end
puts b   # prints out 10

so, is it correct to say, inject is an instance method of the Array object, and this instance method takes a block of code, and then returns a number. If so, then it should be no different from calling a function or method and getting back a return value:

b = foo(3)
puts b

or

b = circle.getRadius()
puts b

In the above two cases, we can directly say

puts foo(3)
puts circle.getRadius()

so, there is no way to make it work directly by using the following 2 ways:

a = [1,2,3,4]

puts a.inject do |sum, x|
  sum + x
end

but it gives

ch01q2.rb:7:in `inject': no block given (LocalJumpError)
        from ch01q2.rb:4:in `each'
        from ch01q2.rb:4:in `inject'
        from ch01q2.rb:4

grouping the method call using ( ) doesn't work either:

a = [1,2,3,4]

puts (a.inject do |sum, x| 
        sum + x   
      end)

and this gives:

ch01q3.rb:4: syntax error, unexpected kDO_BLOCK, expecting ')'
puts (a.inject do |sum, x|
                 ^
ch01q3.rb:4: syntax error, unexpected '|', expecting '='
puts (a.inject do |sum, x|
                          ^
ch01q3.rb:6: syntax error, unexpected kEND, expecting $end
      end)
         ^

finally, the following version works:

a = [1,2,3,4]

puts a.inject { |sum, x|
    sum + x
}

but why doesn't the grouping of the method invocation using ( ) work in the earlier example? What if a programmer insist that he uses do and end, can it be made to work?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

From the (unofficial) ruby grammar, we see that the contents of (...) in puts (...) must be CALL_ARGS, which don't directly reduce to STMT. However, they can reduce to '(' COMPSTMT ')'. By including an extra set of parentheses, you can use do ... end.

a = [1,2,3,4]

puts ((a.inject do |sum, x| 
         sum + x   
       end))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...