DEV Community

Cover image for Intro To Ruby Procs and Lambdas(and the difference)
Sean
Sean

Posted on

Intro To Ruby Procs and Lambdas(and the difference)

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]
Enter fullscreen mode Exit fullscreen mode

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

You mean Crocs. Like these ones.
Image of white crocs.

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}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

With a Lambda

def myFunc()
   myBlock = lambda {return "Hello"}
   return "#{myBlock} World!"
end
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️ • Edited

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.

Collapse
 
seanolad profile image
Sean

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.

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️ • Edited
def foo
  p = proc { puts "Proc is running!" }
  puts "The proc has been created"
  p.call
end

foo

Will output:

The proc has been created
Proc is running!

So as you can see, the proc does not run until it is called. In fact,

def foo
  return proc { puts "Proc is running!" }
end

p = foo
puts "The proc has been created, foo has returned"
p.call

will output:

The proc has been created, foo has returned
Proc is running!

Q.E.D.

Thread Thread
 
seanolad profile image
Sean

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.

Thread Thread
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️ • Edited

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 for Proc.new {} and definitely valid ruby code, I took your statement

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.

to 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.

Thread Thread
 
seanolad profile image
Sean

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.

Collapse
 
abeidahmed profile image
Abeid Ahmed

I have to agree with @darkwiiplayer on this one. As far as the syntax is concerned, procs can be created using proc, Proc.new and Kernel.proc.
As far as the differences are concerned, there are two big differences in my opinion.

  1. How the two handles the return statement.
  2. Proc can silently discard extra params and missing params are set to nil, whereas lambda complains.