web-dev-qa-db-ja.com

JavaScriptは関数型プログラミング言語ですか

  • JavaScriptは関数型言語ですか?私はそれがオブジェクトを持っていることを知っています&OOPでそれを行うこともできますが、それも関数型言語ですか、それはそのように使用できますか?
  • あなたはOOPがプログラミングの次の進化のようになった/そう思われることを知っています、それは「関数型プログラミング」が次の進化であることを意味します(注:これは意見のプロンプトではありませんが、事実に基づく証拠に基づく回答。このメモは、寄稿者よりもモデレーター向けです;))。
  • 私は例を通して最もよく学びます。たぶん誰かが同じタスクをOOPの方法で実行してから、関数型プログラミングの方法で実行して、関数型プログラミングの機能を理解して比較することを示すことができます。

「関数型プログラミング」が正直であるとは完全には理解していません。

簡単な言葉で関数型プログラミングを表現するには、それは単に匿名関数を使用した抽象化の利点ですか?

それとも、その方法は単純すぎるのでしょうか。簡単に言えば、OOPはオブジェクトによる抽象化の利点ですが、OOPを説明するには少し単純すぎると思います。

これは関数型プログラミングの良い例ですか?...

JavaScript OOP例:

// sum some numbers
function Number( v )
{ 
  this.val = v;
}

Number.prototype.add( /*Number*/ n2 )
{
    this.val += n2.val;
}

関数型プログラミングの例:

function forEach(array, action) 
{
   for (var i = 0; i < array.length; i++)
       action(array[i]);
}  

function add(array)
{
    var i=0;
    forEach(array, function(n)
    {
        i += n;
    });
    return i;
}

var res = add([1,9]);
35
Marek

JavaScriptは関数型言語ですか?私はそれがオブジェクトを持っていることを知っています&OOPもできますが、それは関数型言語でもあり、そのように使用できますか?

命令型プログラミング または 手続き型プログラミング の場合、関数型プログラミングと呼ばれることがあります。厳密に言えば、 関数型プログラミング は:

コンピュータサイエンスでは、関数型プログラミングは、計算を数学関数の評価として扱い、状態および可変データを回避するプログラミングパラダイムです。状態の変化を強調する命令型プログラミングスタイルとは対照的に、関数の適用を強調します。関数型プログラミングは、関数の定義、関数の適用、および再帰を調査するために1930年代に開発された正式なシステムであるラムダ計算にルーツがあります。多くの関数型プログラミング言語は、ラムダ計算の詳細と見なすことができます。

JavaScriptは広く知られていないか、関数型言語として使用されていませんが、いくつかの 関数要素 があります。

JavaScriptはSchemeと多くの共通点があります。動的言語です。 s式を簡単にシミュレートできる柔軟なデータ型(配列)があります。そして最も重要なことに、関数はラムダです。

Scheme[〜#〜] lisp [〜#〜] の方言であり、おそらくほとんどのプログラマが考える言語の1つです関数型プログラミングについて話し合うときのことです。 オブジェクト指向 に関して言えば、Javascriptはオブジェクト指向言語です。しかし、そのオブジェクト指向は プロトタイプベース です:

プロトタイプベースのプログラミングは、クラスが存在しないオブジェクト指向プログラミングのスタイルであり、動作の再利用(クラスベース言語では継承と呼ばれます)は、プロトタイプとして機能する既存のオブジェクトを複製するプロセスを介して実行されます。このモデルは、クラスレス、プロトタイプ指向、またはインスタンスベースのプログラミングとしても知られています。委任は、プロトタイプベースのプログラミングをサポートする言語機能です。

そのため、JavaScriptはオブジェクト指向ですが、C++、C#、Javaなどの言語のように、より一般的な クラスベースのモデル には従いません) PHP(および他のかなりの数))そしてもちろん、それは命令型言語でもあり、これは私が上記で説明した関数型プログラミングとの混乱を招きます。

あなたはOOPがプログラミングの次の進化のようになった/ように見える方法を知っています、それは「関数型プログラミング」が次の進化であることを意味しますか

オブジェクト指向と関数型プログラミングは、多くの異なる プログラミングパラダイム の2つにすぎません。これらは、異なる概念と抽象化を備えた異なるプログラミングスタイルです。キーワードは「違う」です。他のものより優れている、または他のものより進化している単一のパラダイムはありません。一人一人が他のシナリオよりもいくつかのシナリオに適しています。 Originでは他のバージョンよりもかなり古いものもありますが、進化していくと、より長く存続するため、より良いものになります。しかし、それは非常にスマートな見方ではありません。

上で説明したように、また他のかなりの数の言語として、Javascriptはマルチパラダイムです。それはあなたが命令型のプロトタイプベースのオブジェクト指向で機能的なスタイルでコードを書くことを可能にします。構築するものに最も適合するものを選択するのは、あなた次第です。いくつかの単一パラダイム言語もあり、標準的な例はJavaで、クラスベースのオブジェクト指向プログラミングのみが可能です。1

言語とパラダイムをファッションステートメントとして扱う衝動に本当に抵抗する必要があります。がらくたがたくさんありますが、そのほとんどはファンボーイ/ファンガールまたはマーケティング担当者によって書かれており、プログラミングについての知識や知識はほとんどありません。 「より良い」、「より進化した」などの用語は適用されません。

私は例を通して最もよく学びます、おそらく誰かが同じタスクをOOPの方法で実行してから、関数プログラミングの方法で実行して、自分が何を理解して比較するかを示すことができます関数型プログラミングはする/する

それは恐ろしい学習方法でしょう。機能指向とオブジェクト指向はまったく異なるスタイルであり、非常に単純なもの以外の例は、どちらか一方のスタイルには適合しません。

1 しかし、最近その範囲を一般的なプログラミングに拡大しようとしています。それがどうなるか見てみましょう。


結論として:

  • Javascriptの学習に集中してください。それは、美しくて非常に役立つ言語です。誇大広告ではなく言語を学ぶ。
  • かなりいくつかの異なるパラダイムがあり、すべて同じように役立ちます。あなたが好きなものを選び、どれがあなたが構築しているものに最もよく合うかはあなた次第です。
  • 関数型プログラミングを学びたい場合は、Schemeや Clojure などのより適切な言語を選択してください。ただし、最初に、関連する数学的概念を理解する必要があります。
  • あなたが尋ねる前にいくつかの研究をしてください。あなたの質問のほとんどは、関連するウィキペディアの記事で答えられています。調査方法と質問方法を知ることは、プログラマーにとって非常に重要なスキルです。
73
yannis

JavaScriptは関数型言語として使用できますが、実際には非常にうまく機能しています。 monads を実装することは可能です。ラムダ構造などをサポートしています。これは、関数型言語だけではなく、オブジェクト指向の機能も多数備えていますが、そのように使用できます。実際、Javascriptを関数型言語として使用することは、Javascriptを使用する優れた方法であることがわかりました。 (jQueryとunderscore.jsの例)

8
Zachary K

進化とは通常、増分の変化を意味します。 OOPは手続き型プログラミングへの追加ではありません-実際、それは基礎となるプログラミングモデルと完全に直交しており、それらのモデルと組み合わせることができます。関数型プログラミングは手続き型への追加ではありません、OOPまたは何でも-それは基本的な計算原理を表現するための代替basisであり、実際には最初のコンピュータが登場するずっと前に、これまでに策定された最初のそのような基礎。そのようなすべての基本システムは同等であることを理解することが重要です(つまり、別の)。

関数型アプローチを理解するには、まず 基本的な数学 を取得する必要があります。 JavaScriptで関数型スタイルをコーディングすることの意味を知りたい場合は、 jQuery の使用を開始してください。

6
SK-logic

Javascriptは最初にプロトタイプであり、機能的な機能を備えています。ファーストクラスオブジェクトとしての関数の使用によって付与されます。

これは、関数をデータとして使用できることを意味し、状態を維持する変数の必要性を減らすという奇妙な効果があります。 varステートメントに手を伸ばしている場合、または1つ以上の「if」ステートメントを使用している場合は、機能的なスタイルから逸脱しています。

関数スタイルのもう1つの注目すべき特異性は、関数は評価の結果のみを返す必要があり、スコープ外の状態に副作用がないことです。

// oops, this is producing a side effect
function sideEffecter(){//theres no input...        
    window.thingy = 'foo';
    // hey, this isn't returning anything!!!
} 

関数型言語は非破壊的です。つまり、入力を変更するのではなく、入力に基づいてまったく新しいデータを返します。このスレッドを参照してください: https://stackoverflow.com/questions/749084/jquery-map-vs-each

関数型言語は、多くの共通のメソッドも備えています-リスト/コレクションを処理する「map」、「fold」、「reduce」のような名前です。 JSでは、他の言語とは異なり、これらを存在させる必要があります。いくつかの例については、underscore.jsのようなライブラリを参照してください。これらのいくつかは、すぐに使用できます。

覚えておかなければならない重要なこと(IMO)は、JSがsome機能パターンを利用できる一方で、そのときに実行できるとは限らないことです。

たとえば、配列を反復処理します。これは、関数スタイルまたはネイティブループ構造を使用して行うことができます。一般的に言えば、ループの方がパフォーマンスが優れています。この例を見てください-サイズの増加するループでヒットし、さまざまなブラウザーでの実行時間を記録します(これはすでに行っていますが、ベンチマークを失いました-すみません!):

var test = ['foo', 'bar', 'baz'], removeFunc, removeLoop;

//(semi)functional style...
// to be really functional each condition in the ternary would be another function
removeFunc = function(src, trg) {
    return src.length === 0 ? 
        src : 
            src[0] === trg ? 
                src.slice(1) : 
                    [src[0]].concat(removeFunc(src.slice(1), trg));
};

//but this is faster
removeLoop = function(src, trg){
    var len = src.length, // using variables to represent state...
        i=0, 
        result = [];        
    while(i < n){
       if(src[i] !== trg){
          result.Push(src[i]);
       }
       i = i+1;
    }
}

さらに、機能的な構造を使用してかなりのサイズのループをヒットし、なんらかの形式のアドホックスタック管理を利用しない場合、スタックをフラッディングする可能性があります(ただし、公平にするために、これを行うにはBIGリストが必要です。 ..)。また、各ブラウザーのバリアント最適化の組み合わせを考慮に入れる必要があります。ただし、Node.js環境で作業している場合、これは明らかに固定されたターゲットです。

これは、JavaScriptで関数構成体を使用してはならないということではありません。環境に対する実装の制限に注意してください。

ここにあなたに興味があるかもしれないいくつかのリンクがあります:

優れた「雄弁なJavaScript」からのJavaScriptでの関数型プログラミングの良い章

リトルスキーマー

私の友人がLittle Schemerに基づいたJSライブラリを書いた

FPをよりよく理解するのに役立つ可能性があるSchemeの優れたチュートリアル

2
sunwukung

いいえ

JavaScriptは何よりもまずオブジェクト指向言語です。

anyで関数型スタイルを採用できるので、JavaScriptプログラムを関数型スタイルで記述できないと言っているのではありません。必要に応じて、アセンブラで関数型プログラミングを行うことができます。しかし、これはすべての言語を機能させるではありません。同様に、Haskell命令、またはJava論理プログラミング言語)を呼び出すこともできます。このアプローチをとると、用語はすぐに無意味になります。

IMOで言語を適切なパラダイムに分類する方法は、次のことを考慮することです。

  • 言語構成によって有効になる主要なスタイルは何ですか(明らかにJavaScriptのOOP、関数型言語は代わりに関数と不変のデータ値を強調します)
  • 言語のコアライブラリでサポートされているパラダイム(ここでも明らかにOOP))
  • 言語で無効化または推奨されていない機能(関数型言語では、可変変数を禁止または禁止しますが、JavaScriptの場合はそうではありません)
  • 言語を使用する開発者のコ​​ミュニティで普及している開発スタイル(ここでも、OOPはJavaScriptの世界で明らかに普及しています)

個人的には、言語が現時点でトレンディな用語であるという理由だけで、言語が「機能的」であると主張するのを好む人が多いのはかなり面白いと思います:-)

長年プログラミングパラダイムについて少し長くて面白い見方が必要な場合は、一見の価値があります ボブマーティンおじさんのビデオ「最後のプログラミング言語」 。私にとって、この講演からの素晴らしい洞察は、プログラミングパラダイムは取り除いた機能によって定義され、彼らが入れた機能ではなく......

2
mikera