我作为练习给了我以下测试:
require "silly_blocks"
describe "some silly block functions" do
describe "reverser" do
it "reverses the string returned by the default block" do
result = reverser do
"hello"
end
result.should == "olleh"
end
it "reverses each word in the string returned by the default block" do
result = reverser do
"hello dolly"
end
result.should == "olleh yllod"
end
end
describe "adder" do
it "adds one to the value returned by the default block" do
adder do
5
end.should == 6
end
it "adds 3 to the value returned by the default block" do
adder(3) do
5
end.should == 8
end
end
describe "repeater" do
it "executes the default block" do
block_was_executed = false
repeater do
block_was_executed = true
end
block_was_executed.should == true
end
it "executes the default block 3 times" do
n = 0
repeater(3) do
n += 1
end
n.should == 3
end
it "executes the default block 10 times" do
n = 0
repeater(10) do
n += 1
end
n.should == 10
end
end
end
我能够使用以下代码解决它们:
def reverser
k = []
x = yield.split(" ")
x.each do |y|
n = y.reverse
k.push(n)
end
m = k.join(" ")
m
end
def adder(num=1, &block)
block.call + num
end
def repeater(num=1, &block)
for i in (1..num) do
block.call
end
end
然而,我对其中的一些概念并不了解。例如:
这项练习有点高于我目前的知识。
答案 0 :(得分:3)
这意味着"这是块参数"。您不必将其称为&block
,因此需要有一种方法将其与其他参数分开。相同的表示法用于将参数作为块传递给块而不是普通参数(见下文)
block.call
与yield
完全相同。不同之处在于您可以使用block
来访问块本身而无需立即调用它。例如,您可以存储块以供以后执行。这是一种常见的模式,称为懒惰评估。
是的,您还可以传递与do
/ end
块不同的内容作为&block
参数。请参阅下面的一些示例。
@UriAgassi为您提供了一个很好的链接。
以下是您可以作为块参数传递的其他一些内容。首先,只是一个简单的方法,用于演示:
def reverser(&block)
block.call.reverse
end
您现在可以传递标准块
reverser do
"hello"
end
#=> "olleh"
或者,在替代块语法中,用于内联样式
reverser { "hello" }
#=> olleh
您还可以传递lambda或proc,它类似于块。 通过使用&块表示法,您可以将变量作为块参数传递:
my_block = lambda { "hello world!" }
reverser(&my_block)
#=> "!dlrow olleh"
或者,替代lambda语法
my_block = -> { "hello world!" }
reverser(&my_block)
#=> "!dlrow olleh"
您甚至可以使用现有方法并将其作为块参数传递 在这里你可以看到块的巨大优势:它们被评估 执行block.call时,而不是加载代码时。在这里 意味着字符串每次都会相应改变。
def foobar
"foobar at #{Time.now}"
end
reverser(&method(:foobar))
#=> "0020+ 15:42:90 02-50-4102 ta raboof"
#=> "0020+ 31:52:90 02-50-4102 ta raboof"
你可以用这个来做很酷的事情,例如:
[1, 2, 3].each(&method(:puts))
1
2
3
#=> [1, 2, 3]
但请记住,不要过分,Ruby就是表达性和可读性的代码。在增强代码时使用这些技术,但如果可能,请使用更简单的方法。
最后,这里也是一个懒惰评估的例子:
class LazyReverser
def initialize(&block)
@block = block
end
def reverse
@block.call.reverse
end
end
reverser = LazyReverser.new do
# some very expensive computation going on here,
# maybe we do not even need it, so lets use the
# lazy reverser!
"hello dolly"
end
# now go and do some other stuff
# it is not until later in the program, that we can decide
# whether or not we even need to call the block at all
if some_condition
reverser.reverse
#=> "yllod olleh"
else
# we did not need the result, so we saved ourselves
# the expensive computation in the block altogether!
end