gpt4 book ai didi

ruby-on-rails - 愚蠢的 block 中的 block rspec 测试

转载 作者:行者123 更新时间:2023-12-03 09:24:32 24 4
gpt4 key购买 nike

我进行了以下测试作为练习:

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

但是我对其中一些概念不太理解。例如:

  1. &block 参数中的 & 符号到底是什么意思?
  2. 同样,什么是 block.call?我假设它调用的实际 block 对象在哪里?
  3. 如果我想实现其他目标,理论上我可以使用另一种方法吗?
  4. 此外,我可以在哪里了解有关 block 的更多信息

这个练习有点超出我目前的知识。

最佳答案

  1. 这意味着“这是 block 参数”。您不必将其称为 &block,因此需要有一种方法将其与其他参数分开。使用相同的符号将参数作为 block 传递给函数,而不是普通参数(见下文)

  2. block.callyield 完全相同。不同之处在于,您可以使用 block 来访问 block 本身,而无需立即调用它。例如,您可以存储该 block 以供以后执行。这是一种称为惰性求值的常见模式。

  3. 是的,您还可以将 do/end block 以外的内容作为 &block 参数传递。请参阅下面的一些示例。

  4. @UriAgassi 为您提供了一个很好的链接。

以下是您可以作为 block 参数传递的其他一些内容。首先,只是一个简单的方法,拿一个 block 来进行演示:

def reverser(&block)
block.call.reverse
end

您现在可以传递标准 block

reverser do
"hello"
end
#=> "olleh"

或者,在替代 block 语法中,用于内联样式

reverser { "hello" }
#=> olleh

您还可以传递 lambda 或 proc,这与 block 类似。通过使用 &block 符号,您可以将变量作为 block 参数传递:

my_block = lambda { "hello world!" }
reverser(&my_block)
#=> "!dlrow olleh"

或者,使用替代的 lambda 语法

my_block = -> { "hello world!" }
reverser(&my_block)
#=> "!dlrow olleh"

您甚至可以采用现有方法并将其作为 block 参数传递在这里你可以看到 block 的巨大优势:它们被评估当执行 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

关于ruby-on-rails - 愚蠢的 block 中的 block rspec 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23751366/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com