Ruby是功能语言吗?


88

维基百科说Ruby是一种功能语言,但我不相信。为什么或者为什么不?


4
可能是因为您的问题很简短,尽管我个人对此都没有问题!
ljs

已经有了很好的答案,所以仅作为补充,它们是讨论FP和Ruby的一对内容:code.google.com/p/tokland/wiki/RubyFunctionalProgramming slideshare.net/tokland/functional-programming-with-ruby-9975242
tokland

1
如果有人对此主题感兴趣,请观看本指南,您将了解如何以函数方式使用ruby,函数式编程的根源,为何ruby不是功能语言,即使它能够进行函数式编程也是如此:youtube .com / watch?v = 5ZjwEPupybw
maddin2code 2014年

Answers:


29

我绝对可以认为您可以在Ruby中使用功能样式。

能够以功能样式进行编程的最关键方面之一是该语言是否支持高阶函数... Ruby就是这么做的。

也就是说,以非功能风格使用Ruby编程也很容易。函数样式的另一个关键方面是不具有状态,并且具有真正的数学函数,这些函数对于给定的一组输入总是返回相同的值。这可以在Ruby中完成,但是并不能像Haskell这样功能更严格的语言强制执行。

所以,是的,它支持函数式风格,但是它也可以让您以非函数式风格进行编程。


4
使用此标准,您会说Smalltalk因为有块而起作用了吗?
OscarRyz

好的答案,但是一个挑剔-高功能不是严格要求的功能样式。例如,您可以通过定义函数对象并将其组成以获得与高阶函数相同的效果,从而实现Java中的函数样式(不具有一等/高阶函数)。
mikera 2011年

2
只是,想声明@peter提出的问题Is ruby a functional language?,直接回答是一个简单的否。Ruby是一种具有某些功能特性的面向对象语言。
埃里亚斯·佩雷斯

58

语言是否是功能性语言无关紧要。函数式编程是一个论文,最好由Philip Wadler(函数式编程的本质)和John Hughes(为什么函数式编程很重要)进行解释。

一个有意义的问题是,“ Ruby在实现函数式编程方面的表现如何?” 答案是“非常糟糕”。

我刚刚在此发表了演讲。这是幻灯片。


3
您提供的幻灯片没有提到Ruby为什么“非常难以实现FP的理论”。为什么C#比Java更适合(好的,更简单的匿名函数?)?是因为您可以在Ruby中使用全局变量吗?
kizzx2'9

7
没有幻灯片没有详细介绍,因为这是一个广泛的话题。例如,冒着过度简化的风险,Ruby实施了一个评估模型(按值调用),以确保程序的非组合性。这样的含义很容易被低估。Ruby还接受了程序是一系列效果的想法。也就是说,Ruby竭尽全力使使用任何其他计算模型变得困难/棘手。希望这篇简短的评论对您有所帮助。
托尼·莫里斯

2
+1指出在将语言分类为功能性时的歧义。地狱,我已经写了函数C!
伊莱(Eli)

1
为什么C#比Ruby更适合?
dan_l

1
有效的仅链接的答案,因为它将解释的关键部分(实际上是整个解释)外包给了外部链接。既然链接消失了,答案就变得毫无用处。
ivan_pozdeev

34

Ruby确实支持更高级别的功能(请参阅Array#map,inject和select),但它仍然是一种命令式,面向对象的语言。

它避免可变状态是功能语言的主要特征之一。功能语言不像Ruby,C,Java或任何其他命令式语言那样具有变量的概念。

功能语言的另一个关键特性是,它着重于根据“什么”而不是“如何”来定义程序。当使用OO语言进行编程时,我们编写类和方法以将实现(“方式”)与“什么”(类/方法名)隐藏起来,但是最后这些方法仍然是使用一系列语句编写的。在功能语言中,即使在最低级别,也不会指定执行顺序。


3
我同意您的大多数说法,但是,我不同意“函数式语言不像Java等语言那样具有变量的概念”。在haskell中,可以在纯函数中使用变量,甚至可以将函数分配给变量,最大的不同是,一旦分配了变量,此后将无法对其进行修改。
HHC

6
根据定义,HHC变量是可以更改的值。您所说的是价值观。
Scala Newb 2014年

实际上,Haskell的“不可修改变量”只是没有参数(定义)的常量函数。
raindev 2014年

16

我认为,支持或具有以一种功能风格的语言进行编程的能力不是功能语言。

如果我想伤害我的同事,甚至几个月以后我什至可以以功能风格编写Java代码。

拥有功能性语言不仅与您可以做什么有关,例如高阶函数,一流函数和currying。这也关乎您不能做什么,例如纯函数的副作用。

这很重要,因为这是函数程序或通用函数代码更易于推理的很大一部分原因。而且,当代码更易于推理时,错误会变得更浅,并浮到可修复的概念表面,从而减少了错误代码。

Ruby的核心是面向对象的,因此,尽管它对功能样式具有相当好的支持,但它本身并不是功能语言。

无论如何,那是我的非科学观点。

编辑: 回顾过去,考虑到到目前为止我已经收到的关于此答案的精美评论,我认为面向对象与功能的比较是苹果和橘子之一。

真正的区别在于执行上是否有意义。功能语言将表达式作为其主要的语言结构,执行顺序通常未定义或定义为惰性。可能执行严格,但仅在需要时使用。在一种指示性语言中,严格执行是默认设置,虽然可以执行懒惰执行,但这样做通常很笨拙,并且在许多情况下可能会产生不可预测的结果。

现在,这是我的非科学观点。


我认为您可以比Java更好地调用Ruby函数....不,Ruby不是严格的函数,但是在其中使用函数样式非常容易...而且非函数样式的同事可以轻松将其更改回非功能状态
Mike Stone

1
是的,迈克,如果您想以功能风格进行编码,那么Ruby是Java的巨大改进。我只是用Java夸大其词。
克里斯·韦斯特

那么既然D具有纯函数,您会称D为一种功能语言吗? digitalmars.com/d/2.0/function.html#pure-functions
彼得·伯恩斯

3
许多人考虑使用Lisp和Scheme函数语言,这在很大程度上是由于匿名函数的广泛使用。但是,它们缺乏有保证的纯功能。将术语限制为支持纯函数的语言似乎过于严格。
skymt

13

Ruby必须满足以下要求才能“真正”起作用。

不变值:一旦设置了“变量”,就无法更改。在Ruby中,这意味着您必须有效地将变量视为常量。语言未完全支持,您将必须手动冻结每个变量。

无副作用:传递给定值时,函数必须始终返回相同的结果。这与拥有不变的价值并存。函数永远不能获取值并更改它,因为这将导致与返回结果相切的副作用。

高阶函数:这些函数允许将函数用作参数或将函数用作返回值。可以说,这是所有功能语言中最关键的功能之一。

Currying:由高阶函数启用,currying会将一个带有多个参数的函数转换为一个带有一个参数的函数。这与部分函数应用程序并驾齐驱,该函数将多参数函数转换为需要较少参数的函数。

递归:通过从自身内部调用函数来循环。当您无权访问可变数据时,将使用递归来构建和链接数据构造。这是因为循环不是功能性概念,因为它需要传递变量以存储给定时间的循环状态。

延迟评估或延迟评估:将值的处理延迟到实际需要时才进行。例如,如果您有一些代码生成了启用了延迟求值的斐波纳契数的列表,那么直到结果中的某个值被另一个函数(例如看跌期权)要求时,才可以对其进行处理和计算。

提议(只是想一想) ,如果能有某种定义来有一个mode指令来声明具有功能范式的文件,那么我将非常高兴

模式“功能化”


2
别客气。我想邀请您阅读有关功能语言的信息。Lisp是所有功能语言,ML(CAML)和Erlang / Elixir的祖父母。它确实改变了您对事物的看法。我绝对不会是专家,而是一名计算机科学的恒定学生会喜欢阅读和学习新知识。
埃里亚斯·佩雷斯

井井有条的答案。本来会喜欢红宝石如何很好地支持这些东西的其他探索。我相信在ruby中都支持/可能使用高阶函数,currying和递归,如果我错了,请纠正我。
Michael Dorst,


4

Ruby是一种面向对象的语言,可以支持其他范例(功能,命令式等)。但是,由于Ruby中的所有内容都是对象,因此它主要是一种OO语言。

例:

“ hello” .reverse()=“ olleh”,每个字符串都是一个字符串对象实例,依此类推。

这里这里阅读


我从来没有真正理解过“一切都是对象”如何使Ruby更加面向对象。我确实同意Ruby主要是面向对象的,但是“一切都是对象”实际上仅意味着没有“原始”类型,考虑到原始的存在,这与开发人员以OO风格编写程序的能力关系不大。类型通常只是意味着有四种或五种没有任何方法的类型。
Michael Dorst

4

这取决于您对“功能语言”的定义。就个人而言,我认为该术语作为绝对术语使用时本身就很成问题。成为“功能性语言”的更多方面不只是语言功能,而且还取决于您所寻找的位置。例如,围绕语言的文化在这方面非常重要。它鼓励功能性风格吗?那可用的库呢?它们是否鼓励您以功能性方式使用它们?

例如,大多数人会将Scheme称为功能语言。但是Common Lisp呢?除了多重/单个命名空间问题和保证的消除尾部调用(某些CL实现也支持此功能,具体取决于编译器设置)之外,没有什么使Scheme成为比Common更适合函数式编程的语言了。 Lisp仍然是大多数Lispers都不会将CL称为功能语言。为什么?因为围绕它的文化在很大程度上取决于CL的命令性功能(例如,LOOP宏,大多数Schemers可能会不赞成这样做)。

另一方面,C程序员可能会认为CL是一种功能语言。毕竟,用Lisp方言编写的大多数代码在样式上肯定比您通常的C代码块具有更多的功能。同样,与Haskell相比,Scheme非常是命令式语言。因此,我认为不可能有明确的是/否答案。是否调用语言功能很大程度上取决于您的观点。


Haskell用什么方式不是纯粹的功能语言?还是Miranda(一种鲜为人知的函数式编程语言)呢?courses.cs.washington.edu/courses/cse505/99au/functional/… “ Haskell是一种标准的纯功能语言,”
barlop 2015年

2

我认为Ruby并不是真正的多范式语言。希望将自己喜欢的语言标记为在许多不同领域有用的语言的人倾向于使用多范式。

我将描述Ruby是一种面向对象的脚本语言。是的,函数是一流的对象(或类似的对象),但这并不能使它真正成为一种功能语言。IMO,我可能会补充。


4
语言的类型由其支持的编程样式定义。而这又取决于它的功能。一等和匿名函数=最少的函数编程。Ruby支持OO编程,但不需要OO编程:您无需定义类。因此,多范式。
skymt

2

递归在函数式编程中很常见。几乎所有语言都支持递归,但是如果没有尾部调用优化(TCO),则递归算法通常无效。

函数式编程语言能够优化尾递归,并且可以在恒定空间中执行此类代码。一些Ruby实现确实优化了尾递归,而其他的则没有,但是总的来说,不需要Ruby实现来进行TCO。请参见Ruby是否执行尾部调用优化?

因此,如果您编写某种Ruby功能样式并依靠某些特定实现的TCO,则您的代码在另一个Ruby解释器中可能会非常无效。我认为这就是为什么Ruby不是功能语言(Python也不是)的原因。


TCO很有趣,因为它从本质上改变了程序的行为。在某些情况下,该程序对程序不可见,但在其他情况下,例如异常回溯。因此,并非总是适当的优化。
ioquatix 2014年

2

严格来说,将语言描述为“功能性”是没有意义的。大多数语言都可以进行功能编程。甚至C ++也是如此。

功能样式或多或少是命令性语言功能的子集,由语法糖和一些编译器优化(如不变性和尾递归展平化)支持,

后者可以说是针对实现的次要技术,与实际语言无关。x64 C#4.0编译器执行尾递归优化,而x86出于某种愚蠢的原因却没有。

语法糖通常可以在某种程度上解决,特别是如果该语言具有可编程的预编译器(即C的#define)。

问“语言__是否支持命令式编程?”可能会更有意义,例如,对于Lisp,答案是“否”。


1

请看看这本书的开头:“ A-Great-Ruby-eBook”。它讨论了您要问的非常具体的主题。您可以在Ruby中进行不同类型的编程。如果您想要像功能一样进行编程,则可以做到。如果您想按势进行编程,则可以这样做。这是一个定义问题,到底Ruby的功能如何。请查看camflan用户的回复。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.