代码之家  ›  专栏  ›  技术社区  ›  OscarRyz

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

  •  21
  • OscarRyz  · 技术社区  · 14 年前

    随着对函数式编程语言的兴趣的不断加深,我已经看到了smalltalk和fpl之间的一些相似之处,即闭包(smalltalk中的blockclosures),但是smalltalk不是fpl吗?

    需要什么来将其视为这样?

    9 回复  |  直到 14 年前
        1
  •  13
  •   Diego Geffner    14 年前

    用面向对象的范式编程就是通过将问题域实体识别和建模为对象来创建一个程序,然后让它们彼此协作来解决每个问题实例。 用函数范式编程是将问题建模为一个数学问题,并创建一个数学函数(通过组合其他函数),为每个问题实例计算问题的解决方案。

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

    在大多数情况下,Smalltalk可以表示使用面向对象编程范式创建的所有解决方案,但它不能原始地表示使用函数编程范式创建的许多解决方案。这就是为什么我不认为它是FPL。 尽管smalltalk不能基本地表达FPL可以表达的每一个解决方案,但它具有极强的可扩展性,您可以将其扩展为能够表达FPL可以表达的所有解决方案。

        2
  •  27
  •   missingfaktor Kevin Wright    14 年前

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

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

    如果还考虑到诸如不可变支持、代数数据类型、模式匹配、部分应用等因素,那么smalltalk*不是一种函数语言。


    我鼓励你阅读以下相关的博客文章(以及下面的评论):

        3
  •  22
  •   Frank Shearar    14 年前

    smalltalk可能不是一种“纯功能语言”(不管它是什么)。然而,自然使用smalltalk通常会导致函数代码。(我猜斯卡拉人会称之为“对象功能”。)

    例如,squak的point类有一个函数API:类似 1@1 translateBy: 1@1 用新状态返回新的点,而不是改变内部状态。(这使得点实际上是不可变的,因为更改对象内部状态的唯一方法是通过反射机制,如instvarat:。)

    在Smalltalk中使用高阶函数是很正常的,比如地图、过滤器、折叠等等。考虑到集合API中包含了这些内容,通常以函数方式编写使用集合的代码要比不使用集合容易得多。

    很多人对“函数式编程语言”有如此多的定义,“is foo a fpl”这个问题和“is foo a object-oriented language”一样毫无用处。

    我已经说过了,这是我的两点:函数式编程语言是一种语言,它是 自然的 惯用的 采用函数技术:一级函数,避免可变状态,无副作用函数,高阶函数。

    根据这种描述,smalltalk是一种函数式编程语言。它调用一阶函数“methods”或“blocks”,这取决于它们是命名的还是匿名的。对象将状态存储在实例变量中。高阶函数只是以块为参数的简单方法。

    说了这句话,是的,你可以用一种非功能性的方式来写Smalltalk。它允许可变状态。这会阻止smalltalk被称为功能语言吗?如果是这样,这些语言也不起作用:common lisp,erlang(通过进程字典,ets/dets共享状态)。

    因此,简而言之, smalltalk是一个fpl 因为:

    • 函数是第一类实体(对象,在smalltalk编译的方法或blockclosures中,更精确地说)。
    • smalltalk支持闭包(称为块)。
    • Smalltalk允许您以自然、惯用的方式进行功能性的编写。

    Smalltalk不是FPL 因为:

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

    (一些小型会谈显然支持不变的对象。我的经验仅限于Squeak,它不支持VM级别的不可变性。)

    编辑:除了通过在对象上定义方法之外,我不理解igouy对命名函数定义的需求。但不管怎样,我们开始:

    Smalltalk at: #func put: [:x | x + 1].
    func value: 1.
    
        4
  •  7
  •   Manuel Araoz    14 年前

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

        5
  •  5
  •   Matthew Schinckel    14 年前

    纯函数语言通常有不变的变量,这使得它们更像数学意义上的变量。

        6
  •  5
  •   blabla999    14 年前

    一种语言不是通过具有命名函数而成为一种功能性语言——根据这个定义,C是功能性的!更重要的是数学意义上的功能语义,即结果仅依赖于参数(特别是:没有副作用)。根据这个定义,可以由setter修改的对象与函数式编程风格相反。但是,正如已经指出的,如果禁止副作用,甚至对象也可以在函数样式(矩形示例)中使用。 而且,顺便说一句,在具有方法的对象和在私有状态的闭包中定义的一组函数之间存在着二元性(有关详细信息,请参阅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)。而且,因为设置!不起作用,破坏了方案的“功能性”。

    总结:看看语义学,而不是来源,卢克!

        7
  •  2
  •   Community CDub    8 年前

    谢谢大家的回答。

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

    我认为称为OO或FP的标准是使用语言构建“东西”的方式,而不是简单或困难的方式,我的意思是,使用的心理模式。

    例如,如链接所示,在scala中键入某些内容可能比在ocaml中键入更困难,但这并不能减少fpl(可能不完整或不完整,但肯定是功能性的);因为scala的目标是将函数用作主要构建块,而不是对象。

    另一方面,如果样式或目标是使用另一个工件,那么用一种语言轻松编写一个函数并不能使其正常工作。例如,smalltalk可以很容易地编写一个匿名块或提供一个可插入的排序比较器,但这根本就不能使它起任何作用,因为重点是使用对象和传递消息。块闭包只是一种对这些消息(而不是函数)进行编码的机制,即使它们看起来像函数。

    混淆来了,因为OO和FP是正交的(如 Rahul 在twitter上声明),所以,它看起来像smalltalk中的编码消息,看起来非常像scala中的匿名函数。但做类似的事情并不能将一种模式的语言转换成另一种模式。

    最糟糕的是,斯卡拉还使用面向对象的范式,使主流(Java、C++、C语言)程序员更容易跳出,如果你看到的话,它比任何其他FPL都有更大的成功。当然,这是感谢Java(IyHo如果Culjule有任何成功将完全相同的原因,JVM)

    总之 :编程语言可以根据它用来构建“事物”的范例进行分类。有一些语言是纯的[ SimalTalk:OO,Haskell:函数,C:程序],或混合,如斯卡拉或多范式,如C++,露比,Python。

    你可以用另一种语言来写一种风格,但这并不能使它成为那种风格的语言。像用Lisp模拟对象并不能使它成为OO,也不能使用Java函数来实现它。

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

        8
  •  1
  •   igouy peenut    14 年前

    我看到了 smalltalk和fpl,即闭包

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

    但是现在看看 Design Principles Behind Smalltalk

    [smalltalk]发送 所需操作,以及 参数,作为数字的消息, 理解到 接受者最了解如何执行 所需的操作。

    这是否描述了您认为的函数式编程?

    @弗兰克·希拉尔-描述了二郎 也是。Erlang现在不起作用了吗?

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

        9
  •  0
  •   igouy peenut    14 年前

    需要什么来考虑它 这样?

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

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

    @缺少faktor-但在本例中不是func 功能?

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

    func 是局部变量。你已经约束了 an anonymous function 到局部变量 芬克 .

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

    要看到不同之处,请看 this Erlang example 它同时显示匿名函数和命名函数。