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)
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.
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.
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:
- The
curry
method doesnât take the arguments you want to apply; it returns a curried version of aProc
. - As pointed out, the
method
method does not return aProc
, so you need to callto_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.