何时何地使用Lambda?

我试图理解为什么我们真的需要rubda(或任何其他语言)lambda或proc?

#method def add a,b c = a+b end #using proc def add_proc a,b f = Proc.new {|x,y| x + y } f.call a,b end #using lambda function def add_lambda a,b f = lambda {|x,y| x + y} f.call a,b end puts add 1,1 puts add_proc 1,2 puts add_lambda 1,3 

我可以使用以下方法进行简单的添加:1。正常函数def,2。使用proc和3.使用lambda。

但是为什么以及在现实世界中使用lambda? 任何不能使用函数和lambda应该使用的例子。

确实,你不需要匿名函数(或lambdas,或任何你想称之为的东西)。 但是有很多你不需要的东西。 您不需要类 – 只需将所有实例变量传递给普通函数。 然后

 class Foo attr_accessor :bar, :baz def frob(x) bar = baz*x end end 

会成为

 def new_Foo(bar,baz) [bar,baz] end def bar(foo) foo[0] end # Other attribute accessors stripped for brevity's sake def frob(foo,x) foo[0] = foo[1]*x end 

同样,你不需要任何循环,除了loop...end ifbreak 。 我可以继续下去。 1但是你用Ruby编写类。 您希望能够使用while循环,甚至可以使用array.each { |x| ... } array.each { |x| ... } ,你希望能够使用, unless不是, if not

就像这些function一样,匿名function可以帮助您优雅,简洁,明智地表达事物。 能够编写some_function(lambda { |x,y| x + f(y) })比写入要好得多

 def temp(x,y) x + f(y) end some_function temp 

必须中断代码流以写出一个def fed函数,然后必须给它一个无用的名称,当它在线编写操作时很明显。 确实没有地方你必须使用lambda,但有很多地方我宁愿使用lambda。

Ruby使用块解决了很多使用lambda的情况:像eachmapopen这样的所有函数each可以将块作为参数,它们基本上采用了一种特殊的匿名函数。 array.map { |x| f(x) + g(x) } array.map { |x| f(x) + g(x) }array.map(&lambda { |x| f(x) + g(x) }) (其中&只是使lambda“特殊”的方式与裸块是)。 再一次,你可以每次写出一个单独的def fed函数 – 但你为什么要这样做?

支持这种编程风格的Ruby以外的语言没有块,但通常支持更轻量级的lambda语法,例如Haskell的\x -> fx + gx ,或者C#的x => f(x) + g(x); 2 。 每当我有一个需要采取一些抽象行为的函数时,例如map ,或者each ,或者on_clicked ,我都会感谢能够传入lambda而不是命名函数,因为它只是那么多更容易 。 最后,你不再认为它们有点特别 – 它们与数组的文字语法一样令人兴奋而不是empty().append(1).append(2).append(3) 。 只是该语言的另一个有用的部分。


1:在退化的情况下,你真的只需要八个指令 : +-<>[].,<>沿arrays移动一个虚构的“指针”; +-递增和递减当前单元格中的整数; []执行循环而非零; 和.,做输入和输出。 实际上,您实际上只需要一条指令 ,例如subleq abc (如果结果小于或等于零,则从b减去b并跳转到c )。

2:我从来没有真正使用过C#,所以如果这种语法错误,请随时纠正它。

块或多或少都是一样的

好吧,在Ruby中,通常不会使用lambda或proc,因为块大致相同并且更方便。

用途是无限的,但我们可以列出一些典型案例。 人们通常将function视为执行一部分处理的较低级别的块,可能通常编写并制作成库。

但通常人们想要自动化包装器并提供自定义库。 想象一下,一个使HTTP或HTTPS连接或直接TCP连接的函数将I / O提供给它的客户端,然后关闭连接。 或者也许只是用普通的旧文件做同样的事情。

所以在Ruby中我们会将函数放在一个库中并让它为用户提供一个块…客户端…“调用者”来编写他的应用程序逻辑。

在另一种语言中,这必须使用实现接口的类或函数指针来完成。 Ruby有块,但它们都是lambda样式设计模式的例子。

1)这只是一个方便。 您不需要为某些块命名

 special_sort(array, :compare_proc => lambda { |left, right| left.special_param <=> right.special_param } 

(想象一下,如果你必须命名所有这些块)

2)#lambda通常用于创建clojures:

 def generate_multiple_proc(cofactor) lambda { |element| element * cofactor } end [1, 2, 3, 4].map(&generate_multiple_proc(2)) # => [2, 3, 5, 8] [1, 2, 3, 4].map(&generate_multiple_proc(3)) # => [3, 6, 9, 12] 

它归结为风格。 Lambdas是一种陈述式的风格,方法是势在必行的风格。 考虑一下:

Lambda,blocks,procs都是不同类型的闭包。 现在的问题是,何时以及为何使用匿名闭包。 我可以回答 – 至少在ruby中!

闭包包含从中调用它们的词汇上下文。 如果从方法中调用方法,则不会获得调用方法的上下文。 这是由于对象链存储在AST中的方式。

另一方面,闭包(lambda)可以通过方法与词汇上下文一起传递,允许进行惰性求值。

lambdas自然也适用于递归和枚举。

它们被用作“高阶”function。 基本上,对于将一个函数传递给另一个函数的情况,接收函数可以根据自己的逻辑调用传入的函数。

这在Ruby中常见,用于迭代,例如some_list.each {| item | …}对some_list each item执行某些some_list 。 虽然这里注意我们不使用关键字lambda ; 如上所述,块基本上是相同的。

在Python中(因为我们在这个问题上有一个与language-agnostic标签)你不能写任何类似Ruby块的东西,所以lambda关键字会更频繁地出现。 但是,您可以从列表推导和生成器表达式中获得类似的“快捷方式”效果。

我发现这有助于理解差异:

http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/

但总的来说,重点是你有时候写一个方法,但是你不知道在那个方法中某个点你想要做什么,所以你让调用者决定。

例如:

 def iterate_over_two_arrays(arr1, arr2, the_proc) arr1.each do |x| arr2.each do |y| # ok I'm iterating over two arrays, but I could do lots of useful things now # so I'll leave it up to the caller to decide by passing in a proc the_proc.call(x,y) end end end 

然后代替编写iterate_over_two_arrays_and_print_sum方法和iterate_over_two_arrays_and_print_product方法,您只需调用:

 iterate_over_two_arrays([1,2,3], [4,5,6], Proc.new {|x,y| puts x + y } 

要么

 iterate_over_two_arrays([1,2,3], [4,5,6], Proc.new {|x,y| puts x * y } 

所以它更灵活。

对于OOP,只有在根据域建模对类进行此类操作时,才应在类中创建函数。

如果您需要一个可以内联写入的快速function,例如比较等,请使用lambda

还要查看这些SOpost –

何时使用lambda,何时使用Proc.new?

C#Lambda表达式:我为什么要使用它们?

何时在Ruby on Rails中使用lambda?