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

Con*_*wen 1 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(' '))
Run Code Online (Sandbox Code Playgroud)

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

Nor*_*sey 8

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

lambda do |n| { n }
Run Code Online (Sandbox Code Playgroud)

作为基础案例.)

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

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

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

如果代码写得正确的话

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

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

不幸的是,我不知道Ruby会为你写一个compose应该做的方式的例子.但其他人会.


Tel*_*hus 6

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

以下是原帖:


Mat*_*ley 5

你的第二个问题是问你在&做什么.

看看Ruby的unary&符号,&符号将proc转换为块.

例:

irb(main):001:0> def meth1
irb(main):002:1>   yield "Hello"
irb(main):003:1> end
=> nil
Run Code Online (Sandbox Code Playgroud)

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

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

使用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>'
Run Code Online (Sandbox Code Playgroud)

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

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

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

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>
Run Code Online (Sandbox Code Playgroud)

这是另一篇关于块,块与lambda vs proc之间差异的文章.