随着对函数式编程语言的持续关注,我发现 Smalltalk 和 FPL 之间存在一些相似之处,比如闭包(Smalltalk 中的 BlockClosures)。但是,Smalltalk 不是一种 FPL?
那么,要将其视为一种 FPL,需要什么条件呢?
随着对函数式编程语言的持续关注,我发现 Smalltalk 和 FPL 之间存在一些相似之处,比如闭包(Smalltalk 中的 BlockClosures)。但是,Smalltalk 不是一种 FPL?
那么,要将其视为一种 FPL,需要什么条件呢?
关于函数式编程语言并没有被广泛接受的定义。
如果你将支持一级函数作为定义函数式语言的标准,那么,Smalltalk *就是* 一种函数式语言。
如果你还考虑了不可变性支持、代数数据类型、模式匹配、部分应用等因素,那么,Smalltalk *不是* 一种函数式语言。
我建议你阅读以下相关博客文章(以及它们下面的评论):
Smalltalk不一定是一个“纯函数式语言”(无论那是什么)。然而,自然使用Smalltalk通常会导致函数式代码。(我猜Scala的人们会称之为“对象-函数式”)。
例如,Squeak的Point类具有函数式API:像1@1 translateBy: 1@1
这样的方法返回具有新状态的新Points,而不是改变内部状态。(这使得Point在实践中是不可变的,因为改变对象的内部状态的唯一方式是通过诸如#instVarAt:之类的反射机制。)
在Smalltalk中使用高阶函数(如maps、filters、folds等)是很正常的。鉴于这些被嵌入到Collections API中,编写使用Collections的函数式代码通常比其他方式更容易。
因此,许多人对“函数式编程语言”的定义都有很多定义,因此“Foo是否是FPL”这个问题与“Foo是否是面向对象语言”一样没有用。
话虽如此,以下是我的想法:函数式编程语言是一种自然且习惯性地运用函数式技术的语言:一级函数、避免可变状态、副作用自由函数和高阶函数。
按照这个描述,Smalltalk是一种函数式编程语言。它将一级函数称为“方法”或“块”,具体取决于它们是否具有名称或匿名。对象在实例变量中存储状态。高阶函数只是接受块作为参数的方法。
话虽如此,是的,您可以以非函数式的方式编写Smalltalk。它确实允许可变状态。这是否阻止Smalltalk被称为函数式语言?如果是这样,那么这些语言也不是函数式的:Common Lisp、Erlang(通过进程字典、ets/dets共享状态)。
因此,Smalltalk是一种FPL,因为:
而且,Smalltalk不是FPL,因为:
(一些Smalltalk显然支持不可变对象。我的经验有限,仅限于不支持VM级别的不可变性的Squeak。)
编辑:我不理解igouy需要命名函数定义的需求���除了在对象上定义方法。但无论如何,我们来试试:
Smalltalk at: #func put: [:x | x + 1].
func value: 1.
采用面向对象的编程范式是通过将问题领域实体建模为对象,并使它们相互协作来解决每个问题实例,从而创建程序。 采用函数式编程范式是将问题建模为数学问题,并创建一个数学函数(通过组合其他函数),该函数针对每个问题实例计算问题的解决方案。
我认为,函数式编程语言是一种语言,在使用函数式编程范式解决问题后,语言可以完全按照思考时的方式精确表达该解决方案。如果需要“转换”解决方案的某些部分以适应语言可以表达的内容,则该语言不完全支持您用于思考解决方案的范式。
Smalltalk在大多数情况下可以表达使用面向对象编程范式创建的所有解决方案,但无法原始地表达使用函数式编程范式创建的许多解决方案。这就是为什么我不认为它是函数式编程语言的原因。 尽管不能原始地表达FPL可以的每个解决方案,但Smalltalk非常可扩展,您可以扩展它以能够表达FPL可以的所有解决方案。
Smalltalk是一种纯面向对象的语言,几乎所有代码都是基于对象之间相互交换消息而进行的。而函数式编程则是基于函数调用和函数组合来创建更复杂的行为(避免为数据保存状态,而不像面向对象语言中的对象那样拥有内部状态)。
(def (make_foo initVal1 ... initValN)
(let ((instVar1 initVal1) ... (instVarN initValN))
(define (method1 args) ...)
...
(define (methodN args) ...)
(define (lookup selector)
(cond ((eq? selector 'method1) method1)
...
((eq? selector 'methodN) methodN)
(true doesNotUnderstandCode)))
lookup)) ; returns the lookup function (provides "access into the closure") !
(defMacro (method1 receiver.args)
((receiver selector) args))
(define foo (make_foo 1 2 ...))
(method1 foo ...)
纯函数式语言通常具有不可变的变量,使它们更像数学意义上的变量。
声明函数的方式而不是在类中声明方法的方式
围绕函数而不是对象来构建程序的结构
@Missing Faktor - 但在这个例子中,func不是一个命名函数吗?
|func v|
func := [:x | x + 1].
v := func value: 5.
不是 func
是一个本地变量。你已经将一个匿名函数绑定到本地变量func
。
|func v|
func := [:x | x + 1].
func := 2.
v := func value: 5.
为了看到区别,请查看这个Erlang示例,其中展示了匿名函数和命名函数。