admin管理员组文章数量:1122832
I am trying to understand how this piece of ruby works. (Please forgive me if it's been asked before but I could not find anything here or on ruby-lang documents.)
The code is:
some_method do
# lines that look like parameters; e.g.
[val1, val2, val3]
end
where some_method
seems to create a hash using val1
, val2
, and val3
as keys.
Would this be the same as
some_method([val1, val2, val3])
I am trying to understand how this piece of ruby works. (Please forgive me if it's been asked before but I could not find anything here or on ruby-lang.org documents.)
The code is:
some_method do
# lines that look like parameters; e.g.
[val1, val2, val3]
end
where some_method
seems to create a hash using val1
, val2
, and val3
as keys.
Would this be the same as
some_method([val1, val2, val3])
Share
Improve this question
edited Dec 16, 2024 at 16:53
user513951
13.6k7 gold badges70 silver badges89 bronze badges
asked Nov 22, 2024 at 18:46
Colin WuColin Wu
6991 gold badge8 silver badges25 bronze badges
3
|
2 Answers
Reset to default 4When you call a method in Ruby you can pass a block and if the method expects the block it can execute it.
In the code below some_method
checks if a block was received (block_given?
) and then executes it (yield
):
def some_method
puts "hello"
if block_given?
x = yield
puts x
end
puts "bye"
end
puts "example one - no block given"
some_method()
puts "example two - block given"
some_method() do
1 + 2
end
Passing a block (via do
) is not the same as passing the parameters as values. Passing a block allows the method do execute any arbitrary piece of code defined in the block. In the example above I just do a simple math operation (1+2
) but the block could have called another function, or read from a database, or anything.
Would this be the same
Not automatically, no.
Let's examine how both versions would normally work, and then we can construct a version that allows them to operate the same.
To achieve the result
some_method
… creates a hash usingval1
,val2
, andval3
as keys
from the code you supplied, the method definition would look like something this:
def some_method
# Get the return value from the block, e.g. [val1, val2, val3]
array = yield
# Generate a hash using the array elements as keys.
# The right-hand values here are just numbers counting up from zero.
array.zip(array.length.times.map).to_h
end
Here's what happens when you call this method as in your first code block:
val1, val2, val3 = :val1, :val2, :val3
result = some_method do
[val1, val2, val3]
end
puts result
# => { val1: 0, val2: 1, val3: 2 }
Your second code block results in the error ArgumentError (wrong number of arguments (given 1, expected 0))
, because some_method
does not take any positional arguments.
If you wanted to write some_method
to produce the same result for the second code block, it would look like this:
def some_method(array)
array.zip(array.length.times.map).to_h
end
The difference is where the value array
comes from. In the first def
, it comes from the result of the block, obtained by calling yield
. In the second def
, it comes from the argument passed in as array
.
If you wanted a single method that would work either way, it might look like this:
def some_method(array=nil)
if array.nil? && block_given?
array = yield
end
if array
array.zip(array.length.times.map).to_h
end
end
This works because it first checks whether an array was passed as a regular argument, and uses it if so (ignoring any block given without even executing it, incidentally).
If no array was passed and a block was given, it uses the result of the block instead. If neither was given, it returns nil.
There are other, more complete ways to implement this (see comments, or answers to this question), but hopefully this sample implementation makes it clear that extra work is needed to achieve the behavior you asked about.
I can't find any explicit coverage of how yield
works at ruby-lang.org, but blocks are covered here and block_given?
is here. Here is a very old explanation of yield
, but it's still accurate.
本文标签: methodsWhat39s the difference between passing an argument and passing a block in RubyStack Overflow
版权声明:本文标题:methods - What's the difference between passing an argument and passing a block in Ruby? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736301513a1931201.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
some_method
accepts a block, technically all ruby methods do, regardless of whether or not it is acknowledged. Whatsome_method
does from there no one can say. Ifsome_method
also accepts an argument then it is possible that the 2 are equivalent ifsome_method
uses the result of the block evaluation the same way it uses the argument but again no one can say based on the question. Please provide a specific example of thesome_method
in question and then maybe we can answer the questions posed. – engineersmnky Commented Nov 22, 2024 at 19:05