Intro
In this post I'll be getting into some of the key parts of Ruby, lambdas and procs. I'll also get into the main differences between them, and how to use either properly.
What are Lambdas?
Lambdas, what the hell is that?
This might be difficult to grasp, and I'm also not the best at explaining, but lambdas are basically small scale functions, that behave like methods. Kind of.
I don't get it.
Okay, a lambda is a block of code that is assigned to a variable. Lambdas require all input/parameters functions do to work, so without them Ruby will return an error. Lambdas are assigned(usually) to a variable, this makes them executable only when the variables value is called. Here's an example:
squared = lambda {|x| x**2}# or {|x| x*x}
[1, 2, 3, 4, 7].map(&squared)
#=> [1, 4, 9, 16, 49]
What happened?
Basically, I used the & to reference squared
and map called it on each item of the list to create a new list. Its values are [1, 4, 9, 16, 49]
.
That's pretty much the basics for writing lambdas, but, of course there's more. We'll get into them a bit later.
Procs
NO!
Procs are an essential part of Ruby. Senior and Junior Ruby developers alike should know how to use Procs. Procs are from the builtin "Proc" class in Ruby. They're blocks of code assigned to a variable.
How do I use a Proc?
Simple here's an example:
myProc = Proc.new {=begin Random block to later be executed =end}
Okay that doesn't look too confusing. But what's the difference between a Proc and a Lambda, other than syntax.
It's actually on the surface, there isn't one. They can be used to do the exact same job almost all the time. There's one small difference that I'd like to note though. Lambdas, which mind you are still nameless functions, aren't evaluated until they're called. But Procs are a class type so they're evaluated immediately. Let's use a simple example so you understand what that means for your code.
With a Proc
def myFunc()
myBlock = Proc.new {return "Hello"}
return "#{myBlock} World!"
end
With a Lambda
def myFunc()
myBlock = lambda {return "Hello"}
return "#{myBlock} World!"
end
If you haven't already noticed with the Proc the intended output never got returned. Since it was evaluated before it was called returning "Hello" ended the function, meaning the next line was never called. With the lambda that doesn't happen because Ruby skips it until it's later called by the return statement at the end of the function. Giving us "Hello World!", the intended output. This is kind of contrived but it's a difference worth pointing out. So having a return statement or any hard coded out put in a Proc is a bad idea.
That's that folks. 😄!!!
Top comments (7)
The part about procs being evaluated immediately is wrong. Procs, just like lambdas, are evaluated only when you call them; or rather, when you send them the
:call
signal.The difference is that, simpy by design, a proc can return from the method that calls it; that is, when function F calls a proc P and P returns, not only P ends there, but F also finishes. You could say P returns on behalf of F.
Lambdas, on the other hand, can only return from themselves, not from the function that called them. If a function F calls a lambda Λ, and Λ returns, F will continue where it called Λ as if it had been any other method call.
The other big difference is that lambdas, just like functions, have an arity and passing them the wrong number of arguments will cause an error. Procs, just like blocks, treat missing arguments as
nil
and discard extra arguments.EDIT: Ironically, Ruby might be the wrong place to start when you want to learn about lambdas though. I would recommend trying out some other language that relies more heavily on anonymous functions (Lua being my personal favourite) to get a better feeling for the whole concept. Fromthere, you can go back to ruby and it will make much more sense.
WRONG!!!! I've already read at least 3 articles on different websites(like medium)that talk about what I just wrote in this post. Maybe that's how it works in Lua(never used it), but I how I've described in my post is correct info.
Will output:
So as you can see, the proc does not run until it is called. In fact,
will output:
Q.E.D.
Buddy, you wrote proc wrong. It's Proc.new and writing foo doesn't call the function it passes it as an object. And of course the Proc doesn't get evaluated immediately if it's inside a function. Ruby waits until the function is called, then once it gets to the Proc it gets evaluated. Your examples don't disprove what I've said they just show how Rubies order works. I mean you literally put the proc after the puts statement in your code. And I specifically said the return statement is what you should look out for not a puts. Next time you want to try to disprove what a dev says learn the syntax first bud.
At first I wasn't sure if this was a troll post, but I assume it's not.
Setting aside that
proc {}
is syntactic sugar forProc.new {}
and definitely valid ruby code, I took your statementto mean that Procs, unlike Lambdas, are evaluated as soon as they are defined, which they are not. They both get evaluated when they receive a
:call
signal; there's no difference whatsoever between either of them. If that wasn't what you meant, please clarify. You're not being very specific in your vocabulary, so it is difficult to know exactly what you mean and I might just be misunderstanding you.EDIT: Some extra advise: don't tell people to "learn X". Even if you actually know what you're talking about, it makes you come across as a dick, and, if on top of it you're wrong, it makes you look even worse. Next time, either just open
irb
and check for yourself if something is correct, or be more open in your statement, like "I think you're wrong". Don't just assume people on the internet don't know what they're doing or it might backfire really hard.Okay, at this point I'm kind of out of fuel to argue so I'll set aside the argument, I didn't know that proc was synthetic sugar for Proc.new(nice) since that turns out to be true I'll read over my post and thoroughly check if what you're saying checks out. Hope I wasn't too toxic in any of my responses I get defensive sometimes. Nevertheless you're a dev, so your opinion should be heard and all warnings heeded. Again, sorry, I may have lost it.
I have to agree with @darkwiiplayer on this one. As far as the syntax is concerned, procs can be created using
proc
,Proc.new
andKernel.proc
.As far as the differences are concerned, there are two big differences in my opinion.
return
statement.lambda
complains.