Ruby on rails 傻块中的块rspec测试

Ruby on rails 傻块中的块rspec测试,ruby-on-rails,ruby,methods,block,Ruby On Rails,Ruby,Methods,Block,作为练习,我接受了以下测试: 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

作为练习,我接受了以下测试:

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, 2, 3].each(&method(:puts))
1
2
3
#=> [1, 2, 3]
  • &block参数中的&symbol的确切含义是什么
  • 类似地,什么是block.call,我假设调用的实际块对象在哪里
  • 如果我想实现其他目标,理论上我可以在block上使用另一种方法吗
  • 我在哪里可以学到更多关于积木的知识
  • 这个练习比我现在所知道的要高得多

  • 它的意思是“这是块参数”。您不必调用它
    &block
    ,因此需要有一种方法将它与其他参数分开。与普通参数不同,相同的符号用于将参数作为块传递给函数(见下文)

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

  • 是的,您还可以将不同于
    do
    /
    end
    块的内容作为
    &block
    参数传递。参见下面的一些示例

  • @乌里加西给了你一个很好的链接

  • 这里还有一些可以作为块参数传递的其他内容。首先,一个简单的方法需要一个模块来演示:

    def reverser(&block)
      block.call.reverse
    end
    
    现在可以通过标准块

    reverser do
      "hello"
    end
    #=> "olleh"
    
    或者,在替代块语法中,用于内联样式

    reverser { "hello" }
    #=> olleh
    
    您还可以传递lambda或proc,这类似于块。 通过使用&block表示法,可以将变量作为块参数传递:

    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
    
  • 它的意思是“这是块参数”。您不必调用它
    &block
    ,因此需要有一种方法将它与其他参数分开。与普通参数不同,相同的符号用于将参数作为块传递给函数(见下文)

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

  • 是的,您还可以将不同于
    do
    /
    end
    块的内容作为
    &block
    参数传递。参见下面的一些示例

  • @乌里加西给了你一个很好的链接

  • 这里还有一些可以作为块参数传递的其他内容。首先,一个简单的方法需要一个模块来演示:

    def reverser(&block)
      block.call.reverse
    end
    
    现在可以通过标准块

    reverser do
      "hello"
    end
    #=> "olleh"
    
    或者,在替代块语法中,用于内联样式

    reverser { "hello" }
    #=> olleh
    
    您还可以传递lambda或proc,这类似于块。 通过使用&block表示法,可以将变量作为块参数传递:

    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
    

    搜索
    ruby block
    时在谷歌上的第一个结果-搜索
    ruby block
    时在谷歌上的第一个结果-