Javascript 是一种函数式编程语言吗?

仅仅因为函数是第一类对象,有闭包和更高阶的函数,那么 Javascript 就应该被称为函数式编程语言吗?我认为它缺少的主要东西是纯函数,而且它不像其他函数式语言(如 lisp)那样“感觉”(尽管这并不是它不是一种函数式语言的真正好理由... ...)

57246 次浏览

我不会说它是函数式编程,但是 会说它是面向对象的,就在今天,一个朋友说他也不会把它放在那个架子上。

所以,虽然我不会说它是,我想有意见的空间。它确实具有函数式编程的经典特性,没有其他特性。

我认为它是一种多范式的语言。

编辑: 它是多范式的,包括函数构造。

对类似的问题重复 我自己的答案,

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

如果将函数式语言定义为 支持头等舱的语言 函数和 lambdas,那么是的,JavaScript * 是 * a 函数式语言。

如果你也考虑到 支持不变性,代数 数据类型,模式匹配,部分 应用程序等,然后没有,JavaScript 不是一种函数式语言。


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

对我来说,Javascript 既是一种命令式语言,也是一种函数式语言,您可以选择以任何一种方式使用它,甚至(天啊)两种方式都可以使用它。或者你可以选择使用一种模式,永远不要触及另一种模式。你自己决定吧。和你一样,我不认为 Javascript 应该是一种函数式语言,因为它允许你在函数式编程范型中进进出出。也许如果它有某种实用程序,来限制您只使用函数式编程范例,那么我认为这将是有用的。但是,总的来说,我认为它更多的是一个命令式/工作语言,并且添加了一些函数式编程特性。

Javascript 在某种程度上。这完全取决于您如何编程它。如果我以 OO 的方式编码,它不会是 OO 吗?因此,如果你只是以“函数式”的方式编写代码,那么它就是函数式的。我想这是一种多范式的语言,所以仅仅称之为一件事情是不完全准确的。

如果将“函数式编程”这个术语延伸和扭曲到哲学讨论的地步,这个问题可能会再次打开。然而,你最终会遇到一些有用的问题,比如“ C + + 真的是一种编程语言吗?”?

对你的问题的答案在更多的日常水平是 “不”

函数式编程意味着将程序概念化为函数的求值,而不是控制流。代码是函数的描述,没有固有的控制流概念。

JavaScript 有一个控制流,并被概念化为一种命令式语言。从其设计目标来看,它显然不是一种函数式语言。

我倾向于不认为编程语言有一个特定的范例,而是认为它们适合某些范例。然而,仅仅因为它们使自己适合于某个特定的范例,并不意味着您必须使用该范例。用 C 语言编写面向对象程序和用机器学习编写命令式程序是完全可能的。不使用特定的范例来解决问题,因为语言不是为它而设计的,这只是人为地限制你自己(当然,在决定某个特定的解决方案是否是一个好的解决方案时,你仍然应该考虑到语言的局限性)。

“函数式编程”这个术语如今已经过载得几乎没有用处了,它有两个主要的含义:

  1. 具有一流的功能
    • Javascript 就是这个!
  2. 基于 lambda 演算中使用的函数,强调避免持久可变状态(通常用传递给函数的参数替换它)
    • 正如通常编写的那样,Javascript 不是远程的!

选择你的意思,然后问题就有答案了。

我真正讨厌 javascript 的地方(如果你把它看作 FP 语言的话)是这样的:

function getTenFunctionsBad() {
var result = [];
for (var i = 0; i < 10; ++i) {
result.push(function () {
return i;
});
}
return result;
}


function getTenFunctions() {
var result = [];
for (var i = 0; i < 10; ++i) {
result.push((function (i) {
return function () {
return i;
}
})(i));
}
return result;
}


var functionsBad = getTenFunctionsBad();
var functions = getTenFunctions()
for (var i = 0; i < 10; ++i) {
// using rhino print
print(functionsBad[i]() + ', ' + functions[i]());
}


// Output:
//   10, 0
//   10, 1
//   10, 2
//   10, 3
//   10, 4
//   10, 5
//   10, 6
//   10, 7
//   10, 8
//   10, 9

您需要理解 JS 堆栈环境(如果这是正确的术语,我就不理解)才能理解这种行为。

例如,在 Scheme 中,你就不能生成这样的东西(OK,OK ——借助底层语言的参考,你可以做到) :

(define (make-ten-functions)
(define (iter i)
(cond ((> i 9) '())
(else (cons (lambda () i) (iter (+ i 1))))))
(iter 0))


(for-each (lambda (f)
(display (f))
(newline)) (make-ten-functions))

@ petraszd 为了获得一个“新的”为了操作符,我稍微重写了一下你的代码:


function ffor(a, b, f){
function it(i){
if(i > b)return
f(i)
it(i+1)
}
it(a)
}


print("----" + new Date()+"----")


var funcs = []
ffor(0, 9, function(i){
funcs.push(function(){return i})
})


ffor(0, 9, function(i){
print(funcs[i]())
})

但是我知道这种方式对于大循环来说有缺点。

JS 中尾部递归优化的相关问题

在这里发帖是因为在作为注释发帖时代码格式有问题

我不认为函数式编程有一个具体的定义,但是人们认为“函数式编程”的许多事情可以用 javascript 来完成。这里有一个很好的简短的例子在这个 文章。

在 Javascript 中,您可以这样做! !

// Data
var fruits = [
{ name: 'apple',  price: 5 },
{ name: 'orange', price: 10 },
{ name: 'lemon',  price: 15 }
]


// Request Data from magicURL
request('magicURL')
.then(selectKeyOf('price'))
.then(priceMethod('sum'))
.then((result)=>{
console.log(result) // 30
})

为了演示这个概念,我做了一个 Github 页面,你可以克隆/查看我的实现

正如我们所知,函数式编程语言不允许改变或变异函数的元素(状态) ,但在 javascript 中,它是允许的,从这个意义上来说,它不是一种函数式编程语言,尽管它确实将函数视为一等公民。

首先,我们必须定义函数式编程。我将它定义为 天生的支持的任何语言,以及规范(或者至少广泛认可的)函数式语言(如 Scheme、 Racket、 Haskell 或 Clojure)所共享的编程风格。

其他语言,如 OCaml、 Elixir 和 Scala 比 JS 具有更深层次的功能支持,但仍倾向于被认为是多范式的。实用性是一个频谱。

所有这些对于无休止的争论和吹毛求疵是非常开放的,但是这个定义似乎足够坚定,可以证明 JS 不是一个严肃的函数式语言,而且可能永远不会比任何其他具有一流函数的现代多范式语言更加严肃。

让我们选择一个特定的功能。该语言应该执行 尾部呼叫优化尾部呼叫优化,这样您就可以在线性数据结构上编写递归函数。几乎所有 JS 的主要实现都没有提供这个我们期望从典型的“函数式”语言(根据上面的定义)得到的基本特性,在编写本文时也没有这样的计划(详见 JavaScript 尾部调用中的函数是否优化?)。

让我们相信 TCO 是有益的,但是 JS 仍然没有提供哪怕是一点点关于“真正的”函数式语言所期望的不可变性设计目标的提示。仅仅使用该语言获得 const就花费了几十年的时间,而且所有对象在默认情况下都是可变的。

这些问题实际上不能完全解决,因为向下兼容,它不可能真正把一个已建立的多范式语言成为一个真正的功能语言后,事实上。

JS 的功能和 Python、 Perl、 PHP 或 Ruby 一样,都在列表上提供 map/filter/reduce操作,并支持一流的函数或过程。第一类函数的存在为编写函数式编程 风格中的代码提供了足够的空间。再加上蹦床和 Ramda.js,乍看起来似乎很有说服力。

问题是一级函数是否足以使语言具有“功能性”。事实上,维基百科的 将上述所有内容都列为函数式语言,但是,这个列表包括了除了 C 和 Go 之外的几乎所有流行的、现代的、通用的语言(包括至少一种 通过设计明确地标识为非功能性) ,所以我不认为这个定义有什么特别的价值。