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(' '))
我的第二个问题是 - 在撰写单词之前,&符号需要什么?
答案 0 :(得分:8)
函数compose
获取函数列表并返回一个新分配的函数,该函数是列表中所有函数的组合。它被编写为非常奇怪地处理空列表;可能应该忽略第一种情况。 (通常组成空的函数列表应该产生身份函数,但这不是你的例子所做的。我原以为
lambda do |n| { n }
作为基本案例。)
有必要使用lambda
来创建新函数您会在compose的递归情况中看到:lambda
创建一个新函数,当给定n
返回调用其余函数的组合的结果,然后最终应用第一个函数。这不是一个很好的模拟代码,因为每次调用合成时都会重复函数列表的递归。在示例中:
创建函数组合使用恒定的时间和空间
应用函数组合需要线性时间和空间
如果代码写得正确
创建函数的组合应该花费线性时间和空间
应用函数的组合应该花费线性时间,并且不需要分配(零空间)
不幸的是,我不知道Ruby会为你写一个compose
应该如何完成的例子。但其他人会。
答案 1 :(得分:6)
作为旁注,我不知道你在哪里得到这个确切的代码,但它看起来像Reginald Braithwaite博客的一些代码的一个非常轻微改变的版本。 (该代码是故意过度解决FizzBuzz问题的解决方案,用于对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之间差异的另一篇文章。