为什么 Smalltalk 不是函数式编程语言?
随着人们对函数式编程语言重新产生兴趣,我看到了 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
函数式编程语言没有公认的定义。
如果您将函数式语言定义为支持一流函数的语言,那么是的,Smalltalk *是*一种函数式语言。
如果您还考虑对不变性、代数数据类型、模式匹配、部分应用程序等的支持等因素,那么 Smalltalk *不是*一种函数式语言。
我鼓励您阅读以下相关博客文章(以及它们下面的评论):
Scala 不是函数式
语言
Erlang 没有功能< /a>
Reddit 讨论“Erlang 不是
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):
Scala is not a functional
language
Erlang is not functional
Reddit discussion on "Erlang is not
functional"
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 不是 FPL,因为:
(一些 Smalltalks 显然支持不可变对象。我的经验仅限于 Squeak,它不支持 VM 级别的不变性。)
编辑:除了通过在对象上定义方法之外,我不明白 igouy 对命名函数定义的需求。但无论如何,我们开始吧:
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:
and Smalltalk is not an FPL because:
(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 在大多数情况下可以表达使用面向对象编程范式创建的所有解决方案,但它不能原始地表达使用函数式编程范式创建的许多解决方案。这就是为什么我不认为它是 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.
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).
纯函数式语言通常具有不可变变量,这使得它们更像数学意义上的变量。
Purely functional languages usually have immutable variables, making them more like the variables in a mathematical sense.
语言不会通过命名函数而成为函数式语言 - 根据该定义,C 将是函数式的!更重要的是数学意义上的函数语义,结果仅取决于参数(特别是:没有副作用)。根据这个定义,可以由 setter 修改的对象与函数式编程风格相反。然而,正如已经指出的,如果您禁止副作用,那么即使是对象也可以以功能样式(矩形示例)使用。
而且,顺便说一句。具有方法的对象和一组在私有状态的闭包中定义的函数之间存在二元性(详细信息请参阅 SICP)。它们可以互相模拟:
上面是对“纯”函数对象的模拟,并且在语义上与很多 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:
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 !
谢谢大家的所有回答。
我将在这里添加我的,这基本上是我(可能错过)对你的理解。
我认为称某个东西为 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.
有一个更基本的相似之处 - 每个 Smalltalk 消息总是返回一个值。
但现在看看 Smalltalk 背后的设计原则
这是否描述了您所认为的函数式编程?
Erlang 有点像嵌合体——顺序编程基于函数,而并发编程基于进程之间的消息传递。因此,Erlang 不像其他语言那样允许使用不同的样式来实现相同的目的,它不是多范式或混合体 - 它使用不同的样式来实现不同的目的。
There's a more basic similarity - every Smalltalk message always returns a value.
But now look at the Design Principles Behind Smalltalk
Does that describe what you think of as Functional Programming?
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.
一种声明函数的方式,而不是在类中声明方法的方式
一种围绕函数构建程序的方式,而不是围绕对象
否
func
是局部变量。您已将匿名函数绑定到局部变量func
。要了解差异,请查看 这个 Erlang 示例,它显示了匿名函数和命名函数。
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
No
func
is a local variable. You've bound an anonymous function to the local variablefunc
.To see the difference, look at this Erlang example which shows both an anonymous function and a named function.