Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where and when to use 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.

like image 389
zengr Avatar asked Dec 04 '10 05:12

zengr


People also ask

When should Lambda be used?

Use a Lambda when you need to access several services or do custom processing. As data flows through services, you use Lambdas to run custom code on that data stream. This is useful in a Kinesis Pipeline that's receiving data from things like IoT devices.

What is a lambda used for?

Lambda runs your code on high availability compute infrastructure and performs all the administration of your compute resources. This includes server and operating system maintenance, capacity provisioning and automatic scaling, code and security patch deployment, and code monitoring and logging.

When should lambda not be used?

Lambda functions that transport data from one service to another without performing any business logic on that data can often be replaced with service integrations. For example, it's usually not necessary to put a Lambda function between API Gateway and DynamoDB to read an item from a table.


4 Answers

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.

like image 103
Antal Spector-Zabusky Avatar answered Oct 08 '22 15:10

Antal Spector-Zabusky


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.

like image 40
DigitalRoss Avatar answered Oct 08 '22 16:10

DigitalRoss


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.

like image 37
thatrubylove Avatar answered Oct 08 '22 15:10

thatrubylove


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]
like image 30
Daniel Vartanov Avatar answered Oct 08 '22 15:10

Daniel Vartanov