在这个例子中lambda的目的是什么?

时间:2009-07-26 16:36:23

标签: ruby lambda metaprogramming

lambda在本例中用于组合和水合物方法。 lambda在这做什么?

def compose *lambdas
  if lambdas.empty?
    lambda { nil }
  elsif lambdas.size == 1
    lambdas.first
  else
    lambda do |n|
      lambdas.first.call(compose(*lambdas[1..-1]).call(n))
    end
  end
end

def hydrate(modulus, printable_form)
  i = 0
  lambda do |n|
    (i = (i + 1) % modulus) == 0 && printable_form || n
  end
end

print(((1..100).map
   &compose(
     hydrate(15, 'Watermelon'), 
     hydrate(5, 'Melon'), 
     hydrate(3, 'Water'))).join(' '))

我的第二个问题是 - 在撰写单词之前,&符号需要什么?

3 个答案:

答案 0 :(得分:8)

函数compose获取函数列表并返回一个新分配的函数,该函数是列表中所有函数的组合。它被编写为非常奇怪地处理空列表;可能应该忽略第一种情况。 (通常组成空的函数列表应该产生身份函数,但这不是你的例子所做的。我原以为

lambda do |n| { n }

作为基本案例。)

有必要使用lambda创建新函数您会在compose的递归情况中看到:lambda创建一个新函数,当给定n返回调用其余函数的组合的结果,然后最终应用第一个函数。这不是一个很好的模拟代码,因为每次调用合成时都会重复函数列表的递归。在示例中:

  • 创建函数组合使用恒定的时间和空间

  • 应用函数组合需要线性时间和空间

如果代码写得正确

  • 创建函数的组合应该花费线性时间和空间

  • 应用函数的组合应该花费线性时间,并且不需要分配(零空间)

不幸的是,我不知道Ruby会为你写一个compose应该如何完成的例子。但其他人会。

答案 1 :(得分:6)

作为旁注,我不知道你在哪里得到这个确切的代码,但它看起来像Reginald Braithwaite博客的一些代码的一个非常轻微改变的版本。 (该代码是故意过度解决FizzBu​​zz问题的解决方案,用于对Ruby中的函数式编程和函数式编程进行认真讨论。)

以下是原帖:

答案 2 :(得分:5)

您的第二个问题询问&正在做什么。

查看The unary ampersand in Ruby,&符将proc转换为块。

示例:

irb(main):001:0> def meth1
irb(main):002:1>   yield "Hello"
irb(main):003:1> end
=> nil

使用块调用meth1,按预期工作:

irb(main):004:0> meth1 { |s| puts s } # Calling meth1 with a block
Hello
=> nil

使用Proc调用不起作用:

irb(main):005:0> p = Proc.new { |s| puts "In proc: #{s}" }
=> #<Proc:0x13e5d60@(irb):5>
irb(main):006:0> meth1 p
ArgumentError: wrong number of arguments (1 for 0)
        from (irb):6
        from C:/Ruby19/bin/irb:12:in `<main>'

但如果将Proc转换为块,它确实有效:

irb(main):007:0> meth1 &p # Convert the proc to a block
In proc: Hello
=> nil

使用以下代码时发生的情况与此相同:

irb(main):001:0> def meth2(&block) # Block is converted to Proc
irb(main):002:1>   puts block.class.to_s if block_given?
irb(main):003:1> end
=> nil
irb(main):004:0> meth2 { puts "Hi There" }
Proc
=> nil
irb(main):005:0>

以下是关于块block vs lambda vs proc之间差异的另一篇文章。