何时何地使用 Lambda?

发布于 2024-10-05 19:40:03 字数 453 浏览 1 评论 0原文

我试图理解为什么我们真的需要 ruby​​ 中的 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 的示例。

I am trying to understand why do we really need lambda or proc in ruby (or any other language for that matter)?

#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

I can do a simple addition using: 1. normal function def, 2. using proc and 3. using lambda.

But why and where use lambda in the real world? Any examples where functions cannot be used and lambda should be used.

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

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

发布评论

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

评论(7

独闯女儿国 2024-10-12 19:40:03

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

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

类似地,除了带有 ifbreakloop...end 之外,您不需要需要任何循环>。我可以继续说下去。1但是您想要使用 Ruby 中的类进行编程。您希望能够使用while循环,甚至array.each { |x| ... },并且您希望能够使用 unless 而不是 if not

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

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

必须中断代码流才能写出要麻烦得多一个 deffed 函数,当它可以清晰地内联编写操作时,必须给它一个无用的名称。确实,没有地方必须使用 lambda,但有很多地方宁愿使用 lambda。

Ruby 通过块解决了许多使用 lambda 的情况:所有函数,如 eachmapopen 都可以将块作为参数基本上采用特殊情况的匿名函数。 array.map { |x| f(x) + g(x) } 与 array.map(&lambda { |x| f(x) + g(x) }) 相同(其中& 只是让 lambda 变得“特殊”,就像裸块一样)。同样,您可以每次都编写一个单独的deffed 函数,但您为什么想要这样做呢?

除了 Ruby 之外,支持这种编程风格的语言没有块,但通常支持更轻量级的 lambda 语法,例如 Haskell 的 \x -> fx + g x,或 C# 的 x => f(x) + g(x);2。任何时候我有一个函数需要采取一些抽象行为,例如 mapeachon_clicked,我都会感谢能够传入 lambda 而不是命名函数,因为它更容易。最终,您不再认为它们有什么特殊之处,它们与数组的文字语法一样令人兴奋,而不是 empty().append(1).append(2).append(3)。这只是该语言的另一个有用的部分。


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

2:我从未真正使用过 C#,因此如果该语法错误,请随时更正。

It's true, you don't need anonymous functions (or lambdas, or whatever you want to call them). But there are a lot of things you don't need. You don't need classes—just pass all the instance variables around to ordinary functions. Then

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

would become

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

Similarly, you don't need any loops except for loop...end with if and break. I could go on and on.1 But you want to program with classes in Ruby. You want to be able to use while loops, or maybe even array.each { |x| ... }, and you want to be able to use unless instead of if not.

Just like these features, anonymous functions are there to help you express things elegantly, concisely, and sensibly. Being able to write some_function(lambda { |x,y| x + f(y) }) is much nicer than having to write

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

It's much bulkier to have to break off the flow of code to write out a deffed function, which then has to be given a useless name, when it's just as clear to write the operation in-line. It's true that there's nowhere you must use a lambda, but there are lots of places I'd much rather use a lambda.

Ruby solves a lot of the lambda-using cases with blocks: all the functions like each, map, and open which can take a block as an argument are basically taking a special-cased anonymous function. array.map { |x| f(x) + g(x) } is the same as array.map(&lambda { |x| f(x) + g(x) }) (where the & just makes the lambda "special" in the same way that the bare block is). Again, you could write out a separate deffed function every time—but why would you want to?

Languages other than Ruby which support that style of programming don't have blocks, but often support a lighter-weight lambda syntax, such as Haskell's \x -> f x + g x, or C#'s x => f(x) + g(x);2. Any time I have a function which needs to take some abstract behavior, such as map, or each, or on_clicked, I'm going to be thankful for the ability to pass in a lambda instead of a named function, because it's just that much easier. Eventually, you stop thinking of them as somehow special—they're about as exciting as literal syntax for arrays instead of empty().append(1).append(2).append(3). Just another useful part of the language.


1: In the degenerate case, you really only need eight instructions: +-<>[].,. <> move an imaginary "pointer" along an array; +- increment and decrement the integer in the current cell; [] perform a loop-while-non-zero; and ., do input and output. In fact, you really only need just one instruction, such as subleq a b c (subtract a from b and jump to c if the result is less than or equal to zero).

2: I've never actually used C#, so if that syntax is wrong, feel free to correct it.

意中人 2024-10-12 19:40:03

块或多或少是同一件事

,在 Ruby 中,人们通常不使用 lambda 或 proc,因为块是同一件事,而且更方便。

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

但人们经常希望自动化包装器并提供自定义库。想象一个函数建立 HTTP 或 HTTPS 连接,或者直接 TCP 连接,将 I/O 提供给其客户端,然后关闭连接。或者也许只是对普通的旧文件执行相同的操作。

因此,在 Ruby 中,我们会将函数放入库中,并让它为用户.. 客户端.. “调用者”占用一个块来编写他的应用程序逻辑。

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

Blocks are more-or-less the same thing

Well, in Ruby, one doesn't usually use lambda or proc, because blocks are about the same thing and much more convenient.

The uses are infinite, but we can list some typical cases. One normally thinks of functions as lower-level blocks performing a piece of the processing, perhaps written generally and made into a library.

But quite often one wants to automate the wrapper and provide a custom library. Imagine a function that makes an HTTP or HTTPS connection, or a straight TCP one, feeds the I/O to its client, and then closes the connection. Or perhaps just does the same thing with a plain old file.

So in Ruby we would put the function in a library and have it take a block for the user .. the client .. the "caller" to write his application logic.

In another language this would have to be done with a class that implements an interface, or a function pointer. Ruby has blocks, but they are all examples of a lambda-style design pattern.

小嗲 2024-10-12 19:40:03
  1. 这只是一个方便。您不需要命名某些块

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

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

  1. #lambda 通常用于创建闭包:

    defgenerate_multiple_proc(辅因子)
    lambda { |元素|元素 * 辅因子 }
    结束

    [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]

  1. It is just a convenience. You don't need to name certain blocks

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

(imagine if you had to name all these blocks)

  1. #lambda is usually used to create closures:

    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]

你げ笑在眉眼 2024-10-12 19:40:03

这取决于风格。 Lambda 是声明式风格,方法是命令式风格。考虑一下:

Lambda、块、过程都是不同类型的闭包。现在的问题是,何时以及为何使用匿名闭包。我可以回答这个问题——至少在红宝石中!

闭包包含调用它们的位置的词汇上下文。如果从方法内部调用方法,则无法获得调用该方法的上下文。这是由于对象链在 AST 中的存储方式造成的。

另一方面,闭包 (lambda) 可以通过方法与词法上下文一起传递,从而允许延迟求值。

lambda 自然也适合递归和枚举。

It comes down to style. Lambdas are a a declarative style, methods are an imperative style. Consider this:

Lambda, blocks, procs, are all different types of closure. Now the question is, when and why to use an anonymous closure. I can answer that - at least in ruby!

Closures contain the lexical context of where they were called from. If you call a method from within a method, you do not get the context of where the method was called. This is due to the way the object chain is stored in the AST.

A Closure (lambda) on the other hand, can be passed WITH lexical context through a method, allowing for lazy evaluation.

Also lambdas naturally lend themselves to recursion and enumeration.

撩起发的微风 2024-10-12 19:40:03

在 OOP 的情况下,只有根据您的领域建模,类中应该有这样的操作,您才应该在类中创建函数。

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

另请检查这些 SO 帖子 -

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

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

何时在 Ruby on Rails 中使用 lambda?

In case of OOP, you should create a function in a class only if there should be such an operation on the class according to your domain modeling.

If you need a quick function which can be written inline such as for comparison etc, use a lambda

Also check these SO posts -

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

C# Lambda expressions: Why should I use them?

When to use a lambda in Ruby on Rails?

玻璃人 2024-10-12 19:40:03

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

这在 Ruby 迭代中很常见,例如 some_list.each { |item| ... } 对 some_list每个 item 执行某些操作。尽管请注意,这里我们没有使用关键字 lambda ;如前所述,块基本上是相同的东西。

在 Python 中(因为我们在这个问题上有一个与语言无关的标签),您无法编写类似于 Ruby 块的任何内容,因此 lambda 关键字出现得更频繁。但是,您可以从列表推导式和生成器表达式中获得类似的“快捷方式”效果。

They're used as "higher-order" functions. Basically, for cases where you pass one function to another, so that the receiving function can call the passed-in one according to its own logic.

This is common in Ruby for iteration, e.g. some_list.each { |item| ... } to do something to each item of some_list. Although notice here that we don't use the keyword lambda; as noted, a block is basically the same thing.

In Python (since we have a language-agnostic tag on this question) you can't write anything quite like a Ruby block, so the lambda keyword comes up more often. However, you can get a similar "shortcut" effect from list comprehensions and generator expressions.

时光是把杀猪刀 2024-10-12 19:40:03

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

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 }

说它更灵活。

I found this helpful in understanding the differences:

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

But in general the point is sometimes your writing a method but you don't know what you're going to want to do at a certain point in that method, so you let the caller decide.

E.g.:

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

Then instead of writing a iterate_over_two_arrays_and_print_sum method and a iterate_over_two_arrays_and_print_product method you just call:

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

or

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

so it's more flexible.

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