Method vs proc vs lambda

Question: when going over codecademys tutorial of procs and lambdas, they mentioned the fact that these two are basically teh same (they listed the 2 main differences, but let’s ignore that). They mentioned these two are actually objects so they have access to different blocks…? Is that right? I believe they also mentioned that proc/lambda are reusable?

I thought that something like this WAS reusable

def crap
 puts "whatever"
end

I could make that above method into a proc or a lambda version if I wanted. Couldn’t I use all 3 of these wherever I wanted? I understand proc/lambda difference but aside from the ability for proc/lambda to be treated as objects, why else do I need them apposed to my above code sample?

Basically a proc gives you the ability to write a block (code between do and end), wrap it up in an object, store it in a variable or pass the proc to a method, and run the code in the block whenever you want. It is similar to a method except that it isn’t bound to an object, the proc IS an object. Hopefully that makes sense.

Why would you need a proc?
To quote directly from Chris Pines’ Learn to Program book:

Ok, so we see what blocks and procs are, and how to use them, but what’s the point? Why not just use methods? Well, it’s because there are some things you just can’t do with methods. In particular, you can’t pass methods into other methods (but you can pass procs into methods), and methods can’t return other methods (but they can return procs). This is simply because procs are objects; methods aren’t.

I think that may answer your question! Let me know if you need a more detailed explanation!

Notes
[1] This info comes from my favorite Learn Ruby book: https://pine.fm/LearnToProgram/chap_10.html
This book is totally free and provides a solid introduction to Ruby programming.

1 Like

I’ve been doing more studying. Sorry for not responding.

So let’s assume I had this

    cube = Proc.new { |x| x ** 3 }
    [1, 2, 3].collect!(&cube)
    # ==> [1, 8, 27]
    [4, 5, 6].map!(&cube)
    # ==> [64, 125, 216]

If I had done that with a method (e.g. def cube) I wouldn’t be able to do the method route? Because I wouldn’t be able to use collect! on it? Or .map? Methods need objects to work off of, and I would need a proc for that, not a method? Ignoring lambdas for now. I’m redoing codecademys tutorial on this. Lambdas are almost like procs anyway so let’s just focus on this.

No worries.

I’m not sure what you mean by method route. But you could write a method that does the exact same thing and just add it to the method chain there.

I’m probably going to muddy the waters here but collect! and map! are methods that can be called on an array. The square brackets create an array. Methods need objects. You created an Array object with the square brackets which is what allowed you to call the collect! and map! methods.

I’m pretty sure that’s as clear as mud for you so, here’s a code example that will shed some light on why to use a proc instead od a method. Let’s take the example you already posted.

cube = Proc.new { |x| x ** 3 }
[1, 2, 3].collect!(&cube)
 ==> [1, 8, 27]
[4, 5, 6].map!(&cube)
 ==> [64, 125, 216]

We could rewrite it this way:

[1,2,3].collect! do |x|
  x ** 3
end
=> [1, 8, 27]

It works the exact same way as your code however, anytime I wanted to cube a number I would have to write that block each and every time. That could become tedious quickly. So we write the proc to keep ourselves from having to write the block over and over when we need this functionality.

Essentially blocks are a one use thing while a Proc is a block that is reusable; a method is just a method. I know, I’ve probably muddied the waters but this is the best way I can think to explain this.

As far as using a method to accomplish the same thing…you could in a variety if different ways but I think you can ignore this for the time being.

I’m hoping this shed some light on what you’re learning. Let us know if you need more help!

Yes that helps thank you. What I mean by method route is taking hte method approach.

For example, taking our code sample. Couldn’t (instead of proc) I just do

def cube do |x|
etc
end

Perhaps collect/map were bad choices. But the idea is still there. What sets proc apart from doing my above code example? That’s my main issue. Because the tutorials are talking about how Procs can be saved and be treated as objects (which means I can run methods off them)

However, can’t I reuse that cube method I just made in this post? I can’t run different methods off of it, I understand that (I’d need a proc for that).

That’s what I’m hoping you or someone can clarify.

@scannon Do you understand what I mean?

The short answer is yes you could. I’ll explain in more detail below.

My answer would be that the proc is easier to implement for this particular use case.

Again the short answer is yes.

Now here’s the longer explanation.

First, I wouldn’t get to hung up on methods vs procs at this point. The more you learn the more this is going to be a non-issue.

Second, let’s assume you wrote the cube method. In Ruby you can do method chaining meaning you can write code like this:

[1,2,3].collect!.cube

In fact I suggest that you write the method and then try to call it like above. Go ahead, give it a try.

You should have gotten an undefined method error. It probably looked like this:

NoMethodError: private method `cube' called for #<Enumerator: [1, 2, 3]:collect

But didn’t you just define the method? Technically you did but we need to find out which class our cube method belongs to.

NOTE: whenever you define a method outside of a class, that method becomes a PRIVATE method of the Object class

This is important because you’ll only be able to use this within the Object class. Now there are a number of ways that you could make the cube method available to the Array/Enum. The easiest way is something the Ruby world calls this monkeypatching and can be accomplished by doing the following:

class Array
  def cube
    #implementation
  end
end

Which in the end would allow you to call cube on an Array.

I know that we keep going further down the rabbit hole, but these are probably things that you’re going to need to know anyway. Hope this helps.

Brilliant reply. The above quote is hte money maker. I understand private classes (unaccessible outside of the parent class)…that is what I didn’t understand. So by default I should try to just define methods in my custom classes? Otherwise use proc/lambda for my purposes?

Awesome, I knew we’d hit the “lightbulb” moment eventually! :wink:

This might be a bit confusing but I’m going to try to keep it clear. Whenever you are working with an object that is a part of Ruby’s standard library (Array, String, Float, etc.) I would use a Proc if I am calling an already built in method that accepts a block (collect! for example). However, there are times when you need to manipulate the object in a specific way and the Ruby standard library doesn’t have a built in method that does what you want; in this case I would monkeypatch and write my own method.

Also please note, I am not an expert in Ruby nor in Ruby idioms, so there may be more standard ways of doing these things but this is how I would probably approach these things.

I guess I’ll just take it on a case by case basis and learn as I go. Once I start coding this stuff more, I’ll have a better understanding. I wish the Ruby forums here had more posts so I could read other peoples code. Not quite sure what you mean by your answer other than default Objects that Ruby has should use Proc when possible. Almost done the codecademy Ruby tutorial 3 times now (9hr course each time lol). Then 2 books to read and Ruby Warrior game…

@scannon can you interpret this? This is from a tutorial

attr_reader, attr_writer
We saw in the lesson on classes that Ruby needs methods in order to access attributes. For instance, if we want to access a @name instance variable, we had to write something like

def name
@name
end
Well, no longer! We can use attr_reader to access a variable and attr_writer to change it. If we write

class Person
attr_reader :name
attr_writer :name
def initialize(name)
@name = name
end
end
Ruby does something like this for us automatically:

def name
@name
end

def name=(value)
@name = value
end
Like magic, we can read and write variables as we please! We just pass our instance variables (as symbols) to attr_reader or attr_writer.

(That name= might look funny, but you’re allowed to put an = sign in a method name. That’s just a Ruby convention saying, “hey, this method sets a value!”)

Everything in Ruby is an object. A great way to see how this works is to append “.class” to an object to see what kind of object you are working with. Here’s a few examples and I suggest you try this yourself too.

a = [1,2]
a.class
=> Array
b = "stuff"
b.class
=> String
c = 2.0
c.class
=> Float

This is super helpful because Ruby has a ton of already built in methods. For example if you are working on a String object you can go to the Ruby Docs and get a list of pre-built methods. (http://www.ruby-doc.org/core-2.1.4/String.html)

That’s what I was trying to get at; basically if you know what kind of object you are working with you can check the docs and see if a method exists that will do what you need. If there is, use it and pass a proc if you need to add to that function. If not, do some monkeypatching and add the method yourself. Hopefully that makes more sense.

I’m going to defer to a StackOverflow answer here as the explanation is a little long and this guy does a darn good job. http://stackoverflow.com/a/4371458

Hope that helps!

Ah I understand now! If not in the documentation, create the method yourself! Otherwise proc. Thank you so much. That makes sense.

What I got out of that thread : Use the attribute thingies if I need to access (read/write) those attributes outside of the class? Does that sound right?

In that thread example, he was accessing @name, not the method, right? That makes perfect sense. Everything is makign sense!

Learning Modules…will I ever really need them? I understand that they are used for storage, and you could even theoretically have two classes with the same name, but in different modules. Can’t really think of when I’d need this.

Also why do I need to do something like this

require ‘math’

And then this

include Math

Why do I need quotes on one and not the other? I got an error on Codecademy when removing quotes on “require”. That’s VERY confusing. Is one the main way apposed to the other? I feel like require is better. I like knowing what Module I’m using (and for future users)

Also apologies for ANOTHER post but I just realized something else.

During codecademys tutorial, certain modules were available by default, e.g. the Math module. Yet when codecademy taught me about require/include, they forced me to require it to run the PI function. What gives? What modules are available by default? An explanation would be nice. Thank you.

You got it.

It’s hard to say but, a general rule would be if you find yourself writing similar functions over and over in multiple places wrap the functions up in a module and then require the module instead of rewriting the function.

The first example you can require the module in ANY ruby file doing this.

The second example you would call the include immediately after starting a class.

class SomeClass
  include Math

end

No idea. :stuck_out_tongue: However a require can be called anywhere but an include is called after starting a class.

[quote=“RyanReese, post:17, topic:103233”]
Also apologies for ANOTHER post but I just realized something else.
[/quote] No worries!

There are a bunch. Take a look at the following link to get an idea: http://www.ruby-doc.org/core-2.1.4/doc/syntax/modules_and_classes_rdoc.html

Hopefully the above info helps. Like I said before I have zero experience with codecademy so I can’t really comment on what they are teaching. From my perspective it seems like there are some things that they are skipping that would be really helpful. Obviously it would have been helpful if they explained that Ruby provides a plethora of helpful modules and showed you where to find that info at. Just my humble opinion but, I would probably finish the tutorial and then move on to something else.

I like codeschool.com but most of the courses are not free. As always sitepoint’s materials are good. And The Pragmatic Programmer’s (pragprog.com) have a good selection of materials about Ruby. All of these will require you to put some cash out but, it would be money well spent in my opinion. There was a topic here in the Ruby forum that had some good links but I can’t seem to find it anymore.

I’ll use modules for repeated functions and what not. Just curious if people usually use it for every project. Thanks

Thanks for require vs include information.

I’m reading some Ruby books now so hopefully that helps. Good suggestions of hard-copy Ruby books would be good. I’m reading hte online versions of these now

https://pine.fm/LearnToProgram/chap_00.html

I like Zed Shaw’s Learn Ruby the Hard Way. http://learnrubythehardway.org/book/ There are lots of options for reading /purchasing.

David Black’s The Well-Grounded Rubyist is another good book. http://www.manning.com/black3/

Cool thanks :slight_smile: