Wikipediaによると、Rubyは関数型言語ですが、確信はありません。なぜか、なぜそうでないのか?
Wikipediaによると、Rubyは関数型言語ですが、確信はありません。なぜか、なぜそうでないのか?
回答:
Rubyでは関数型スタイルを使用できると思います。
関数型スタイルでプログラミングできる最も重要な側面の1つは、言語がRubyのように高次関数をサポートしているかどうかです。
そうは言っても、Rubyで非機能的なスタイルでプログラミングするのも簡単です。関数スタイルのもう1つの重要な側面は、状態を持たず、特定の入力セットに対して常に同じ値を返す実際の数学関数を持つことです。これはRubyで実行できますが、Haskellのようなより厳密に機能するような言語では強制されません。
つまり、そうです、機能的なスタイルをサポートしていますが、非機能的なスタイルでプログラミングすることもできます。
Is ruby a functional language?
、そして正直な答えは単純なノーであると述べたいです。Rubyは、いくつかの機能を備えたオブジェクト指向言語です。
言語が関数型言語であるかどうかは重要ではありません。関数型プログラミングは論文であり、Philip Wadler(関数型プログラミングの本質)とJohn Hughes(関数型プログラミングが重要な理由)によって最もよく説明されています。
意味のある質問は、「Rubyは関数型プログラミングの論文を達成するのにどの程度順応できるか」です。答えは「非常に悪い」です。
最近、これについてお話しました。こちらがスライドです。
Rubyはより高いレベルの関数(Array#map、inject、&selectを参照)をサポートしていますが、それでもやはり必須のオブジェクト指向言語です。
関数型言語の主要な特徴の1つは、変更可能な状態を回避することです。関数型言語には、Ruby、C、Java、またはその他の命令型言語のように変数の概念がありません。
関数型言語のもう1つの重要な特徴は、「方法」ではなく「何」でプログラムを定義することに焦点を当てていることです。オブジェクト指向言語でプログラミングするとき、実装(「方法」)を「何」(クラス/メソッド名)から隠すためにクラスとメソッドを記述しますが、結局これらのメソッドは一連のステートメントを使用して記述されます。関数型言語では、たとえ最下位レベルであっても、実行のシーケンスを指定しません。
私は、関数型言語でサポートする、または言語でプログラムする能力を持つことは、関数型言語が作成するものではないと提出します。
同僚や自分自身を数か月傷つけたい場合は、関数型のJavaコードを書くこともできます。
関数型言語を持つことは、高階関数、ファーストクラスの関数、カリー化など、できることだけではありません。それはまた、純粋な関数の副作用のように、あなたができないことについてでもあります。
これが重要なのは、関数型プログラム、または一般的な関数型コードが推論しやすい理由の大部分であるためです。そして、コードが推論しやすくなると、バグはより浅くなり、修正できる概念面に浮かぶため、バグの少ないコードが得られます。
Rubyは、その中心がオブジェクト指向であるため、関数型スタイルをある程度サポートしているにもかかわらず、それ自体が関数型言語ではありません。
それはとにかく私の非科学的な意見です。
編集: 振り返ってみると、これまで私がこの回答を受け取った細かいコメントを考慮して、オブジェクト指向と機能の比較は、リンゴとオレンジの1つだと思います。
本当の差別化要因は、実行において命令的であるかどうかです。関数型言語は、その主要な言語構成要素として式を持ち、実行の順序は、多くの場合、定義されていないか、遅延であると定義されています。厳密な実行が可能ですが、必要な場合にのみ使用されます。命令型言語では、厳密な実行がデフォルトであり、遅延実行は可能ですが、実行するのが難しい場合が多く、多くのエッジケースで予期しない結果が生じる可能性があります。
さて、それは私の非科学的な意見です。
Rubyが「真に」機能するためには、次の要件を満たす必要があります。
不変の値:「変数」がいったん設定されると、変更できません。Rubyでは、これは変数を定数のように扱う必要があることを意味します。は言語で完全にサポートされていないため、各変数を手動でフリーズする必要があります。
副作用なし:指定された値が渡された場合、関数は常に同じ結果を返す必要があります。これは不変の値を持つことと関連しています。関数は値を取得して変更することはできません。これは、結果を返すことに正接する副作用を引き起こすためです。
高階関数:これらは関数を引数として許可する関数、または関数を戻り値として使用する関数です。これは間違いなく、関数型言語の最も重要な機能の1つです。
カリー化:高次関数によって可能になるカリー化は、複数の引数を取る関数を1つの引数を取る関数に変換します。これは、複数の引数を持つ関数を、元の引数よりも引数の少ない関数に変換する部分的な関数の適用と連動しています。
再帰:内部から関数を呼び出すことによるループ。変更可能なデータにアクセスできない場合は、再帰を使用してデータ構築を構築およびチェーンします。これは、特定の時点でループの状態を格納するために変数を渡す必要があるため、ループは機能的な概念ではないためです。
遅延評価、つまり遅延評価:実際に必要になる瞬間まで値の処理を遅らせます。例として、遅延評価を有効にしてフィボナッチ数のリストを生成するコードがある場合、結果の値の1つがputsなどの別の関数によって要求されるまで、これは実際には処理および計算されません。
提案(ちょうど考え)
私はある種の定義を持っていると素晴らしいと思いますmode
機能的なパラダイムを使用してファイルを宣言するディレクティブをことです。例
モード「機能的」
それは、「関数型言語」の定義に依存します。個人的には、この用語を絶対的なものとして使用する場合、それ自体がかなり問題になると思います。単なる言語機能よりも「関数型言語」であることに多くの側面があり、ほとんどはどこから見ているかに依存します。たとえば、言語を取り巻く文化はこの点で非常に重要です。機能的なスタイルを奨励していますか?利用可能なライブラリはどうですか?それらを機能的な方法で使用するように勧めていますか?
たとえば、ほとんどの人はSchemeを関数型言語と呼びます。しかし、Common Lispはどうですか?複数/単一の名前空間の問題と保証された末尾呼び出しの排除(コンパイラーの設定によっては、一部のCL実装でもサポートされる)を除いて、SchemeをCommonよりも関数型プログラミングに適した言語にする要素はあまりありません。 Lisp、そしてそれでも、ほとんどのLispersはCLを関数型言語とは呼びません。どうして?それを取り巻く文化はCLの必須機能に大きく依存しているため(たとえば、ほとんどのSchemersがおそらく嫌うLOOPマクロなど)。
一方、CプログラマーはCLを関数型言語と見なすことがよくあります。Lisp方言で記述されたほとんどのコードは、結局のところ、通常のCコードブロックよりもスタイルがはるかに機能的です。同様に、SchemeはHaskellと比較して非常に重要な言語です。したがって、明確なイエス/ノーの答えはあり得ないと思います。言語を関数型と呼ぶかどうかは、あなたの見方次第です。
Rubyもマルチパラダイム言語ではありません。マルチパラダイムは、多くの異なる分野で役立つものとしてお気に入りの言語をラベル付けしたい人々によって使用される傾向があります。
Rubyはオブジェクト指向のスクリプト言語です。はい、関数はファーストクラスのオブジェクト(一種)ですが、それでも関数型言語にはなりません。IMO、追加するかもしれません。
再帰は関数型プログラミングでは一般的です。ほとんどすべての言語が再帰をサポートしていますが、末尾呼び出しの最適化(TCO)がない場合、再帰アルゴリズムは効果がないことがよくあります。
関数型プログラミング言語は、末尾再帰を最適化でき、一定の空間でそのようなコードを実行できます。Rubyの実装には、末尾再帰を最適化するものとそうでないものがありますが、一般に、Rubyの実装はTCOを実行する必要はありません。Rubyが末尾呼び出しの最適化を実行するかを参照してください。
そのため、Rubyの機能スタイルを記述し、特定の実装のTCOに依存している場合、コードは別のRubyインタープリターでは非常に効果がない可能性があります。これがRubyが関数型言語ではない(Pythonでもない)理由です。
厳密に言えば、言語を「関数型」と表現しても意味がありません。ほとんどの言語は関数型プログラミングが可能です。C ++もです。
関数スタイルは、多かれ少なかれ、命令型言語機能のサブセットであり、構文シュガーと、不変性や末尾再帰のフラット化などのコンパイラの最適化でサポートされています。
後者は間違いなく実装固有のマイナーな技術であり、実際の言語とは何の関係もありません。x64 C#4.0コンパイラーは末尾再帰の最適化を行いますが、x86コンパイラーは愚かな理由のために行いません。
特に言語にプログラム可能なプリコンパイラー(つまり、Cの#define)がある場合は、通常、構文糖衣はある程度は回避できます。
「言語__は命令型プログラミングをサポートしていますか?」と尋ねる方が少し意味があるかもしれません。たとえば、Lispでの答えは「いいえ」です。
「A-Great-Ruby-eBook」という本の冒頭をご覧ください。それはあなたが求めている非常に具体的なトピックについて説明します。Rubyではさまざまなタイプのプログラミングを行うことができます。機能的にプログラミングしたい場合は、それを行うことができます。命令的にプログラミングしたい場合は、それを行うことができます。結局のところ、Rubyがどのように機能するかという定義の問題です。ユーザーcamflanの返信をご覧ください。