ウィキペディアはRubyは関数型言語だと言っていますが、私は確信していません。なぜまたはなぜそうではないのですか?
12 に答える
言語が関数型言語であるかどうかは重要ではありません。関数型プログラミングは論文であり、Philip Wadler (The Essence of Functional Programming) と John Hughes (Why Functional Programming Matters) によって最もよく説明されています。
意味のある質問は、「Ruby は関数型プログラミングのテーゼを達成するのにどのくらい従順ですか?」です。答えは「非常に悪い」です。
私はつい最近、これについて講演しました。ここにスライドがあります。
Ruby は高レベルの関数 (Array#map、inject、および select を参照) をサポートしていますが、依然として命令型のオブジェクト指向言語です。
関数型言語の重要な特徴の 1 つは、可変状態を回避することです。関数型言語には、Ruby、C、Java、またはその他の命令型言語にあるような変数の概念がありません。
関数型言語のもう 1 つの重要な特徴は、「どのように」ではなく「何を」という観点からプログラムを定義することに重点を置いていることです。OO 言語でプログラミングする場合、実装 (「方法」) を「何」 (クラス/メソッド名) から隠すためにクラスとメソッドを記述しますが、最終的にこれらのメソッドは一連のステートメントを使用して記述されます。関数型言語では、最低レベルであっても実行順序を指定しません。
Rubyでは機能的なスタイルが使えると思います。
関数型でプログラムできるようにするための最も重要な側面の1つは、言語が高階関数をサポートするかどうかです...これはRubyがサポートします。
とは言うものの、Rubyで非機能的なスタイルでプログラミングするのも簡単です。関数スタイルのもう1つの重要な側面は、状態がなく、特定の入力セットに対して常に同じ値を返す実際の数学関数を持つことです。これはRubyで行うことができますが、Haskellのようなより厳密に機能するもののような言語では強制されません。
つまり、機能的なスタイルをサポートしますが、非機能的なスタイルでプログラムすることもできます。
私は、関数型スタイルの言語でプログラミングをサポートすること、またはプログラミングする能力を持っていることは、関数型言語を作るものではないことを提出します.
同僚を傷つけたいのであれば、Java コードを関数型スタイルで書くことさえできます。
関数型言語を持つことは、高階関数、一級関数、カリー化など、できることだけではありません。また、純粋な関数の副作用のように、できないことについてもです。
これは、関数型プログラム、または一般的な関数型コードが推論しやすい理由の大部分であるため、重要です。また、コードが簡単に推論できるようになると、バグは浅くなり、修正できる概念的な表面に浮かび上がり、バグの多いコードが少なくなります。
Ruby はその中核がオブジェクト指向であるため、関数型スタイルをかなり適切にサポートしていますが、それ自体は関数型言語ではありません。
とにかく、それは私の非科学的な意見です。
編集: 振り返ってみると、これまでにこの回答に対して受け取った素晴らしいコメントを考慮して、オブジェクト指向と機能の比較はリンゴとオレンジの 1 つだと思います。
真の差別化要因は、実行において命令的であるかどうかです。関数型言語は、主要な言語構造として式を持ち、実行順序は未定義であるか、遅延として定義されていることがよくあります。厳密な実行は可能ですが、必要な場合にのみ使用されます。命令型言語では、厳密な実行がデフォルトであり、遅延実行は可能ですが、多くの場合、実行するのが面倒であり、多くのエッジ ケースで予測できない結果になる可能性があります。
さて、それは私の非科学的な意見です。
Rubyは、機能的なプログラミングスタイルをサポートするマルチパラダイム言語です。
「関数型言語」の定義によって異なります。個人的には、この用語自体が絶対的なものとして使用されると、かなり問題があると思います. 「関数型言語」であることには、単なる言語機能というよりも多くの側面があり、そのほとんどはどこから見ているかに依存します。たとえば、言語を取り巻く文化は、この点で非常に重要です。機能的なスタイルを奨励していますか?利用可能なライブラリはどうですか?機能的な方法でそれらを使用することをお勧めしますか?
たとえば、ほとんどの人はSchemeを関数型言語と呼ぶでしょう。しかし、Common Lisp はどうだろうか? 複数/単一の名前空間の問題と保証された末尾呼び出しの除去 (コンパイラの設定に応じて、一部の CL 実装でもサポートされます) を除けば、Scheme が共通言語よりも関数型プログラミングに適した言語である理由はあまりありません。 Lisp、そしてそれでもなお、ほとんどの Lispers は CL を関数型言語とは呼びません。なんで?それを取り巻く文化は、CL の命令型機能に大きく依存しているためです (たとえば、ほとんどのスキーマ作成者はおそらく眉をひそめる LOOP マクロなど)。
一方、C プログラマーは CL を関数型言語と見なすこともできます。結局のところ、Lisp の方言で書かれたほとんどのコードは、通常の C コードのブロックよりもスタイルがはるかに機能的です。同様に、Scheme は Haskell と比較して非常に命令型の言語です。したがって、明確なイエス/ノーの答えはあり得ないと思います。言語を機能的と呼ぶかどうかは、あなたの視点に大きく依存します。
Rubyもマルチパラダイム言語ではないと思います。マルチパラダイムは、お気に入りの言語をさまざまな分野で役立つものとしてラベル付けしたい人に使用される傾向があります。
Rubyはオブジェクト指向のスクリプト言語だと思います。はい、関数はファーストクラスのオブジェクト(一種)ですが、それは実際には関数型言語にはなりません。IMO、追加するかもしれません。
厳密に言えば、言語を「関数型」と表現するのは意味がありません。ほとんどの言語は関数型プログラミングが可能です。C++でさえそうです。
関数型スタイルは多かれ少なかれ命令型言語機能のサブセットであり、構文糖衣と、不変性や末尾再帰の平坦化などのコンパイラの最適化でサポートされています。
後者は間違いなく、実装固有のマイナーな技術であり、実際の言語とは何の関係もありません。x64 C# 4.0 コンパイラは末尾再帰の最適化を行いますが、x86 コンパイラはなんらかの愚かな理由でそうしません。
シンタックス シュガーは、特に言語にプログラム可能なプリコンパイラ (つまり、C の #define) がある場合は、通常、ある程度回避することができます。
「言語 __ は命令型プログラミングをサポートしていますか?」と尋ねる方が、もう少し意味があるかもしれません。答えは、たとえば Lisp では「いいえ」です。
再帰は、関数型プログラミングでは一般的です。ほぼすべての言語が再帰をサポートしていますが、末尾呼び出しの最適化 (TCO) がなければ、再帰アルゴリズムは効果がないことがよくあります。
関数型プログラミング言語は、末尾再帰を最適化することができ、そのようなコードを定数空間で実行できます。末尾再帰を最適化する Ruby 実装もあれば、最適化しない Ruby 実装もありますが、一般に、Ruby 実装は TCO を実行する必要はありません。Ruby は末尾呼び出しの最適化を実行しますか?を参照してください。
そのため、Ruby の関数型スタイルを記述し、特定の実装の TCO に依存している場合、そのコードは別の Ruby インタープリターでは非常に効果がない可能性があります。これが、Ruby が関数型言語ではない (Python でもない) 理由だと思います。
本の冒頭をご覧ください: "A-Great-Ruby-eBook" . あなたが求めている非常に具体的なトピックについて説明します。Ruby ではさまざまな種類のプログラミングを行うことができます。関数のようにプログラムしたい場合は、それを行うことができます。命令型のようにプログラミングしたい場合は、それを行うことができます。最終的に Ruby がどの程度機能するかは、定義の問題です。ユーザー camflan による返信を参照してください。