Ruby中的代码块如何知道哪个变量属于对象的某个方面?
考虑以下几点:Ruby中的代码块如何知道哪个变量属于对象的某个方面?,ruby,Ruby,考虑以下几点: (1..10).inject{|memo, n| memo + n} 问题: n怎么知道它应该存储从1到10的所有值?我很困惑Ruby是如何理解n可以立即自动与(1..10)关联的,而memo就是memo 我知道Ruby代码块与C或Java代码块不同——Ruby代码块的工作方式有点不同。我不知道竖直的管道“|”之间的变量如何自动分配给对象的各个部分。例如: hash1 = {"a" => 111, "b" => 222} hash2 = {"b" => 333
(1..10).inject{|memo, n| memo + n}
问题:
n怎么知道它应该存储从1到10的所有值?我很困惑Ruby是如何理解n可以立即自动与(1..10)关联的,而memo就是memo
我知道Ruby代码块与C或Java代码块不同——Ruby代码块的工作方式有点不同。我不知道竖直的管道“|”之间的变量如何自动分配给对象的各个部分。例如:
hash1 = {"a" => 111, "b" => 222}
hash2 = {"b" => 333, "c" => 444}
hash1.merge(hash2) {|key, old, new| old}
“| key,old,new |”如何以这样的方式自动分配自己:当我在代码块中键入“old”时,它会自动意识到“old”是指旧的散列值?我从来没有给任何东西加上“old”,只是声明了它。有人能解释一下这是怎么回事吗
备忘录就是备忘录
“只是备忘录”是什么意思memo
和n
获取inject
传递的任何值。它的实现是将accumulator/memo作为第一个参数传递,将current collection元素作为第二个参数传递
“|键、旧键、新键”如何自动分配它们自己
他们不“分配自己”<代码>合并分配它们。或者更确切地说,将这些值(键、旧值、新值)按该顺序作为块参数传递
如果你改写
hash1.merge(hash2) {|foo, bar, baz| bar}
它仍能像以前一样正常工作。参数名称[此处]没有任何意义。重要的是实际值
备忘录就是备忘录
你什么意思,“只是备忘录”memo
和n
获取inject
传递的任何值。它的实现是将accumulator/memo作为第一个参数传递,将current collection元素作为第二个参数传递
“|键、旧键、新键”如何自动分配它们自己
他们不“分配自己”<代码>合并分配它们。或者,将这些值(键、旧值、新值)按该顺序作为块参数传递
如果你改写
hash1.merge(hash2) {|foo, bar, baz| bar}
它仍能像以前一样正常工作。参数名称[此处]没有任何意义。重要的是实际值。块的参数由方法定义确定。
reduce/inject
的定义是重载的()并在C中定义的,但是如果您想定义它,可以这样做(注意,对于实际的reduce
定义,这并不涵盖所有重载情况):
此方法定义确定要为memo
和element
使用哪些值,并按特定顺序调用blk
变量(传递给方法的块)
但是,请注意,块与常规方法不同,因为它们不检查参数的数量。例如:(注意,此示例显示了yield
的用法,这是传递块参数的另一种方式)
您还可以在运行块时使用解构来定义变量,例如,如果您想通过哈希减少,您可以执行以下操作:
# this just copies the hash
{a: 1}.reduce({}) { |memo, (key, val)| memo[key] = val; memo }
module Enumerable
def inject(memo)
each do |el|
memo = yield memo, el
end
memo
end
end
其工作原理是,对散列调用reduce
,隐式地调用到a
,从而将其转换为元组列表(例如{a:1}.to_a=[[:a,1]]
)reduce
将每个元组作为第二个参数传递给块。在调用块的地方,元组被分解为单独的键和值变量。块的参数由方法定义确定。reduce/inject
的定义是重载的()并在C中定义的,但是如果您想定义它,可以这样做(注意,对于实际的reduce
定义,这并不涵盖所有重载情况):
此方法定义确定要为memo
和element
使用哪些值,并按特定顺序调用blk
变量(传递给方法的块)
但是,请注意,块与常规方法不同,因为它们不检查参数的数量。例如:(注意,此示例显示了yield
的用法,这是传递块参数的另一种方式)
您还可以在运行块时使用解构来定义变量,例如,如果您想通过哈希减少,您可以执行以下操作:
# this just copies the hash
{a: 1}.reduce({}) { |memo, (key, val)| memo[key] = val; memo }
module Enumerable
def inject(memo)
each do |el|
memo = yield memo, el
end
memo
end
end
其工作原理是,对散列调用reduce
,隐式地调用到a
,从而将其转换为元组列表(例如{a:1}.to_a=[[:a,1]]
)reduce
将每个元组作为第二个参数传递给块。在调用块的地方,元组被分解为单独的键和值变量。这里只是为了简化一些其他好的答案:
如果您正在努力理解块,一种简单的方法是将它们视为您正在创建和执行的原始临时方法,管道字符|memo |
之间的值只是参数签名
参数背后没有特殊的概念,它们只是为您调用的方法传递变量而存在,就像用参数调用任何其他方法一样。与方法类似,参数是块范围内的“局部”变量(这有一些细微差别,取决于调用块时使用的语法,但我离题了,这是另一回事)
您将块传递给的方法只是调用这个“临时方法”,并将参数传递给它。就像通常调用方法一样,有一些细微的区别,比如没有“必需”参数。如果您没有定义任何要接收的参数,它将很高兴地不传递它们,而不是引发ArgumentError
。同样,如果您为块定义了太多的参数而无法接收,那么它们将被忽略