在此示例中 lambda 的用途是什么?

发布于 2024-07-29 07:21:12 字数 609 浏览 3 评论 0 原文

在此示例中,lambda 在 compose 和 Hydro 方法中均使用。 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(' '))

我的第二个问题是 - 在“撰写”一词前面需要加“&”号吗?

lambda is used in this example in both the compose and the hydrate methods. What does lambda do here?

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(' '))

My second question is - what is the need for the ampersand in front of the word compose?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

熊抱啵儿 2024-08-05 07:21:12

函数 compose 接受一个函数列表并返回一个新分配的函数,该函数是列表中所有函数的组合。 它被编写为相当奇怪地处理空列表; 可能第一种情况应该被忽略。 (通常编写空函数列表应该生成恒等函数,但这不是您的示例所做的。我期望将其

lambda do |n| { n }

作为基本情况。)

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

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

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

,而如果代码编写正确

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

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

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

The function compose takes a list of functions and returns a newly allocated function that is the composition of all the functions on the list. It's been written to treat the empty list rather oddly; it may be that the first case should be ignored. (Normally composing the empty list of functions should produce the identity function, but that's not what your example does. I would have expected

lambda do |n| { n }

as the base case.)

It's necessary to use a lambda in order to create a new function You see that in the recursive case in compose: the lambda creates a new function which when given n returns the result of calling the composition of the remaining functions, then finally applies the first function. This is not good code to emulate, as the recursion over the list of functions is repeated every time the composition is called. In the example:

  • Creating the composition of functions uses constant time and space

  • Applying the composition of functions costs linear time and space

Whereas if the code were written properly

  • Creating the composition of functions should cost linear time and space

  • Applying the composition of functions should cost linear time and should require no allocations (zero space)

Unfortunately I don't know enough Ruby to write for you an example of compose the way it ought to be done. But others will.

已下线请稍等 2024-08-05 07:21:12

顺便说一句,我不知道你从哪里得到这个确切的代码,但它看起来像是雷金纳德·布雷斯韦特博客中的一些代码的轻微修改版本。 (该代码是对 FizzBu​​zz 问题的故意过度解决方案,用于对 Ruby 中的函数式编程和更一般的函数式编程进行认真讨论。)

以下是原始帖子:

As a side note, I don't know where you got this exact code, but it looks like a very lightly altered version of some code from Reginald Braithwaite's blog. (The code was a deliberately over-the-top solution to the FizzBuzz question used in a serious discussion of functional programming in Ruby and functional programming more generally.)

Here are the original posts:

Oo萌小芽oO 2024-08-05 07:21:12

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

查看 Ruby 中的一元 & 符号,& 符号将过程转换为块。

示例:

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>

这是另一篇关于块之间差异的文章,块、lambda 与过程

Your second question asks what the & is doing.

Looking at The unary ampersand in Ruby, the ampersand converts a proc to a block.

Example:

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

Calling meth1 with a block, works as expected:

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

Calling with a Proc does not work:

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>'

But it does work if you convert the Proc to a block:

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

This is the same thing that is happening when you use the following code:

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>

Here is another article on the differences between blocks, block vs lambda vs proc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文