在rspec上下文中解释procs的用法

时间:2015-07-19 13:22:51

标签: ruby rspec proc

这是一个利用自定义RSpec匹配器yield_variables:

的期望
specify { expect{ |p| [3,4,5].my_each(&p) }.to yield_variables [3,4,5] }

我的yield_variables匹配器的匹配?方法使用一个名为Probe的自定义类(Probe是RSpec' s yield probe的精简版):

...
    def matches? block
        ap Probe.probe block
        # note i am inspecting what is returned by Probe.probe with ap
    end
...


# Probe class is what all my questions are about!
class Probe
    attr_accessor :yielded_args
    def initialize
        self.yielded_args = []
    end

    def self.probe(block)
        probe = new
        block.call(probe)
        probe.yielded_args
    end

    def to_proc
        Proc.new { |*args| yielded_args << args }
    end
end

现在我在matches?内的ap报告了这个:[3,4,5]这就是我的期望。但是,我不知道Probe类是如何工作的!

问题1)比赛?块

通常,我们传递的参数匹配?是我们期望主题回归的。即,我希望将[3,4,5]传递给阻止。 相反,|p| [3,4,5].my_each(&p)作为proc传递到块中。这是为什么?

问题2) block.call(探测)

我对触发器有点不确定所以请慢慢解释。但基本上,我们在这里采用我的Probe类的一个新实例并且发送&#39;它的块,作为一个论点。这就是我如何尽我所能解释它,但我可能完全错了,所以请慢慢解释。

问题3)如何调用to_proc?

如何自动调用.to_proc?我相信它会被block.call(探测器)自动调用。 to_proc是一个自动调用的方法,比如initialize?每当将类发送到proc时它会自动调用吗? (顺便说一句,这个类被发送到一个proc的短语对我来说甚至没有任何意义 - 请解释一下。该块不再作为参数传递给该类。或者如果该块被传递作为一个参数,block.call语法感觉非常奇怪和倒退)

问题4) to_proc

to_proc如何访问期望主题,即|p| [3,4,5].my_each(&p)? Proc.new&#39; s * args如何自动填充每一个可能的yield参数,即使我只传入了| p | ? Proc.new如何与my_each一起循环,逐步将我的所有args放在一个数组中? Proc.new如何知道主题|p| [3,4,5].my_each(&p)?怎么样??请解释一下,谢谢。

1 个答案:

答案 0 :(得分:2)

基于块的游行者与其他游戏玩家的工作方式略有不同。通常,如果评估了您感兴趣的表达式并将结果传递给您,您通常会做一些无法实现的事情。

例如,raises_error匹配器想要执行块本身以查看是否引发了正确的异常,并且change匹配器想要在之前和之后评估其他表达式,以查看它是否在指定的方式。这就是你传递一个块而不是值的原因。

您传递给expect的块接受1个参数,并将其用作my_each调用中的块,因此当您的Probe.probe方法调用块时,它必须传递一些内容作为值。你的措辞是“将块发送到探测器实例”,但它是另一种方式:使用probe作为参数调用块。

该块执行并调用my_each。在此处pProbe的实例。使用&amp;前缀参数告诉ruby这个参数应该用作方法的块(方法是my_each)。如果参数不是proc ruby​​,则调用to_proc。这就是Probe#to_proc的调用方式

假设my_each的行为与普通each类似,它将为数组中的每个值调用其块(即to_proc的返回值)。< / p>

通常,您的匹配器会将Probe.probe的返回值与实际值进行比较。