如果 Java 人转向 Scala,C# 转向 F#,那么 Ruby 人该去哪里寻求函数式涅槃呢?
我知道很多 Java 人已经开始关注 Scala,因为它运行在 JVM 上,而 Microsoft 世界的很多人都在关注 F#,但是 Ruby 有什么作为天然的功能继承者呢?
从纯粹的 FP 意义上来说,Ruby 并不缺少任何东西,相反,有些人可能会说它太多了。函数式语言迫使程序员不要过多使用全局变量和其他习惯用法(尽管可以在函数式语言中使用全局变量)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
对于“函数式编程”的含义有两种非常不同的定义。您可以在 Ruby 中执行其中一个操作,但不能执行另一个操作。
这两个定义是:
您可以在 Ruby 中使用一等函数进行编程。它支持一流的功能。事实上,它对它们的支持太多了:有
Proc.new
、proc
、lambda
、< code>Method、UnboundMethod
、块、#to_proc
和->()
(可能还有其他一些我忘记的) 。所有这些行为略有不同,语法略有不同,行为也略有不同和略有不同的限制。例如:其中唯一一个在语法上足够轻量级以至于您可以实际密集使用它的就是块。但是块有一些相当严格的限制:您只能将一个块传递给方法,块不是对象(在面向对象语言中,“一切都是对象”是一个非常严格的限制)限制)并且至少在 Ruby 1.8 中还有一些关于参数的限制。
引用方法是另一件相当尴尬的事情。在 Python 或 ECMAScript 例如,我可以直接说
baz = foo.bar
来引用foo
对象的bar
方法。在Ruby中,foo.bar
是一个方法call,如果我想引用foo
的bar
方法,我不得不说baz = foo.method(:bar)
。如果我现在想调用该方法,我不能只说baz()
,我必须说baz.call
或baz[]
或(在 Ruby 1.9 中)baz.()
。因此,Ruby 中的一流函数并不是真正的一流。它们比二流要好得多,并且足够好™,但它们并不完全是一流。
但一般来说,Ruby 主义者不会仅仅为了一流的功能而放弃 Ruby。 Ruby 的支持足够好,以至于您可能从另一种语言的更好支持中获得的任何优势通常都会被新语言的培训工作或您现在必须提供的其他东西所吞噬。向上。比如 RubyGems 或紧密的 Unix 集成或 Ruby on Rails 或语法或……
然而,FP 的第二个定义是 Ruby 的失败之处。如果您想在 Ruby 中使用数学函数进行编程,那么您将面临一个痛苦的世界。您不能使用绝大多数 Ruby 库,因为它们中的大多数都是有状态的、有效的、鼓励突变的或者是不纯粹的。出于同样的原因,您不能使用标准库。您无法使用核心库。您不能使用任何核心数据类型,因为它们都是可变的。你可以只是说“我不在乎它们是可变的,我不会改变它们并总是复制它们”,但问题是:其他人仍然可以改变它们。此外,由于它们是可变的,Ruby 无法优化复制,并且垃圾收集器也无法针对此类工作负载进行调整。
它就是行不通。
还有一些功能实际上与函数式编程无关,但大多数函数式语言往往都具有,而 Ruby 却缺少这些功能。例如,模式匹配。在 Ruby 1.9 中更积极地使用枚举器之前,惰性也不是那么容易实现的。还有一些东西可以与严格的
Enumerable
或Array
一起使用,但不能与惰性的Enumerator
一起使用,尽管实际上没有理由让它们这样做要求严格。对于 FP 的这个定义,将 Ruby 抛在后面绝对是有意义的。
Rubyists 蜂拥而至的两种主要语言是 Erlang 和 Clojure.它们对于 Ruby 来说都是相对较好的匹配,因为它们都是动态类型的,具有与 Ruby 类似的 REPL 文化,而且(这更像是 Rails 的东西,而不是 Ruby 的东西)在 Web 上也非常好。他们仍然拥有相当小而热情的社区,原始语言的创建者仍然活跃在社区中,非常注重做新的、令人兴奋的和前卫的事情,所有这些都是 Ruby 社区所具有的特征。
当有人在 RubyConf 上展示 1993 年的原始介绍视频“Erlang:电影”时,人们对 Erlang 产生了兴趣。 2006 年。一些备受瞩目的 Rails 项目开始使用 Erlang,例如 PowerSet 和 GitHub。对于 Ruby 爱好者来说,Erlang 也很容易掌握,因为它不像 Haskell 或 干净。 Actor 的内部是相当纯粹的,但发送消息本身的行为当然是一个副作用。使 Erlang 易于掌握的另一件事是,当您遵循 Alan Kay 对面向对象编程的定义。
Clojure 是 Rubyist 工具带中最近新增的成员。我想它的流行主要是由于 Ruby 社区终于接受了 JVM ≠ Java 的想法并接受了 JRuby 然后他们开始研究 JVM 上还有哪些其他有趣的东西。再说一次,Clojure 比 Haskell 等其他函数式语言和 Scheme 等其他 Lisp 语言更加实用,而且更简单和更简单。比 CommonLisp 更现代,因此它非常适合 Rubyists。
Clojure 的另一个很酷的事情是,因为 Clojure 和 Ruby 都在 JVM 上运行,所以您可以将它们组合起来。
“Programming Clojure”(Stuart Halloway)的作者是一位(前?)Rubyist ,例如,Phil Hagelberg,Leiningen Clojure 构建工具。
然而,Rubyists 也在关注 Scala(作为更实用的静态类型 FP 语言之一)和 Haskell(作为更优雅的之一)。然后还有诸如 Scuby 和 Hubris 是让您分别将 Ruby 与 Scala 和 Haskell 集成的桥梁。 Twitter 决定首先将其部分低级消息基础设施从 MySQL 迁移到 Ruby,然后从 Ruby 迁移到 Scala,这一决定也广为人知。
F# 似乎根本没有发挥任何作用,可能是由于对 Microsoft Ruby 社区拥有的所有东西的非理性恐惧。 (顺便说一句,这似乎几乎没有根据,因为 F# 团队总是为 Mono 提供可用的版本。)
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:
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 thebar
method of thefoo
object. In Ruby,foo.bar
is a method call, if I want to refer to thebar
method offoo
, I have to saybaz = foo.method(:bar)
. And if I now want to call that method, I cannot just saybaz()
, I have to saybaz.call
orbaz[]
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 strictEnumerable
s orArray
s but not with lazyEnumerator
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 人员在 JVM 上使用一种语言,并且想要一种与其运行时兼容的功能更强大的语言,因此他们转向 Scala。
C# 人员在 CLR 上使用一种语言,并且想要一种与其运行时兼容的功能更强大的语言,因此他们转向 F#。
Ruby 人们正在使用一种已经非常实用的语言,并且他们在许多底层运行时上使用它(JRuby、IronRuby、MRI、MacRuby、Rubinius 等)。我认为它没有一个自然的功能继承者,甚至不需要一个。
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.
任何版本的 Lisp 都应该没问题。
Any version of Lisp should be fine.
Ruby 本身是一种函数式编程语言,所以我没有看到任何使用 ruby 的 FP 的特殊方言。
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.
假设 Ruby 人们不只是自己使用 JVM,我认为大多数人会采用 Erlang,这是另一种动态类型语言。
Assuming Ruby people don't just go to the JVM themselves, I think most would adopt Erlang, being another dynamically typed language.
Ruby 不像 Lisp 那样功能强大,但它的功能足够让您可以以一种有趣的方式进行一些函数式编程。 (与尝试使用 C# 等函数式编程不同)
此外,它实际上迫使您在某些语法中采用函数式范例,例如大量使用块和yield。 (我在学习 Ruby 后就爱上了它)。
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).