在这个评论中,有人说 Ruby 没有函数,只有方法。如果Ruby没有函数,是不是不能在里面做函数式编程?还是我对“功能”一词感到困惑?
我的意思是“函数式编程”,将函数作为一等对象,而不是禁止可变状态。
在这个评论中,有人说 Ruby 没有函数,只有方法。如果Ruby没有函数,是不是不能在里面做函数式编程?还是我对“功能”一词感到困惑?
我的意思是“函数式编程”,将函数作为一等对象,而不是禁止可变状态。
Blocks 和 Procs 是一流的函数。您可以将它们传递给方法和函数。这就是 Ruby 能够支持像 map 和 reduce 这样的 FP-ish 的方式。
更一般地,一个方法可以被视为一个具有额外关联状态(它的self
)的函数,但是方法在 Ruby 中很少被传递——尽管它们可以传递——所以在实践中它们对于 FP-ish 习惯用法来说并不像块和过程。
是的。方法与功能是一个很好的区别。
很容易将每个特定的方法实现视为一个函数;只需将调用该方法的对象作为额外参数(如果您的语言没有明确传递它;对 Ruby 不太熟悉)。这并不能完全为您提供虚拟方法调用(即,调用的特定实现由运行时的对象确定)。但也很容易将虚拟方法调用想象成调用一个函数,该函数只检查其第一个参数(self
, this
,无论它被调用什么)并使用它来确定要调用哪个方法实现。建立了这些约定后,object.method(param1, param2)
与method(object, param1, param2)
仅在微不足道的句法方式上有所不同。
就个人而言,我认为上述是“事实”,面向对象语言只是为此提供语法糖和优化执行,因为它是编写/执行 OO 程序的核心部分。当您拥有函数但没有真正的类/方法时,这种系统也正是您执行 OO 的方式。
如果您认为方法不是函数,那么使用方法实现函数也很容易。只需拥有一个具有单一方法且没有属性的对象!这也是您使用 Java 等语言进行函数式编程的方式,这些语言坚持一切都是对象,并且不允许您将方法/函数作为一等值传递。
函数式编程所需要做的就是可以作为一等值传递的东西,这些值可用于执行由“事物”的创建者确定的代码(而不是由使用“事物”的代码确定),根据可以访问“事物”的代码的要求。我想不出没有这种能力的编程语言。
一个函数(或者更准确地说是一个过程,因为我们在这里不讨论引用透明性)与只有一个方法的对象同构。
这就是在 Java 中伪造一流过程的方式,例如:使用所谓的SAM接口(单一抽象方法)。这也是 Ruby 中“伪造”一流过程的方式:任何响应call
(并且可能to_proc
)的东西都是一流过程。有一个名为的便利类Proc
,它为诸如柯里化之类的“过程”提供附加功能,并且有-> (x, y) { x + y }
用于创建Proc
类实例的过程的文字语法 ( ),但这两个并不是绝对必要的:
def (i_am_a_first_class_procedure = Object.new).call(x) p x end
i_am_a_first_class_procedure.(42)
# 42
Scala 类似,只是方法被称为apply
,而不是call
。在 Python 中,它是一种名为__call__
.
注意:我在这里忽略了闭包。闭包是有状态的过程,对象当然也可以有状态,所以表示它们并没有真正的问题,但是用具有实例变量的对象来表示自由变量的词法捕获变得相当麻烦。
自然是的,只要语言是图灵完备的。
后来补充:
实际上,Ruby 支持几种典型的函数式编程。Matz 在 Ruby 1.9 的 Proc 类中添加#curry 方法时曾说过“为函数式编程的孩子提供玩具”,但您也可以使用方法进行函数式编程。