【问题标题】:What is the purpose of lambda in this example?这个例子中 lambda 的目的是什么?
【发布时间】:2009-07-26 16:36:23
【问题描述】:

lambda 在本示例中用于 compose 和 hydrate 方法。 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(' '))

我的第二个问题是 - compose 这个词前面的 & 符号有什么用?

【问题讨论】:

    标签: ruby lambda metaprogramming


    【解决方案1】:

    函数compose 接受一个函数列表并返回一个新分配的函数,该函数是列表中所有函数的组合。它被写成相当奇怪地对待空列表。可能应该忽略第一种情况。 (通常组成空的函数列表应该产生标识函数,但这不是你的示例所做的。我本来期望的

    lambda do |n| { n }
    

    作为基本情况。)

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

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

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

    如果代码写得正确

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

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

    不幸的是,我对 Ruby 了解的不够多,无法为您编写一个 compose 的示例。但其他人会。

    【讨论】:

      【解决方案2】:

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

      以下是原帖:

      【讨论】:

        【解决方案3】:

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

        查看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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-15
          • 2016-06-14
          • 2019-04-27
          • 1970-01-01
          • 2017-08-12
          相关资源
          最近更新 更多