为什么smalltalk不是函数式编程语言?

时间:2010-08-20 02:26:24

标签: programming-languages functional-programming oop smalltalk

随着人们对函数式编程语言的兴趣,我看到了Smalltalk和FPL之间的一些相似之处,即闭包(Smalltalk中的BlockClosures)然而,Smalltalk不是FPL?

需要考虑什么呢?

9 个答案:

答案 0 :(得分:27)

函数式编程语言没有公认的定义。

如果将函数式语言定义为支持第一类函数的语言,那么是的,Smalltalk *是一种函数式语言。

如果您还考虑了支持不变性,代数数据类型,模式匹配,部分应用等因素,那么,Smalltalk *不是*函数式语言。


我建议您阅读以下相关博客文章(以及下面的评论):

答案 1 :(得分:22)

Smalltalk可能不是“纯函数式语言”(无论可能是什么)。但是,Smalltalk的自然使用通常会产生功能代码。 (我猜Scala人会称之为“对象功能”。)

例如,Squeak的Point类有一个功能API:像1@1 translateBy: 1@1这样的方法返回具有新状态的新Points,而不是改变内部状态。 (这使得Point实际上是不可变的,因为改变对象内部状态的唯一方法是通过#instVarAt:等反射机制。)

在Smalltalk中使用高阶函数(如地图,滤镜,折叠等)是很正常的。鉴于这些已经被集成到Collections API中,编写以功能性方式使用Collections的代码通常更容易。

很多人对“函数式编程语言”的定义如此之多,以至于“Foo a FPL”这个问题就像“Foo是一种面向对象的语言”一样毫无用处。

话虽如此,这是我的两分钱:函数式编程语言是一种使用函数技术自然惯用的语言:一流的函数,避免可变状态,无副作用函数,高阶函数。

通过该描述,Smalltalk是一种函数式编程语言。它根据是否命名或匿名调用一阶函数“方法”或“块”。对象在实例变量中存储状态。高阶函数是将块作为参数的简单方法。

话虽如此,是的,你可以用非功能性方式编写Smalltalk。它确实允许可变状态。这会阻止Smalltalk被称为功能语言吗?如果是这样,这些语言都不起作用:Common Lisp,Erlang(通过进程字典共享状态,ets / dets)。

因此,简而言之, Smalltalk是一个FPL 因为:

  • 函数是第一类实体(对象,在Smalltalk中 - 准确地说是CompiledMethods或BlockClosures)。
  • Smalltalk支持闭包(它称之为块)。
  • Smalltalk允许用户以自然,惯用的方式进行功能性写作。

Smalltalk不是FPL ,因为:

  • 作为程序员,您必须确保您的数据结构(对象)是不可变的(通过让setter / mutators返回具有变异状态的对象的副本)。
  • 作为程序员,您必须确保您的方法(功能)没有副作用。

(有些Smalltalks显然支持不可变对象。我的经验仅限于Squeak,它不支持VM级别的不变性。)

编辑:除了通过在对象上定义方法之外,我不理解igouy对命名函数定义的需求。但无论如何,我们走了:

Smalltalk at: #func put: [:x | x + 1].
func value: 1.

答案 2 :(得分:13)

使用面向对象的范例进行编程是通过识别问题域实体并将其建模为对象来创建程序,然后使它们在它们之间协作以解决每个问题实例。 使用Functional范例进行编程是将问题建模为一个数学问题,并创建一个数学函数(通过编写其他函数),为每个问题实例计算问题解决方案。

在我看来,函数式编程语言是一种语言,它为使用函数式编程范例解决的问题提供了解决方案,该语言可以完全按照它的想法表达该解决方案。如果您需要“转换”解决方案的某些部分以使其适合语言可以表达的内容,那么它并不完全支持您用于思考解决方案的范例。

Smalltalk在大多数情况下可以表达使用面向对象编程范例创建的所有解决方案,但它无法原始地表达使用功能编程范例创建的许多解决方案。这就是为什么我不认为它是一个FPL。 尽管没有原始能够表达FPL可以解决的每个解决方案,但Smalltalk极其可扩展,您可以扩展它以表达FPL可以提供的所有解决方案。

答案 3 :(得分:7)

Smalltalk是一种纯粹的面向对象语言,几乎所有代码基本上都是交换消息的对象。函数式编程面向函数调用,以及函数之间的组合以创建更复杂的行为(避免数据的状态,而不是对象在任何面向对象语言中具有的内部状态)。

答案 4 :(得分:5)

纯粹的函数式语言通常具有不可变的变量,使它们更像数学意义上的变量。

答案 5 :(得分:5)

语言不会通过命名函数成为函数式语言 - 根据该定义,C将是有用的!更重要的是数学意义上的功能语义,结果仅取决于参数(特别是:没有副作用)。通过这个定义,可以通过setter修改的对象与函数式编程风格相反。但是,正如已经指出的那样,如果禁止副作用,偶数对象也可以用于函数样式(Rectangle示例)。 而且,顺便说一句。在具有方法的对象和一组函数之间存在二元性,这些函数在私有状态的闭包中定义(有关详细信息,请参阅SICP)。他们可以相互模拟:

(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 ...)

以上是模拟“纯”功能对象,并且在语义上与很多Smalltalk代码相同!但是,要实现setter方法,必须添加一个方法(set!instVar newValue)。并且,因为设置!是无功能的,打破了该计划的“功能”。

总结:看一下语义,而不是源,luke!

答案 6 :(得分:2)

谢谢大家的所有答案。

我会在这里添加我的,这基本上是我(可能想念)对你的理解。

我认为调用OO或FP的标准是“东西”是使用该语言构建的;不是多么容易或难以做到这一点,我的意思是,所使用的心理范式。

例如,如图所示,在Scala中输入内容可能比在OCaml中更难,但这并不会减少FPL(可能不完整或不纯,但绝对有效);因为Scala的目标是使用函数作为主要构建块,而不是对象。

另一方面,如果样式或目标是使用其他工件,那么使用语言编写函数容易使其无法正常工作。例如,Smalltalk使得编写匿名块或提供可插入的排序比较器非常容易,但这并不能使它成为任何功能,因为重点是使用对象并传递消息。 Blockclosures只是一种编码这些消息(不是函数)的机制,即使它们看起来就像它们是函数一样。

混乱来了,因为OO和FP是正交的(如通过twitter所述的Rahul),因此,它看起来像Smalltalk中的编码消息,看起来非常像Scala中的匿名函数。但是做类似的事情并不能将一种范式的语言转换成另一种范式。

最糟糕的是,Scala还使用了OO范例,使主流(Java,C ++,C#)程序员更容易进行跳转,如果你看到,它比任何其他程序都更容易获得成功FPL做到了。当然这是感谢Java(恕我直言,如果Clojure取得任何成功将是出于同样的原因,JVM)

总之:编程语言可以按照用于构建“事物”的范例进行分类。有些语言纯粹像[Smalltalk:OO,Haskell:Functional,C:Procedural],或者像Scala或者多种范式,如C ++,Ruby,Python。

你可以用另一种语言写一种风格的事实,并不能使它成为那种风格的语言。就像使用Lisp模拟对象一样,它不会使它成为OO,也不会使用Java函数使其成为功能。

要回答这个问题,为了被认为是功能性的,Smalltalk需要使用函数作为构建块,而不是因为它使用对象。

答案 7 :(得分:1)

  我已经看到了一些相似之处   Smalltalk和FPL,即闭包

有一个更基本的相似性 - 每个Smalltalk消息总是返回一个值。

但现在看看Design Principles Behind Smalltalk

  

[Smalltalk]发送的名称   期望的操作,以及任何   参数,作为数字的消息,   了解到了   接收者最了解如何进行   期望的操作。

这是否描述了您对功能编程的看法?

  

@Frank Shearar - 这描述了Erlang   太。 Erlang现在不起作用吗?

Erlang是一种奇怪的东西 - 顺序编程基于函数,但并发编程基于进程之间的消息传递。因此,Erlang不是多范式或混合,因为其他语言允许使用不同的样式来实现相同的目的 - 它使用不同的样式用于不同的目的。

答案 8 :(得分:0)

  

需要考虑什么   这样?

  • 一种声明函数的方法,而不是在类中声明方法的方法

  • 围绕函数而不是围绕对象构建程序的方法

  

@Missing Faktor - 但这个例子中的func并不是命名的   功能

|func v|
func := [:x | x + 1].
v := func value: 5.

func是一个局部变量。您已将an anonymous function绑定到本地变量func

|func v|
func := [:x | x + 1].
func := 2.
v := func value: 5.

要查看差异,请查看显示匿名函数和命名函数的this Erlang example