以下是扫描示例:
"abcdeabcabc".scan("a")
所以它返回一个3 a的数组。另一个扫描示例:
"abcdeabcabc".scan("a") {|x| puts x}
只输出每个“a”,但仍然输出一个数组,这次它实际上是它返回的原始字符串。
因此,从上面的文档和行为中,扫描要么返回一个数组(没有给出块),要么返回原始字符串,在此之前会发生一些副作用。关键是这两种情况都会返回一些东西。
那么如果我在块内放一个“收益”会发生什么?什么将被退回?或者,没有? 返回值的类型是什么?
"abcdeabcabc".scan("a") {|x| yield x}
以上内容不起作用,因为Ruby抱怨没有给出阻止。这对我来说很有意义。但如果它是类方法的一部分,比如说,自我实现的“每个”,则以下工作:
class Test
def my_each
"abcdeabcabc".scan("a") {|x| yield x}
end
end
# => :my_each
t = Test.new
# => #<Test:0x007ff00a8d79b0>
t.my_each {|x| puts "so this is #{x}"}
# it works. Outpus 3 a's then return the original string.
那么,Test类的my_each方法的返回值是多少?这是收益率列表还是什么?但正如之前所讨论的“abcdeabcabc”.scan(“a”){| x |在给出一个块之前,Ruby会抱怨yield x}段。内部发生了什么事情,将my_each的块提供给my_each实现中的段?
答案 0 :(得分:2)
该块与该函数的参数类似地传递。这可以明确指定,如下所示:
class Test
def my_each(&block)
"abcdeabcabc".scan("a") do |x|
puts "!!! block"
yield x
# Could be replaced with: block.call(x)
end
end
end
从技术上讲,它完全相同(puts
放在那里进行澄清),它的存在不会像通常对参数那样进行检查。如果你忘记给它一个块,函数将停止在它必须以完全相同的yield
执行的第一个LocalJumpError
(至少,这是我在Rubinius上得到的)。但是,请注意控制台中的“!!! block”。
这样做是有原因的。您可以使用if block
检查您的函数是否被赋予块,如果是如上所述,使用yield
,然后跳过content_tag
。一个很好的例子是Rails的content_tag :div do
content_tag :div
end
帮助器。这个助手的调用可以是块嵌套的。一个简单的例子:
<div>
<div></div>
</div>
...产生如下输出:
yield
因此,该块在您的方法的“顶部”(就调用堆栈而言)执行。每次Enumerator
发生时都会调用它作为块上的某种函数调用。之后执行该块时,它不会累积在任何地方。
UPD:
许多each
es返回的my_each
由许多迭代器显式构造,以保存应该发生的事件的上下文。
可以在class Test
def my_each(&block)
if block
"abcdeabcabc".scan("a") { |x| yield x }
else
Enumerator.new(self, :my_each)
end
end
end
:
{{1}}
答案 1 :(得分:1)
由于块被赋予scan
,因此返回原始字符串。在块内做什么并不重要。
答案 2 :(得分:0)
"abcdeabcabc".scan("a") {|x| yield x}
在上述情况下,#scan
将每个匹配的字符传递给与其关联的块。
现在在#scan
的块中,您正在调用yield
,然后调用传递给方法my_each
的块。 x
的值将传递给您通过方法my_each
调用传递的块。
这太简单了,没有混淆。
Test类的my_each方法的返回值是什么?
根据您当前的代码,返回值应该是#scan
方法返回值,这又会导致最后一个语句的结果与调用方法#my_each
的方法#scan
(如果被调用)或接收器相关联的块。
这是一份收益清单还是什么?
是的,yield
将被调用,因为#scan
方法可以找到多个匹配项。
考虑以下示例: -
"abcdeabcabc".scan("w") {|x| yield x}
此处与方法#scan
相关联的块将不会被调用,因为#scan
找不到任何匹配项,这就是为什么yield
不会也被调用,因此方法#my_each
不会输出块表达式(与方法一起传递)结果,但是"abcdeabcabc"
。