ruby特点,RUby什么意思
为什么Ruby是一个流行的LISP?
为什么Ruby是一个流行的LISP?
翻译于2007年8月13日04: 55: 38 已有7441人查看过它 4人对它发表过评论。
几年前,我考虑过Ruby,决定忽略它。Ruby没有Python流行,也没有LISP强大。我为什么要把时间花在这上面?当然,我们可以反过来考虑这件事。如果Ruby比LISP流行,比Python强大怎么办?这足以让Ruby变得有趣吗?在回答这个问题之前,我们应该确定是什么让LISP如此强大。保罗格拉厄姆已经写了一些令人信服的文章来说明LISP的优点。出于讨论的目的,我将这些文章的内容总结为两点:*LISP是一种紧凑的函数式语言。*LISP有可编程的宏。正如您将在下面看到的,Ruby也是一种函数式语言,它比我想象的更好地模拟了宏。Ruby是一种比LISP更紧凑的函数式语言。简洁的语言可以让你简洁而明确地表达你的意思。一眼就能看出来。
几年前,我考虑过Ruby,决定忽略它。Ruby没有Python流行,也没有LISP强大。我为什么要把时间花在这上面?
当然,我们可以反过来考虑这件事。如果Ruby比LISP流行,比Python强大怎么办?这足以让Ruby变得有趣吗?
在回答这个问题之前,我们应该确定是什么让LISP如此强大。保罗格拉厄姆已经写了一些令人信服的文章来说明LISP的优点。为了便于讨论,我将这些文章的内容归纳为两点:
LISP是一种紧凑的函数式语言。
LISP有可编程的宏。
正如您将在下面看到的,Ruby也是一种函数式语言,它比我想象的更好地模拟了宏。
Ruby是一种比LISP更紧凑的函数式语言。
简洁的语言可以让你简洁而明确地表达你的意思。一眼就能看到更多的程序,再也没有bug藏身的地方了。达到一定程度后,让你的程序更紧凑的唯一方法就是使用更强大的抽象。
lambda是一个特殊而强大的抽象概念。使用lambda,您可以立即创建一个新函数并将其传递给其他函数,甚至可以保存它以备后用。例如,如果您想将表格中的每个数字加倍,您可以写:
(mapcar(lambda(n)(* n ^ 2))我的列表)
Mapcar通过转换mylist中的每个元素来构建新的列表。在这个例子中,这个转换可以理解为“对于每个值n,乘以2。”在JavaScript中用function替换lambda可能更清楚:
map(function (n) { return n * 2 },mylist)
当然,这只是提示您可以使用lambda做些什么。喜欢这种编程风格的语言被称为函数式语言,因为它们使用函数。一旦你学会阅读一个用紧凑的函数式语言编写的程序,你会发现它真的简洁明了。
Ruby在函数式编程中如何与Lisp竞争?让我们考虑一个保罗格拉厄姆的经典例子,一个函数,并建立一个累加器:
(defun foo(n)((I)(incf n I)))
如果用Ruby编写,这段代码会更短,并且C用户会更熟悉这种写法:
def foo(n) lambda {i n=i} end
acc=foo 3
根据呼叫(1) # - 4
acc.call(10) # - 14
acc.call(0) # - 14
但是Ruby中有一个有趣的特例,它允许我们输入更少的单词。考虑一个需要作为参数的(非常愚蠢的)函数:
$对每个自然数调用一次“fn”。
(defun每个自然数(fn)
(从1 do开始循环n(funcall fn n)))
$打印1,2,3.
(每个自然数
(lambda (n)(格式t ~D~% n)))
现在,我们可以用Ruby编写相同的函数:
定义每个自然数(fn)
n=0
loop { fn.call(n=1) }
目标
each _ natural _ number({ n puts n })
但是我们可以做得更好。让我们用yield代替lambda和fn:
定义每个自然数
n=0
循环{产量n=1 }
目标
每个自然数{n puts n }
是的,yield是一种有特定目的的技能,它只在那些需要单个lambda的函数中起作用。但是在高功能代码中,yield对我们很有帮助。比较:
[1,2,3].映射{n n*n }。拒绝{n n%3==1 }
(remove-if (lambda (n) (=(mod n 3) 1))
(mapcar (lambda (n) (* n n))
(1 2 3)))
在一个大型程序中,这很重要。(LISP的论点是,你可以写一个reader宏,让lambda更简洁。但是很少有人知道。)
Ruby可以给你几乎80%你想要的宏。
对此,LISP用户会说:“lambda的语法很棒,但是宏呢?”这是一个好问题。LISP宏是一个函数,并且:
由编译器运行
将自定义语法转换成原始LISP。
宏最常见的用途是避免键入过多的lambda:
(每个自然数的defmacro表达式)
`(每个自然数((,n),expr)))
(每个自然数n
(格式t ~D~% n))
Defmacro定义了一个需要一个列表作为参数的函数,并返回另一个列表。在这个例子中,每次编译器看到-each-natural-number时都会调用我们的宏。它使用LISP的“反引号”语法从模板快速构造一个列表,并替换N和expr。然后,该列表被传递回编译器。
当然这个宏在Ruby中是没用的,因为Ruby中没有这个宏要解决的问题。
宏的第二个最常见的用途是通过构建小型语言来定义事物:
$生成一些到我们数据库的绑定
$使用假设的“LISP on Rails”
(定义模型顺序()
(属于客户)
(有-多项:依赖?t))
使用Ruby on Rails,我们可以这样写:
类别顺序ActiveRecord:Base
属于_客户
has_many :items,dependent=true
目标
这里,belongs_to是一个类方法。当被调用时,一批成员方法将被添加到顺序中。方法的实现比较难看,但是界面真的很美。
对任何类似宏的函数的真正测试是迷你语言是否经常被建立。Ruby在这方面取得了不错的成绩:除了Rails,还有Rake(用来写Makefiles)、Needle(连接组件)、OptionParser(解析命令行选项)、DL(与C APIs交互)等等,数不胜数。Ruby程序员用Ruby写任何东西。
当然,还有很多高级的LISP宏不能简单移植到Ruby中。特别是那些编译迷你语言的宏还没有出现,尽管有足够的工作使它们成为可能。(Ryan Davis在这个方向做了一些很有前途的工作,ParseTree和RubyInline。我会写一些相关技术的文章。)
Ruby拥有优秀的库和社区,增长势头良好。
所以如果LISP还是比Ruby强大,为什么不用LISP呢?反对LISP编程的常见原因有:
没有足够的图书馆。
我们不能雇佣LISP程序员。
LISP已经20年没见过了。
这些都不是压倒性的理由,但确实值得考虑。
曾几何时,人们认为Common Lisp标准库过于庞大。然而今天,人们苦于它的体积小。Java的手册可以填满一面墙,Perl的CPAN档案有可以满足你能想象的任何目的的模块。相比之下,Common Lisp连网络通信的标准方法都没有。
同样,LISP程序员也太少了。如果你在波士顿附近,有一小群黑客可以创造出神奇的灰发。在其他地方,渴望成功的年轻黑客们分散了。LISP永远是小众语言。
另一方面,Ruby越来越受欢迎。最大的动力似乎是始于2004年末的Rails。如果你想开一家公司,每个可能的员工都是Rails的粉丝已经很普遍了。Rails将很快被整合到一般的web开发中,并最终从中产生巨大的商机。
Ruby已经花了足够多的时间来开发一个优秀的标准库和大量的附加库。如果你需要下载网页,解析RSS,生成图形或者调用SOAP API,你需要的一切都已经做好了。
现在,如果你必须在强大的语言和流行的语言之间做出选择,选择强大的可能会更好。但是如果强大的功能是次要的,那么流行的语言就具备了所有的优势。2005年,我会考虑很长一段时间很难从Ruby中选择LISP。我可能只在需要优化代码时,或者需要宏充当全功能编译器时才这样做。
(感谢Michael Fromberger审阅了本文的早期草稿。)
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。