在 Ruby 1.8 有进程/lambda 一方面和其他的Proc.new之间的细微差别。

  • 这些不同之处有哪些?
  • 您能否指导如何决定选择哪一种?
  • 在 Ruby 1.9 进程和 lambda 是不同的。什么是怎么回事?
2008-08-03 06:40:54
问题评论:

另请参见︰ Ruby 编程语言书籍通过 Matz Flanagan,它已全面覆盖本主题。进程内像产量语义块的位置视为 lambda 以类似方法的方法调用语义。此外返回,工间休息,等。所有的行为过程 n lambda 中的比较

Ruby 过程和 Lambda 之间的控制流差异请参阅详细的公告

回答:

另一个重要但细微之处在于使用lambda创建方式过程中,并使用Proc.new创建的过程处理return语句︰

  • lambda中的创建过程, return语句返回只能从该过程本身
  • Proc.new-创建进程内, return语句是有点令人惊讶︰ 它将控制权返回不只是从该过程中,也从封闭该过程的方法,但 !

这里是lambda-操作中创建进程内的return它的行为可能期望的方式︰

def whowouldwin

mylambda = lambda {return "Freddy"}
mylambda.call

# mylambda gets called and returns "Freddy", and execution
# continues on the next line

return "Jason"

end


whowouldwin
=> "Jason"

现在轮到Proc.new-创建进程内的return做同样的事情。您将会看到一个 Ruby 在何处断开多自吹自擂原则的最奇怪的情况下︰

def whowouldwin2

myproc = Proc.new {return "Freddy"}
myproc.call

# myproc gets called and returns "Freddy",
# but also returns control from whowhouldwin2!
# The line below *never* gets executed.

return "Jason"

end


whowouldwin2
=> "Freddy"

这要归功于此令人惊讶的行为,(以及减少键入),我倾向于 favour 制作过程时,通过Proc.new使用lambda

然后还有proc方法。是它只是一种简写形式为Proc.new?

@panzi 是的没错,proc相当于Proc.new

@mattdipasquale 在我的测试中,proc的作用与lambda一样,不像Proc.new与 return 语句。这意味着 ruby 的文档都不准确。

@mattdipasquale 很抱歉我只是一半。proc相当于lambda中 1.8,但像Proc.new在 1.9。看到 Peter Wagenet 问题的解答。

为什么是这种"不可思议"的现象?lambda是匿名方法。由于它是一种方法,它返回一个值,并调用它的方法,可对其进行随意,包括忽略它并返回不同的值。Proc就像在代码段中的粘贴。它不像一种方法。因此在退货Proc中情况下,这只是调用它的方法的代码的一部分。

若要提供进一步的澄清︰

你 Joey 说Proc.new的返回行为是令人惊讶。但是当您考虑 Proc.new 像一块这不令人惊讶因为这正是块的行为方式。lambas 在另一方面更类似的方法。

这实际上说明了为什么过程是灵活的而不是 lambda 时说到 arity (参数数量)。块不要求其所有参数提供但方法 (除非已提供默认值)。同时提供了 lambda 参数默认值不是 Ruby 1.8 中的一个选项,它现在支持在 Ruby 1.9 替代 lambda 语法 (如由 webmat 所述)︰

concat = ->(a, b=2){ "#{a}#{b}" }
concat.call(4,5) # => "45"
concat.call(1)   # => "12"

和 Michiel de Mare (OP) 不正确有关的过程和表现在 Ruby 1.9 元数具有相同的 lambda。我已验证它们仍然保持从 1.8 如同上面所指定的行为。

break语句没有实际意义更在过程或 lambda。在过程中,分页符将使您返回从 Proc.new,其尚未完成。和毫无任何意义,因为它实质上是一种方法,而且将从最高级的一种方法永远不会中断中断从 lambda。

nextredo,并raise行为过程和 lambda 中相同。retry中不是允许,将引发异常。

最后,proc方法应永远不会使用不一致,并已和意外的行为。在 Ruby 1.8 中它会实际返回 lambda !在 Ruby 1.9 此问题已修复,并返回处理器。如果您想要创建进程内,继续使用Proc.new.

有关详细信息,我强烈建议 O'Reilly 的Ruby 编程语言是我大部分信息来源。

"""然而当您想到,Proc.new 像一块这并不令人惊讶的是完全块的行为。""<-块 Proc.new 创建一个对象时对象的一部分。Lambda 和 Proc.new 创建一个对象的类是进程内,为什么比较?

我发现此页显示 Proc.new 和 lambda 的区别是什么。根据页,唯一的区别是 lambda 是严格限制的接受它,参数的个数,而 Proc.new 将缺少的参数转换为零。下面是示例 IRB 会话阐释区别︰

irb(main):001:0> l = lambda { |x, y| x + y }
=> #<Proc:0x00007fc605ec0748@(irb):1>
irb(main):002:0> p = Proc.new { |x, y| x + y }
=> #<Proc:0x00007fc605ea8698@(irb):2>
irb(main):003:0> l.call "hello", "world"
=> "helloworld"
irb(main):004:0> p.call "hello", "world"
=> "helloworld"
irb(main):005:0> l.call "hello"
ArgumentError: wrong number of arguments (1 for 2)
    from (irb):1
    from (irb):5:in `call'
    from (irb):5
    from :0
irb(main):006:0> p.call "hello"
TypeError: can't convert nil into String
    from (irb):2:in `+'
    from (irb):2
    from (irb):6:in `call'
    from (irb):6
    from :0

该页面还建议使用 lambda,除非您特别想错误的容错问题。我同意此观点。使用 lambda 似乎稍微更简洁,并似乎与这种无意义的差异,在平均情况下更好的选择。

与 Ruby 1.9,很抱歉,我没有看起来到 1.9,但我不想他们会得的所有更改 (不要轻易相信我说的也是如此,它看起来您听说过一些更改,因此我有可能不正确)。

也不同于 lambda 返回过程。

"""Proc.new 缺失将参数转换为零"""Proc.new 还会忽略额外的参数 (当然 lambda 报告此错误)。

我不能说很多细微的差别有关。但是,我可以指出 Ruby 1.9 现在允许 lambda 和块的可选参数。

以下是 stabby lambda 下 1.9 的新语法︰

stabby = ->(msg='inside the stabby lambda') { puts msg }

Ruby 1.8 没有该语法。声明块/lambda 的简便的方法是既不支持可选参数的︰

# under 1.8
l = lambda { |msg = 'inside the stabby lambda'|  puts msg }
SyntaxError: compile error
(irb):1: syntax error, unexpected '=', expecting tCOLON2 or '[' or '.'
l = lambda { |msg = 'inside the stabby lambda'|  puts msg }

Ruby 1.9,但是,支持可选参数,即使使用旧语法︰

l = lambda { |msg = 'inside the regular lambda'|  puts msg }
#=> #<Proc:0x0e5dbc@(irb):1 (lambda)>
l.call
#=> inside the regular lambda
l.call('jeez')
#=> jeez

如果您想要为美洲虎或 Linux 构建 Ruby1.9,签出这篇文章(shameless 自我提升)。

在 lambda 的可选参数,基本需要我很高兴他们在 1.9 添加它。我假定块还可以具有可选参数然后过 (在 1.9)?

您不演示了以块为单位仅 lambda 的默认参数

Proc 是旧的但返回的语义是非常违反直觉的给我 (至少当我已学习语言) 因为︰

  1. 如果您使用的过程,很可能使用某种类型的功能模式。
  2. 过程可以返回封闭范围之外 (见以前的响应),基本上是 goto,和高度非职能的性质。

Lambda 是功能上更安全、 更易于辨析-我总是使用它而不是处理器。

内容来源于Stack Overflow When to use lambda, when to use Proc.new?
请输入您的翻译

When to use lambda, when to use Proc.new?

确认取消