Where and when to use Lambda?

后端 未结 7 2014
执笔经年
执笔经年 2021-01-31 16:47

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
de         


        
相关标签:
7条回答
  • 2021-01-31 17:27

    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.

    0 讨论(0)
  • 2021-01-31 17:27

    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)

    2) #lambda is usually used to create 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]
    
    0 讨论(0)
  • 2021-01-31 17:33

    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.

    0 讨论(0)
  • 2021-01-31 17:33

    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.

    0 讨论(0)
  • 2021-01-31 17:40

    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?

    0 讨论(0)
  • 2021-01-31 17:44

    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.

    0 讨论(0)
提交回复
热议问题