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

发布于 2024-09-14 19:47:37 字数 127 浏览 10 评论 0原文

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

需要什么来考虑它?

With the renewed interest in functional programming languages, I've seen some similitudes between Smalltalk and FPL, namely closures ( BlockClosures in Smalltalk ) Yet, Smalltalk is not a FPL?

What would be needed to consider it as such?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

唐婉 2024-09-21 19:47:38

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

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

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


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

There's no accepted definition of functional programming language.

If you define functional language as the language that supports first class functions, then yes, Smalltalk *is* a functional language.

If you also consider the factors like support for immutability, algebraic data types, pattern matching, partial application etc then no, Smalltalk *is not* a functional language.


I'd encourage you to read the following related blog posts (and also the comments below them):

仙女山的月亮 2024-09-21 19:47:38

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

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

在 Smalltalk 中使用高阶函数(如映射、过滤器、折叠等)是很正常的。鉴于这些已融入 Collections API 中,因此编写以函数方式使用 Collections 的代码通常比不使用 Collections 更容易。

很多人对“函数式编程语言”有如此多的定义,以至于“Foo 是 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.

Smalltalk might not be a "pure functional language" (whatever that might be). However, natural use of Smalltalk often results in functional code. (What I guess the Scala people would call "object-functional".)

For example, Squeak's Point class has a functional API: methods like 1@1 translateBy: 1@1 return new Points with the new state, instead of mutating internal state. (This makes Point practically immutable, since the only way to change the internal state of the object is through reflection mechanisms like #instVarAt:.)

It's quite normal to use higher order functions in Smalltalk like maps, filters, folds, and the like. Given that these are baked into the Collections API, it's often easier to write code that uses Collections in a functional way than not.

So many people have so many definitions of "functional programming language" that the question "is Foo a FPL" is as useless a question to ask as "is Foo an object oriented language".

Having said that, here's my two cents: a functional programming language is a language in which it is natural and idiomatic to employ functional techniques: first-class functions, avoidance of mutable state, side-effect free functions, higher-order functions.

By that description, Smalltalk is a functional programming language. It calls first-order functions "methods" or "blocks" depending on whether or they're named or anonymous. Objects store state in instance variables. Higher order functions are simply methods that take blocks as parameters.

Having said that, yes, you can write Smalltalk in a non-functional manner. It does allow for mutable state. Does that stop Smalltalk from being called a functional language? If so, neither are these languages functional: Common Lisp, Erlang (shared state through the process dictionary, ets/dets).

So, in brief, Smalltalk is an FPL because:

  • Functions are first-class entities (objects, in Smalltalk - CompiledMethods or BlockClosures, to be precise).
  • Smalltalk supports closures (it calls them blocks).
  • Smalltalk allows one to write functionally in a natural, idiomatic manner.

and Smalltalk is not an FPL because:

  • You as programmer must ensure that your data structures (objects) are immutable (by having setters/mutators return copies of the object with the mutated state).
  • You as programmer must ensure that your methods (functions) are side-effect free.

(Some Smalltalks do apparently support immutable objects. My experience is limited to Squeak, which does not support VM-level immutability.)

Edit: I don't understand igouy's need for named function definitions other than through defining methods on an object. But anyway, here we go:

Smalltalk at: #func put: [:x | x + 1].
func value: 1.
给不了的爱 2024-09-21 19:47:38

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

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

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

Programming with the Object Oriented paradigm is creating a program by identifying and modeling the Problem Domain Entities as objects, and then make them collaborate between themselves to solve each problem instance.
Programming with the Functional paradigm is modeling the problem as a mathematical problem, and creating a mathematical function (by composing other functions) that for each problem instance, computes the problem solution.

In my opinion, a functional programming language is a language that given a solution for a problem solved using the functional programming paradigm, the language can express that solution exactly as it was thought. If you need to "transform" some part of your solution so it fits in what the language can express, then it doesn't fully support the paradigm you used to think the solution.

Smalltalk can express in most cases all the solutions created using the Object Oriented Programming paradigm, but it cannot expresss primitively a lot of solutions created using the Functional Programming paradigm. That's why I don't consider it a FPL.
Despite not primitively be able to express every solution that a FPL can, Smalltalk is extremelly extensible, and you can extend it to be able to express all the solutions a FPL can.

我的黑色迷你裙 2024-09-21 19:47:38

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

Smalltalk is a purely Object Oriented Language, where almost all code is basically objects interchanging messages. Functional programming is oriented to function calls, and compositions between functions to create more complex behavior (avoiding state for data, as opposed to internal states that objects have in any Object Oriented language).

半葬歌 2024-09-21 19:47:38

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

Purely functional languages usually have immutable variables, making them more like the variables in a mathematical sense.

上课铃就是安魂曲 2024-09-21 19:47:38

语言不会通过命名函数而成为函数式语言 - 根据该定义,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) 的方法。并且,因为设定!是非功能性的,破坏了方案的“功能”。

摘要:看语义,而不是来源,卢克!

A language does not become a functional language by having named functions - by that definition, C would be functional ! More important is the functional semantics in the mathematical sense, that the result depends on the arguments alone (in particular: no side effects). By this definition, objects which can be modified by setters are contrary to a functional programming style. However, as already pointed out, even objects can be used in a functional style (Rectangle example) if you forbid side effects.
And, btw. there is a duality between objects with methods and a set of functions which are defined in a closure over a private state (see SICP for details). They can simulate each other mutually:

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

the above is a simulation of "pure" functional objects, and semantically the same as a lot of Smalltalk code! However, to implement a setter-method, you have to add a method which does a (set! instVar newValue). And, because set! is non-functional, breaks the "functionality" of the scheme.

Summary: look at the semantics, not the source, luke !

丿*梦醉红颜 2024-09-21 19:47:38

谢谢大家的所有回答。

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

我认为称某个东西为 OO 或 FP 的标准是它们使用该语言构建“东西”的方式;我的意思是,不是做起来有多容易或多难,而是所使用的心理范式。

例如,如链接所示,在 Scala 中输入某些内容可能比在 OCaml 中更难,但这并不会降低 FPL(可能不完整或不纯粹,但绝对是功能性的);因为 Scala 的目标是使用函数作为主要构建块,而不是对象。

另一方面,如果风格或目标是使用其他工件,那么用一种语言轻松编写函数并不意味着它具有功能性。例如,Smalltalk 使编写匿名块或提供可插入排序比较器变得非常容易,但这根本不会使其具有任何功能,因为重点是使用对象和传递消息。块闭包只是一种对这些消息(而不是函数)进行编码的机制,即使它们看起来就像函数一样。

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

最糟糕的是,Scala 还使用了 OO 范式,让主流(Java、C++、C#)程序员更容易跳跃,如果你看到的话,它比任何其他 FPL 都取得了更大的成功。当然,这要归功于 Java(恕我直言,如果 Clojure 取得成功,JVM 也会出于完全相同的原因)

结论:编程语言可以根据其用于构建的范例进行分类“事物”。有些语言是纯粹的,如 [Smalltalk:OO,Haskell:函数式,C:过程式],也有混合语言,如 Scala 或多范式,如 C++、Ruby、Python。

事实上,你可以用另一种语言编写一种风格,但这并不意味着它就是那种风格的语言。就像用 Lisp 模拟对象并不意味着它是面向对象的一样,使用 Java 的函数也不意味着它是函数式的。

为了回答这个问题,为了被认为是函数式的,Smalltalk 需要使用函数作为构建块,但事实并非如此,因为它使用对象。

Thank you all for all the answers.

I'll add mine here which basically is my ( probably miss) understanding of yours.

I think the criteria to call something OO or FP is they way "stuff" is built using the language; not how easy or hard is to do it, I mean, the mental paradigm used.

For instance, as the links shown, it may be harder to type something in Scala than in OCaml, but that doesn't make it less FPL ( maybe incomplete or impure, but definitely functional ); because the aim of Scala is to use functions as primary building blocks, rather than objects.

On the other hand, making easy to write a function in a language doesn't make it functional, if the style or the aim is to use another artifacts. Smalltalk for instance, make it very easy to write an anonymous block or to provide a pluggable sorting comparator, but that doesn't make it ANY Functional at all, because the focus is to use objects and pass messages. Blockclosures are just a mechanism to encode these messages ( not functions ) even if they look like just like they were functions.

The confusion comes, because OO and FP are orthogonal ( as Rahul stated via twitter ) , so, what it looks like a encoded message in Smalltalk, looks pretty much like an anonymous function in Scala. But doing something similar doesn't converts a language of one paradigm into another.

To make it worst, Scala also uses the OO paradigm, to make it easier for mainstream ( Java, C++, C# ) programmers to give the jump, and if you see, it have had way more success than any of the others FPL's did. And of course this was thank to Java ( IMHO if Clojure has any success will be for exactly the same reason, the JVM )

In conclusion: A programming language may be classified by the paradigm it uses to build "things". There are languages that are pure like [Smalltalk : OO, Haskell: Functional, C: Procedural], or hybrids, like Scala or multi paradigm , like C++, Ruby, Python.

The fact you can write one style with the other language, doesn't make it that language of that style. Like simulating Objects with Lisp doesn't make it OO nor using functions with Java make it Functional.

To answer the question, to be considered functional, Smalltalk would need to use functions as building blocks, which it doesn't because it uses objects.

四叶草在未来唯美盛开 2024-09-21 19:47:38

我发现了一些相似之处
Smalltalk和FPL,即闭包

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

但现在看看 Smalltalk 背后的设计原则

[Smalltalk] 发送的名称
所需的操作,以及任何
参数,作为发送给该号码的消息,
据了解,
接收者最清楚如何执行
所需的操作。

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

@Frank Shearar - 描述了 Erlang
也。 Erlang 现在无法运行了吗?

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

I've seen some similitudes between
Smalltalk and FPL, namely closures

There's a more basic similarity - every Smalltalk message always returns a value.

But now look at the Design Principles Behind Smalltalk

[Smalltalk] sends the name of the
desired operation, along with any
arguments, as a message to the number,
with the understanding that the
receiver knows best how to carry out
the desired operation.

Does that describe what you think of as Functional Programming?

@Frank Shearar - That describes Erlang
too. Is Erlang now non-functional?

Erlang is something of a chimera - sequential programming is based on functions, but concurrent programming is based on message passing between processes. So Erlang is not multi paradigm or hybrid in the way that other languages allow different styles to be used to achieve the same purpose - it uses different styles for different purposes.

坐在坟头思考人生 2024-09-21 19:47:38

需要什么才能将其视为
这样?

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

  • 一种围绕函数构建程序的方式,而不是围绕对象

@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 示例,它显示了匿名函数和命名函数。

What would be needed to consider it as
such?

  • a way to declare functions rather than a way to declare methods in a class

  • a way to structure a program around functions rather than around objects

@Missing Faktor - but isn't func in this example a named
function?

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

No func is a local variable. You've bound an anonymous function to the local variable func.

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

To see the difference, look at this Erlang example which shows both an anonymous function and a named function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文