views:

639

answers:

6

Can Ruby really be used as a functional language? What are some good tutorials to teach this facet of the language? Note: I really want to use and stick with Ruby as my primary language so I am not interested at this point in being converted to YAFL (yet another functional language). I am really interested in how well Ruby's functional facets perform against the standard functional language baseline. Thanks.

+3  A: 

It depends what you mean by "Functional Programming". In my view, the most important thing is that functions are first class values, and in this respect Ruby is a functional language.

Jonas
+13  A: 

Yes...sort of. Ruby lacks a reasonable construct to enforce immutability. (Object#freeze doesn't count) Immutability is really the cornerstone of functional languages. Further, Ruby's core libraries are highly oriented toward imperative design. Its Array and Hash classes are both mutable by nature, even String has methods which make non-immutable (e.g. gsub!). Ironically, Java is more "functional" than Ruby in this respect.

With that said, it is possible to do functional-like programming in Ruby. Any time you use a block/proc/lambda, you are using a feature that comes from functional programming. Likewise, collection methods like map and zip are also higher-order constructs which find their roots in languages like Lisp, ML and Haskell.

If you really want to do functional programming, you will want to use a language which is more geared toward that genre. Some suggestions:

  • Clojure - Since you phrased the question using Ruby, I'm guessing you're of the dynamically typed persuasion. Clojure is like a strictly-functional Lisp that runs on the JVM.
  • F# - Basically OCaml on the CLR. Very nice, very clean
  • Scala - Not a strictly functional language, but much better for it than Ruby
  • Haskell - Everybody's favorite!

You'll notice that three of these four languages are statically typed. In fact, in the case of Scala and Haskell, these are very statically typed languages (much stronger type systems than, say, Java). I'm not sure why this is a trend in functional languages, but there you have it.

Daniel Spiewak
@Daniel Spiewak - argh you beat me! You have to be fast in this place ;-)
johnstok
lol I just got lucky I guess. :-) Better luck next time!
Daniel Spiewak
I agree, If one really want to learn functional you should try Haskell.
Jonke
No mention of scheme? (;
keyofnight
Scheme is nice, but it still has some imperative hooks which allow it to be used in a non-functional manner. Clojure is just as much of a Lisp, but it enforces functional programming much more strictly.
Daniel Spiewak
+3  A: 

It has a fairly comprehensive set of list comprehensions - see Martin Fowler's article. However, it's type system is not as powerful as the likes of Haskell. Also, its focus is not on immutability, as is typical for functional languages.

johnstok
A: 

For most uses, yes. There is (albeit a somewhat limited) ability to do currying, first class functions, and recursion. But due to the high cost of object creation, and method dispatch, deep recursion can get you into trouble quick!

Ruby is plenty capable fitting into a variety of programming "molds", but it's certainly not optimal at most of them.

tanner
A: 

Take a look at Haskell. It's a functional language that syntactically is very similar to Ruby.

JDrago
+1  A: 

You'll also run into issues fairly quickly if you're using any kind of recursive algorithm. Ruby doesn't support tail-recursion, so if you can't reliably use recursion as an iteration technique like you would as the natural way of doing things in a more functional language. Something like:

def foo(n)
  puts n
  foo(n + 1)
end

foo(1)

Will give you

SystemStackError: stack level too deep
    from (irb):2:in `puts'
    from (irb):2:in `foo'
    from (irb):3:in `foo'
    from (irb):5

After a few thousand iterations (depending on your system)

madlep
Your example would be better if actually had a condition to branch out of the recursion. No machine can use recursion indefinitely.
fooledbyprimes
With proper tail-call elimination, you're effectively creating a while loop, and so you can use recursion indefinitely. This is how you'd implement an infinite loop, say in Scheme. The example above is obviously contrived.
Andrew Gwozdziewycz
Doesn't "c" have recursion? I would not call "c" a functional language therefore recursion alone does not define a language to be "functional."
fooledbyprimes
In a proper functional language with tail-recursion optimisation, the above code WOULD be able to run indefinitely. This is equivalent to a while(true) loop in imperative languages. This is a common pattern for server processes in Erlang for example.
madlep
And yes, this is totally contrived :)
madlep