众所周知,所有函数语言都共享一些基本属性,例如使用函数作为程序的基本构建块,具有使用递归而不是迭代的所有后果.但是,也存在一些基本差异.Lisp对Lisp代码和数据使用单个表示,而ML没有ML代码的标准表示.Erlang有一个内置的基于actor的并发.Haskell有monad.Haskell在纯函数和不纯函数之间对静态类型系统进行了区分; ML没有.
其他功能语言(Clojure,F#,Arc,还是其他语言)之间有什么明显的根本区别?从根本上来说,我的意思是影响你在这种语言中发展的方式,而不是例如它是否与一些广泛的运行时集成.
脱离我的头顶:
懒惰与渴望(又名非严格与严谨或致电按需要对呼叫按值):为功能参数的功能应用评估之前或之后,或者永远不会?
纯与不纯:语言是否允许函数产生副作用?它有可变参考吗?
静态与动态:语言在编译时或运行时检查类型吗?
代数数据类型:语言是否支持模式匹配变体类型?
元编程:语言是否提供了强大的代码生成系统?
并发性和并行性:线程/进程是一流的抽象吗?该语言是否可以轻松地同时运行多个计算?
"异国情调"类型:静态类型系统的表现力如何?GADTs?依赖类型?线性类型?系统F?
只有前两个项目对于函数式语言来说才是真正独特的(即,几乎所有命令式语言都非常渴望和不纯粹).
我喜欢克里斯康威的答案,其中说明了一些有助于对不同功能语言进行分类的重要轴.
在特定语言的功能方面,我会选择F#来调出许多其他FPL中没有的功能:
活动模式:许多FPL具有代数数据类型和模式匹配,但称为"活动模式"的F#功能允许您定义允许您对任意数据使用模式匹配语法的新模式.
计算表达式:F#有一些漂亮的语法糖用于编写monadic代码; 虽然类型系统不能表达更高级别的多态性(没有类型构造函数的抽象),所以你不能为任意monad M编写代码,你可以为固定monad写的代码非常酷,人们写了一些很好的理解seq {}或async {} monad.
引用:通常的'代码作为元编程的数据'位,虽然F#有一个富有表现力的静态类型系统和丰富的语法,但我不确定有多少非lisps可以做到这一点.
在一般分类方面,F#是
渴望(严格,按值调用;但'懒惰'是一个关键字和库,使用seq/IEnumerable进行一些懒惰是一种常见的策略)
不纯(虽然语法偏向于纯粹的默认样式)
static(使用类型推断,因此F#经常'感觉就像脚本',只有类型安全)
你的问题的表达方式明显偏向某些语言外的语用学(例如它与运算符集成在一起),但你也会问"影响你的发展方式",这些事情会影响到:
Visual Studio集成意味着出色的编辑体验(例如Intellisense)
Visual Studio集成意味着良好的调试体验(例如断点/跟踪点,本地,即时窗口......)
脚本或即时UI的REPL是热门的(在VS中集成了fsi.exe命令行或"F#Interactive")
.NET集成意味着大多数'X'已经有了一个库来做到这一点
像FsLex/FsYacc这样的辅助工具,以及与MSBuild的集成,使"构建系统"变得简单
(我认为尝试将语言与运行时和工具分开是一项主要的学术练习.)
因此,我描述了一种特定语言的许多独特特征,我是其中的粉丝.我希望其他人可能会发布类似的答案,这些答案可以说明其他语言的独特特征
非严格与严格的评估.
静态与动态类型.
结构与名义静态类型.OCaml是我能想到的结构类型(在对象和多态变体中)的唯一语言,它通过消除定义许多类型(例如变体类型)的需要来填补动态类型的空白.
Hindley-Milner衍生物与其他静态类型推理算法.SML,OCaml,Haskell和F#使用基于Hindley-Milner的类型推断算法,而Scala只有本地类型推断(如C#3),需要更多的注释才能编译.(Haskell代码在函数级别通常充满了类型注释,但大多数是不必要的,并且是为了文档而添加的,并且在出现错误时帮助编译器).
模式匹配与手动解构.SML,OCaml,F#,Haskell,Mathematica和Scheme自动化了价值的解构.
封闭的总和类型与仅开放的总和类型.SML,OCaml,F#和Haskell允许定义封闭/密封的代数类型,以通过隐含地传达更具体的约束来加强静态类型.OCaml和F#也允许开放和类型,而SML不允许和Haskell需要精心设计的解决方法(由Oleg Kiselyov描述).
有限时间模式.在SML和(vanilla)OCaml中模式匹配非常快,但由于Mathematica中的活动模式甚至未知的渐近复杂性,在F#中具有未知的性能.
即时编译到本机代码.F#,Lisp和Scheme允许在运行时有效地生成,编译和执行代码.
宏.OCaml,Mathematica,Lisp和Scheme是可扩展的语言.
标准化与专有.SML,Haskell 2010,Common Lisp和Scheme是标准化语言,而OCaml,Erlang,F#和Mathematica是专有的.
有许多不同之处,但只有两个不同之处,我将其归类为基础,因为它们会对您的开发产生重大影响:
具有代数数据类型和类型推断的动态类型与静态,多态类型系统.静态类型系统在某种程度上限制了代码,但具有许多优点:
类型是由编译器检查的文档.
类型系统可以帮助您选择接下来要编写的代码,当您不确定要编写什么时,类型系统可以帮助您轻松快速地排除许多替代方案.
功能强大的现代多态类型系统在检测小型,愚蠢,浪费时间的错误方面非常擅长.
惰性评估作为默认无处不在与延迟评估仅限于精心控制的构造.
Lazy vs eager对您预测和理解程序的时间和空间成本的能力有着巨大的影响.
在一种完全惰性的语言中,您可以完全将数据生成与关于如何生成数据的决策分离.这对于搜索问题尤为重要,因为模块化和重用代码变得更加容易.