Javascript 是函数式编程语言吗?

Posted

技术标签:

【中文标题】Javascript 是函数式编程语言吗?【英文标题】:Is Javascript a Functional Programming Language? 【发布时间】:2011-04-27 03:08:08 【问题描述】:

仅仅因为函数是一等对象,有闭包和更高阶的函数,javascript 是否应该被称为函数式编程语言?我认为它缺少的主要是纯函数,它不像其他函数式语言,比如 lisp(尽管这并不是它不成为函数式语言的真正理由......)

【问题讨论】:

@slashmais:不!这只会阻止它成为纯粹的函数式语言。 ML(至少是现代方言)也是不纯的——但没有人敢称它们没有功能;) 有很多语言通常被认为是函数式的,但它们并不纯粹。我看不出这是什么要求。如果你想那么严格,那么大多数所谓的 OOP 语言也不是 OOP。你最终会发现大约 95% 的语言都是非范式语言。 为什么这很重要?当我用 C++ 编码时,我不在乎语言是否“是 OOP”。我关心它是否具有某些 OOP 特性,并且它具有几个函数式编程特性、许多命令式编程特性和许多通用编程特性。但它是“是”OOP 语言还是 FP 语言或其他语言都无关紧要。同样,当我在 JS 中编码时,它是否是 FP 都没关系。重要的是它支持许多不错的 FP 功能。看来这是一个错误的问题。 @hvgotcodes:所以?绝对没有规则说它不是。我的经验法则是,如果您可以使用它以函数式风格进行编程,那么它就是一种函数式语言。由于 Javascript 具有一流的函数、闭包和 lambda,我相信您可以,就我而言,它是一种函数式语言。显然,这不是一种纯粹的语言,但我们通常考虑的大多数语言也不是 FP(例如 SML)。所以真的,我认为你只需要放松一下。如果这让您的眼睛抽搐,您需要去看医生。 @jalf,绝对的。这个问题的动机是我想知道我的同龄人和比我聪明的人的想法。 【参考方案1】:

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

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

【讨论】:

JavaScript 是面向对象的。 OO 不需要类,但它需要对象。 Javascript 不是面向对象的,它是基于原型的。 JavaScript 是编程汤。一点这个和一点那个。【参考方案2】:

我会说它是一种多范式语言。

编辑:它是多范式,包括功能构造。

【讨论】:

是的,我同意这是一个混合和几个不同的东西。 但这并不能回答它是否功能的问题。多范式意味着支持多个范式。这些范例之一是函数式编程吗?【参考方案3】:

对类似问题重复my own answer,

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

如果您将函数式语言定义为 支持一流的语言 函数和 lambda,那么是的,JavaScript *is* a 函数式语言。

如果您还考虑以下因素 支持不变性,代数 数据类型,模式匹配,部分 应用程序等然后不,JavaScript *不是*一种函数式语言。


我建议您阅读 关注相关的博客文章(以及 他们下面的cmets):

Scala is not a functional language

Erlang is not functional

Reddit discussion on "Erlang is not functional"

【讨论】:

Mozilla 的 JavaScript 实现的更高版本(从 1.7 开始)以解构赋值的形式进行模式匹配:developer.mozilla.org/en/New_in_JavaScript_1.7#section_20 JavaScript 有分部的概念,部分地应用参数,所以不知道您说它不支持这一点的说法是否不正确? @OpenLearner,我能想到的几乎所有语言都支持部分应用程序,甚至 C。无论如何,对于“支持”的特定定义。 JS 的情况也不例外。关键是部分应用在该语言中是否轻松且一流。在 JS 中,它不是。如果您对我的意思感到好奇,请查看 OCaml 或 Haskell。 JavaScript 支持不变性 afaik。 @fka,你能详细说明你的意思吗?【参考方案4】:

对我来说,Javascript 既是命令式语言又是函数式语言,您可以选择使用任何一种方式,甚至 (egad) 两种方式。或者您可以选择使用一种范式,而从不触及另一种。由你决定。我和你一样,不认为 Javascript 应该被称为一种函数式语言,因为它允许你在函数式编程范式中游走。也许如果它有某种编译指示,限制你只使用函数式编程范式,那么我认为这将是有用的。但是,总而言之,我说它更像是一种命令式/过程式语言,其中包含一些函数式编程特性。

【讨论】:

按此推理,F# 不能再称为函数式了。 对。根据***的说法,F# 正是我刚才所说的 Javascript:“F# [...] 是一种多范式编程语言 [...],它包含函数式编程以及命令式面向对象编程学科”【参考方案5】:

Javascript 很重要。这真的取决于你如何进行编程。如果我以 OO 方式编码,那它不是 OO 吗?因此,如果您只是以“功能性”的方式对事物进行编码,那么它将是功能性的。我猜它是多范式语言,所以称它为一件事并不完全准确。

【讨论】:

如果你足够努力,你通常可以用任何语言用任何风格进行编程。谈论该语言的设计范式和程度似乎更有意义。与大多数同时代的 Perl、php、Ruby、Python 等相比,JS 并没有被设计成一种函数式语言。它是一种多范式语言,具有一些功能特性,尤其是一流的功能。我认为这不足以将语言称为“功能性”,就像能够游泳使某物成为鱼一样。【参考方案6】:

如果您将“函数式编程”一词延伸到哲学讨论的地步,这个问题可能会再次公开。但是,您最终会遇到诸如“C++ 真的是一种编程语言”之类的有用问题吗?

您的问题在日常层面上的答案是“否”

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

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

【讨论】:

设计目标?你的意思是?最后我检查了一下,它的灵感来源之一是 Scheme。我想说的是,它的设计目标之一是支持函数式编程以及作为一大堆其他范式,这很明显 它支持函数式编程,就像 C++ 一样,如果您自己为此编写适当的基础 - 就像您可以通过一点工作在 Haskell 中模拟命令式语法一样多。然而,JavaScript 的语法导致它被认为是一个工作流,而不是一个函数的求值。出于这个原因,我(或大多数函数式程序员)认为使用“函数式”一词过于广泛。 @user411768:所以您是说一种语言是否具有功能性取决于其标准库的设计?我以前从未听过那个的定义。 Java 拥有以函数式风格进行编程所需的大部分工具(例如,闭包和匿名函数),而 C++(目前)没有。我认为这使得 JS 比 C++ 更 FP。该语言不会强制您以 FP 风格进行编程这一事实并不会使其“功能降低”,不是吗? (i) 标准库是标准的一部分,就像语法特征一样,强调某种惯用和概念风格。例如。 “带有 STL 的 C++”与“带有类的 C”非常不同。它有影响。 (ii) JavaScript 具有面向对象、一流公民功能的特性——这些特性与命令/功能二分法相当正交。但是,它既没有直接实现柯里化,也没有提供纯度,也没有为此设计过。 (iii) 我的最后一句话,请参阅帖子的第一段。 关于 JavaScript 和 C++ 提供相同的函数式编程便利性的说法肯定是错误的。 JavaScript 使函数式编程变得非常简单明了,而无需在 C++ 中为实现相同目的而必须经历的所有杂乱结构。有很多优秀的 C++ 程序员明确表示,在 C++ 中确实不鼓励函数式编程,但是关于在 JavaScript 中进行函数式编程的文章比比皆是【参考方案7】:

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

【讨论】:

【参考方案8】:

如今,“函数式编程”语言这个术语已经被过度使用了,几乎没用了。主要有两种含义:

    具有一流的功能 Javascript 是这个! 基于 lambda 演算中使用的函数,重点是避免持久的可变状态(通常用传递给函数的参数替换它) 正如通常写的那样,Javascript 远非如此!

选择你的意思,然后问题就可以回答了。

【讨论】:

有没有使用“函数式编程”来指代具有一阶公民功能的语言的来源?。 @user411768:实际上,另一个回答者链接到***的文章,它使用了这个定义。 en.wikipedia.org/wiki/Javascript — Joel Spolsky 在他的“你的编程语言能做到这一点吗?”中也暗示了这个定义。发布“函数式编程”的好处 您注意到,正如通常所写的那样,JavaScript 没有使用您的第二点,但这当然并不意味着没有程序员这样做,并且该语言不支持这样一个功能,因为它确实有 @OpenLearner:嗯,是的,但 Java 和许多其他通常被认为是严格命令式的语言也是如此——你可以将它们写成函数式风格,但这不是语言的快乐之路。 ...但是最新的JS会支持它。【参考方案9】:

我真正讨厌 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 堆栈环境(如果它是正确的术语,我不知道)才能理解这种行为。

例如,在方案中你不能产生这样的东西(好的,好的——借助底层语言的引用你可以做到):

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

【讨论】:

嗯,我认为 Javascript 持有对 variable 的引用,但不持有对 value 的引用。 理解变量作用域对于任何语言的有效编程都至关重要。 Javascript 并不孤单。【参考方案10】:

@petraszd 我稍微重写了您的代码以获得“新” for 运算符:

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

但我知道这种方式对于大循环有缺点...

Related question about tail recurtion optimization in JS

附:发布在这里因为在作为评论发布时代码格式有问题

【讨论】:

【参考方案11】:

我不认为函数式编程有一个具体的定义,但是人们认为“函数式编程”的许多事情都可以用 javascript 完成。这是article.中的一个很好的简短示例

【讨论】:

【参考方案12】:

在 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 page 来演示这个概念,你可以克隆/查看我的实现

【讨论】:

这如何回答这个问题?【参考方案13】:

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

【讨论】:

【参考方案14】:

首先,我们必须定义函数式编程。我将其定义为本机支持和特权的编程风格的任何语言,这些编程风格由规范(或至少广泛认可的)函数式语言(如 Scheme、Racket、Haskell 或 Clojure)共享。

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

所有这一切都非常容易引发无休止的争论和吹毛求疵,但这个定义似乎足以证明 JS 不是一种严肃的函数式语言,并且可能永远不会比任何其他现代、多具有一流功能的范式语言。

让我们选择一个特定的功能。该语言应该执行tail call optimization,因此您可以在线性数据结构上本地编写递归函数。几乎所有主要的 JS 实现都未能提供我们对典型“函数式”语言(根据上述定义)所期望的基本特性,并且在撰写本文时还没有计划(详见Are functions in JavaScript tail-call optimized?)。

让我们从 TCO 中的怀疑和折腾中受益,但 JS 仍然无法提供您对“真正”函数式语言所期望的不变性设计目标的一点暗示。仅仅在语言中获得const 需要几十年的时间,并且默认情况下所有对象都是可变的。

由于向后兼容,这些问题并不能真正彻底解决;事实上,实际上不可能将已建立的多范式语言转变为真正的函数式语言。

JS 的功能与 Python、Perl、PHP 或 Ruby 差不多,它们都提供map/filter/reduce 对列表的操作并支持一流的函数或过程。一等函数的存在为编写函数式编程风格的代码提供了足够的空间。加入蹦床和 ramda.js,乍一看似乎很有说服力。

问题是一流的功能是否足以使语言“功能化”。实际上,Wikipedia lists all of the aforementioned as functional languages,但是,该列表几乎包括除 C 和 Go 之外的所有流行的、现代的、通用的语言(至少包括 explicitly identifies as not functional by design 的一种),所以我认为这个定义没有提供有很大的区别价值。

【讨论】:

以上是关于Javascript 是函数式编程语言吗?的主要内容,如果未能解决你的问题,请参考以下文章

为什么纯函数式语言至今无法流行起来?

Javascript 是函数式编程语言吗?

前端必学——函数式编程

浅析函数式编程与前端

iOS 中的链式编程函数式编程入门

JS中函数式编程基本原理简介