Functional & Object Oriented Programming in Ruby

How do functional program and object-oriented programming stack up in Ruby? In this episode, Ben and Joe dive find out. We've put together a number of code samples, each of which follows an object-oriented, functional, or hybrid approach. We'll re...
This is a companion discussion topic for the original entry at https://thoughtbot.com/upcase/videos/functional-object-oriented-programming-in-ruby

Functional ruby and OO ruby are my specialty (most rails guys and rubyists write neither) :smiley:

If any of the subscribers here @ learn want to do a live session where we discuss this episode, let me know and I will set it up. I am a lambda junkie and I think immutability is the bees knees.

I have finished the video and I would like to pick on (I will limit myself to) one thing…

Both examples EVERY time were OO examples. OOP is not about just state modification. It is about organizing objects with methods.

Functional in contrast is about functions as opposed to methods, and doesn’t deal much with structure. That is why it is naturally immutable and stateless. You could have used a module in every ‘functional’ example (think FileUtils or countless other stdlib utils)

But in reality, pure functional programming in Ruby is done in lambdas, and on the object namespace. You didn’t show that.

What you guys were really demonstrating was state modification and a bit about hierarchy and inheritance vs immutable programming. Imperative, procedural vs functional, explicit.

Ok, I lied… one more thing.

Ifs and loops are Imperative Programming, not OOP. SmallTalk? I can OOP all day long without ever using an if or case. I start with them, then I concretize them away.

I am always available for discussion. :smiley:

The weekly iteration is THE BEST regularly released ruby screencast, absolutely. I wasn’t very happy with that 2 week break in my Joe and Ben fix! Please keep it up.

1 Like

I tried using the curry method in the screencast like so:

class Thing
  def process(time, message)
    puts "#{time}: #{message}"
  end
end

thing = Thing.new
client = thing.method(:process).curry(Time.now)

undefined method `curry' for #<Method: Thing#process>

Am I missing something in the concept?

I am using 2.1.2.

A little more playing and I came up with this which works:

client = thing.method(:process).to_proc.curry.(Time.now)
client.call('My Message')

Is this the proper way to use this method and not what is shown in the video? Or was I originally doing something incorrectly?

@frank_west_iii, if you look ruby docs you’ll see that Object#method returns Method object, which don’t have curry method on its instances. And the only place you can find that method is Proc#curry. That’s why turning method object to a proc solved the problem.

@lompy, reading the docs is how I finally came to the solution. I was just curious because the code in the screencast appeared to be using the method method and curry together and then they deep dived into it a bit. So I decided look into curry since I have never used curry before. Come to find out it doesn’t work the way the screencast presented it (or I am/was missing something). @jferris, is the code in the screencast non-functional?

Paypal.method(:charge!).curry(auth_code)

Yes this code will raise an undefined method error, like in your example above, unless the guys did override one of those two core ruby methods, which would be wired in scope of learning video.
So I guess it’s just a plain old ruby typo and they didn’t actually run the code through the interpreter.

Sorry about that; the code in the slides does have a few errors:

  1. The curry method doesn’t take the arguments you want to apply; it returns a curried version of a Proc.
  2. As pointed out, the method method does not return a Proc, so you need to call to_proc on it.

The correct code looks like this:

Paypal.method(:charge!).to_proc.curry.call(auth_code)

I haven’t used curry much myself in Ruby, and it in my research I’ve found that not many others do, either. I’ve started looking for opportunities to use it in place of noisier method classes or metaprogramming, though.

@jferris I believe you could also do something like:

 Paypal.method(:charge!).to_proc.curry[auth_code]

I’ll preface this with saying that I’ve only used curry a couple of times.