web-dev-qa-db-ja.com

Rubyは関数型言語ですか?

ウィキペディアによると、Rubyは関数型言語ですが、私は確信していません。

85
Esteban Araya

私は、あなたがRubyで機能的なスタイルを使用できると最も確実に思います。

関数型スタイルでプログラミングできるようにするための最も重要な側面の1つは、言語が高階関数をサポートしているかどうかです... Rubyはそうします。

そうは言っても、Rubyで非機能的なスタイルでプログラミングするのは簡単です。機能スタイルのもう1つの重要な側面は、状態を持たず、入力の特定のセットに対して常に同じ値を返す実際の数学関数を持つことです。これはRubyで実行できますが、Haskellのようなより厳密に機能するような言語では強制されません。

そのため、機能スタイルをサポートしていますが、非機能スタイルでもプログラムできます。

29
Mike Stone

言語が関数型言語であるかどうかは重要ではありません。関数型プログラミングは論文であり、Philip Wadler(関数型プログラミングの本質)とJohn Hughes(なぜ関数型プログラミングが重要なのか)によって最もよく説明されています。

意味のある質問は、「関数型プログラミングの論文を達成するのにどの程度寛容かRuby?)」です。答えは「非常に貧弱」です。

これについて最近話をしました。 スライドはこちらです

58
Tony Morris

Rubyは、高レベルの関数(Array#map、inject、およびselectを参照)をサポートしますが、それでも命令型のオブジェクト指向言語です。

関数型言語の重要な特徴の1つは、可変状態を回避することです。関数型言語には、Ruby、C、Java、または他の命令型言語であるような変数の概念はありません。

関数型言語のもう1つの重要な特徴は、「どのように」ではなく「何を」という観点でプログラムを定義することに焦点を合わせていることです。 OO言語でプログラミングする場合、実装( "how") "を" what "(クラス/メソッド名)から隠すクラスとメソッドを記述しますが、最終的にはこれらのメソッド関数型言語では、最低レベルであっても実行シーケンスを指定しません。

34
Mike

私は、機能的スタイルの言語でサポートする、またはプログラミングする能力を持っていることは、機能的言語を作るものではないことを提出します。

同僚や自分自身を傷つけたいなら、機能的なスタイルでJavaコードを書くことさえできます ヶ月 数週間。

関数型言語は、高階関数、一流の関数、カリー化など、canができることだけではありません。また、純粋な関数の副作用のように、あなたがcannotすることについても同じです。

これは、関数型プログラムが理由である理由の大部分であるため、または汎用の関数型コードが推論しやすいため、重要です。また、コードの推論が容易になると、バグはより浅くなり、修正できる概念の表面に浮かび上がり、バグの少ないコードが得られます。

Rubyはコアがオブジェクト指向であるため、機能的なスタイルを十分にサポートしていますが、Ruby自体は機能的な言語ではありません。

とにかくそれは私の非科学的な意見です。

編集:振り返ってみると、これまでこの回答に対して受け取ったすばらしいコメントを考慮して、オブジェクト指向と機能の比較はリンゴとオレンジの1つだと思います。

真の差別化要因は、実行において不可欠であるかどうかということです。関数型言語は、その表現を主要な言語構成体として持ち、実行順序は未定義または怠asであると定義されることがよくあります。厳密な実行は可能ですが、必要な場合にのみ使用されます。 imparative言語では、厳密な実行がデフォルトであり、遅延実行は可能ですが、多くの場合Edgeの場合に予測不可能な結果を​​もたらす可能性があります。

さて、that's私の非科学的意見。

15
Chris Vest

Rubyが「真に」機能するためには、次の要件を満たす必要があります。

不変の値:「変数」が設定されると、変更できません。 Rubyでは、これは変数を定数のように効果的に扱う必要があることを意味します。は言語で完全にサポートされていないため、各変数を手動でフリーズする必要があります。

副作用なし:指定された値が渡された場合、関数は常に同じ結果を返す必要があります。これは、不変の値を持つことに関連しています。関数は値を取得して変更することはできません。これは、結果を返すことに接する副作用を引き起こすためです。

高階関数:これらは、関数を引数として許可する関数、または関数を戻り値として使用する関数です。これはおそらく、関数型言語の最も重要な機能の1つです。

Currying:高階関数によって有効になり、カリー化は、複数の引数を取る関数を1つの引数を取る関数に変換します。これは、部分引数アプリケーションと連動します。部分引数アプリケーションは、複数の引数を持つ関数を、元の引数よりも少ない引数を取る関数に変換します。

再帰:内部から関数を呼び出してループします。可変データにアクセスできない場合は、再帰を使用してデータ構築を構築および連鎖します。これは、特定の時間にループの状態を保存するために変数を渡す必要があるため、ループは機能的な概念ではないためです。

遅延評価、または遅延評価:値の処理を実際に必要になる瞬間まで遅らせます。例として、遅延評価を有効にしてフィボナッチ数のリストを生成するコードがある場合、結果の値のいずれかがputなどの別の関数で必要になるまで、実際に処理および計算されません。

提案(考えているだけ)機能パラダイムでファイルを宣言するためのmodeディレクティブを持つ何らかの種類の定義があると素晴らしい

モード「機能」

11
Elias Perez

Rubyは、プログラミングの機能的なスタイルをサポートするマルチパラダイム言語です。

10
skymt

Rubyはオブジェクト指向言語であり、他のパラダイム(関数型、命令型など)をサポートできます。ただし、Rubyのすべてがオブジェクトであるため、主にOO言語です。

例:

"hello" .reverse()= "olleh"、すべての文字列は文字列オブジェクトインスタンスなどです。

読む here または here

4
camflan

「関数型言語」の定義に依存します。個人的には、この用語は絶対的なものとして使用すると、それ自体が非常に問題があると思います。これは、単なる言語機能よりも「関数型言語」であることの側面であり、ほとんどはあなたが探している場所に依存しています。たとえば、言語を取り巻く文化はこの点で非常に重要です。機能的なスタイルを奨励していますか?利用可能なライブラリはどうですか?機能的な方法で使用することを奨励していますか?

たとえば、ほとんどの人はSchemeを関数型言語と呼びます。しかし、Common Lispはどうですか?複数/単一の名前空間の問題と保証された末尾呼び出しの除去(コンパイラの設定に応じて一部のCL実装も同様にサポートします)を除き、SchemeをCommonよりも機能的なプログラミングに適した言語にするものはあまりありませんLISP、そしてそれでも、ほとんどのLispersはCLを関数型言語とは呼びません。どうして?それを取り巻く文化はCLの必須機能(たとえば、ほとんどのSchemersがおそらく眉をひそめるLOOPマクロなど)に大きく依存しているためです。

一方、CプログラマーはCLを関数型言語と見なすかもしれません。 LISPの方言で書かれたほとんどのコードは、結局のところ、通常のCコードのブロックよりもスタイルがはるかに機能的です。同様に、SchemeはHaskellと比較して非常に命令的な言語です。したがって、明確なyes/noの答えはありえないと思います。言語を関数型と呼ぶかどうかは、あなたの視点に大きく依存します。

4

関数型プログラミングでは再帰が一般的です。ほとんどすべての言語が再帰をサポートしていますが、再帰アルゴリズムは、 末尾呼び出し 最適化(TCO)がない場合、しばしば無効になります。

関数型プログラミング言語は末尾再帰を最適化でき、そのようなコードを一定のスペースで実行できます。いくつかのRuby実装は末尾再帰を最適化しますが、他の実装はそうではありませんが、一般的にRuby実装はTCOを行う必要はありません。 Does Rubyテールコールの最適化を実行しますか?

したがって、何らかのRuby機能スタイルを記述し、特定の実装のTCOに依存している場合、別のRubyインタープリターではコードが非常に無効になる可能性があります。 Rubyは関数型言語ではありません(Pythonでもありません)。

2
sastanin

Rubyは実際にはマルチパラダイム言語でもありません。マルチパラダイムは、多くの異なる分野で役立つものとして自分の好きな言語をラベル付けしたい人々によって使用される傾向があります。

私はRubyはオブジェクト指向のスクリプト言語です。はい、関数はファーストクラスのオブジェクト(一種)です。しかし、実際に関数型言語になりません。IMO、I追加するかもしれません。

2
JesperE

厳密に言えば、言語を「機能的」と表現するのは意味がありません。ほとんどの言語は関数型プログラミングが可能です。 C++です。

関数型は多かれ少なかれ命令型言語機能のサブセットであり、構文シュガーと、不変性や末尾再帰平坦化などのコンパイラー最適化でサポートされています。

後者はおそらく、実装固有のマイナーな技術であり、実際の言語とは関係ありません。 x64 C#4.0コンパイラーは末尾再帰の最適化を行いますが、x86コンパイラーは愚かな理由ではありません。

特に言語にプログラム可能なプリコンパイラがある場合(つまり、Cの#define)、構文糖は通常ある程度回避できます。

「言語__は命令型プログラミングをサポートしていますか?」と尋ねると、たとえばLISPの場合の答えは「いいえ」です。

2
Rei Miyasaka

本の冒頭をご覧ください: "A-Great-Ruby-eBook" 。それはあなたが尋ねている非常に具体的なトピックを議論します。 Rubyではさまざまな種類のプログラミングを行うことができます。機能的にプログラムしたい場合は、それを行うことができます。命令型のようにプログラミングしたい場合は、それを行うことができます。これは、定義上の質問です。Ruby最終的に。