I know a lot of Java people have started looking at Scala since it runs on the JVM, and a lot of people in the Microsoft world are looking at F#, but what does Ruby have as a natural functional successor?
In a pure FP sense Ruby doesn't lack anything, instead it has too much some may say. A functional language forces the programmer to not use global variables and other idioms so much (although it is possible to use globals in functional languages)
There's two very different definitions of what "functional programming" means. You can kind-of do the one in Ruby, but you cannot do the other.
Those two definitions are:
- programming with first-class functions and
- programming with mathematical functions
You can kind-of program with first-class functions in Ruby. It has support for first-class functions. In fact, it has too much support for them: there is Proc.new
, proc
, lambda
, Method
, UnboundMethod
, blocks, #to_proc
and ->()
(and probably some others that I forget).
All of these behave slightly differently, have slightly different syntax, slightly different behavior and slightly different restrictions. For example: the only one of these which is syntactically lightweight enough that you can actually use it densely, is blocks. But blocks have some rather severe restrictions: you can only pass one block to a method, blocks aren't objects (which in an object-oriented language in wich "everything is an object" is a very severe restriction) and at least in Ruby 1.8 there are also some restrictions w.r.t parameters.
Referring to a method is another thing that is fairly awkward. In Python or ECMAScript for example, I can just say baz = foo.bar
to refer to the bar
method of the foo
object. In Ruby, foo.bar
is a method call, if I want to refer to the bar
method of foo
, I have to say baz = foo.method(:bar)
. And if I now want to call that method, I cannot just say baz()
, I have to say baz.call
or baz[]
or (in Ruby 1.9) baz.()
.
So, first-class functions in Ruby aren't really first-class. They are much better than second-class, and they are good enough™, but they aren't fully first-class.
But generally, Rubyists do not leave Ruby just for first-class functions. Ruby's support is good enough that any advantages you might gain from better support in another language usually is eaten up by the training effort for the new language or by something else that you are accustomed to that you must now give up. Like, say RubyGems or tight Unix integration or Ruby on Rails or syntax or …
However, the second definition of FP is where Ruby falls flat on its face. If you want to do programming with mathematical functions in Ruby, you are in for a world of pain. You cannot use the absolute majority of Ruby libraries, because most of them are stateful, effectful, encourage mutation or are otherwise impure. You cannot use the standard library for the same reasons. You cannot use the core library. You cannot use any of the core datatypes, because they are all mutable. You could just say "I don't care that they are mutable, I will simply not mutate them and always copy them", but the problem is: someone else still can mutate them. Also, because they are mutable, Ruby cannot optimize the copying and the garbage collector isn't tuned for that kind of workload.
It just doesn't work.
There is also a couple of features that have really nothing to do with functional programming but that most functional languages tend to have, that Ruby is missing. Pattern matching, for example. Laziness also was not that easy to achieve before Enumerator
s were more aggressively used in Ruby 1.9. And there's still some stuff that works with strict Enumerable
s or Array
s but not with lazy Enumerator
s, although there's actually no reason for them to require strictness.
And for this definition of FP, it definitely makes sense to leave Ruby behind.
The two main languages that Rubyists have been flocking to, are Erlang and Clojure. These are both relatively good matches for Ruby, because they are both dynamically typed, have a similar REPL culture as Ruby, and (this is more a Rails thing than a Ruby thing) are also very good on the web. They have still pretty small and welcoming communities, the original language creators are still active in the community, there is a strong focus on doing new, exciting and edgy things, all of which are traits that the Ruby community also has.
The interest in Erlang started, when someone showed the original 1993 introduction video "Erlang: The Movie" at RubyConf 2006. A couple of high-profile Rails projects started using Erlang, for example PowerSet and GitHub. Erlang is also easy to master for Rubyists, because it doesn't take purity quite as far as Haskell or Clean. The inside of an actor is pretty pure, but the act of sending messages itself is of course a side-effect. Another thing that makes Erlang easy to grasp, is that Actors and Objects are actually the same thing, when you follow Alan Kay's definition of object-oriented programming.
Clojure has been a recent addition to the Rubyist's toolbelt. Its popularity is I guess mostly driven by the fact that the Ruby community has finally warmed up to the idea that JVM ≠ Java and embraced JRuby and then they started to look around what other interesting stuff there was on the JVM. And again, Clojure is much more pragmatic than both other functional languages like Haskell and other Lisps like Scheme and much simpler and more modern than CommonLisp, so it is a natural fit for Rubyists.
Another cool thing about Clojure is that because both Clojure and Ruby run on the JVM, you can combine them.
The author of "Programming Clojure" (Stuart Halloway) is a (former?) Rubyist, for example, as is Phil Hagelberg, the author of the Leiningen build tool for Clojure.
However, Rubyists are also looking at both Scala (as one of the more pragmatic statically typed FP languages) and Haskell (as one of the more elegant ones). Then there is projects like Scuby and Hubris which are bridges that let you integrate Ruby with Scala and Haskell, respectively. Twitter's decision to move part of their low-level messaging infrastructure first from MySQL to Ruby, then from Ruby to Scala is also pretty widely known.
F# doesn't seem to play any role at all, possibly due to an irrational fear towards all things Microsoft the Ruby community has. (Which, BTW, seems mostly unfounded, given that the F# team has always made versions available for Mono.)
Java people are using a language on the JVM and want a more functional one compatible with their runtime, so they go to Scala.
C# people are using a language on the CLR and want a more functional one compatible with their runtime, so they go to F#.
Ruby people are using a language that's already pretty functional, and they're using it on a number of underlying runtimes (JRuby, IronRuby, MRI, MacRuby, Rubinius, etc...). I don't think it has a natural functional successor, or even needs one.
Any version of Lisp should be fine.
Ruby it self is a kind of Functional programming language, So I don't see any special dialects for FP using ruby.
In hype level, Haskell.
Assuming Ruby people don't just go to the JVM themselves, I think most would adopt Erlang, being another dynamically typed language.
Ruby isn't as functional as say Lisp, but it is just functional enough that you can do some functional programming in a good fun way. (unlike trying to do functional programming in something like C#)
Also, it actually forces you into functional paradigms in some of its syntax, such as the heavy use of blocks and yield. (which I fell in love with after learning Ruby).
精彩评论