Rubyは関数型言語ですか?


87

Wikipediaによると、Rubyは関数型言語ですが、確信はありません。なぜか、なぜそうでないのか?


4
おそらくあなたの質問は非常に短いためでしょう。個人的には私はまったく問題ありません!
ljs 2008年

すでに良い答えがありますので、それらを補足するために、FPとRubyについて説明する2つのコンテンツ:code.google.com/p/tokland/wiki/RubyFunctionalProgramming slideshare.net/tokland/functional-programming-with-ruby-9975242
tokland

1
誰かがこのトピックに興味がある場合は、これを見てください。関数型のルビの使用方法、関数型プログラミングのルーツ、および関数型プログラミングが可能な場合でも関数型言語ではないルビーについて学習してください:youtube .com / watch?v = 5ZjwEPupybw
maddin2code

回答:


29

Rubyでは関数型スタイルを使用できると思います。

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

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

つまり、そうです、機能的なスタイルをサポートしていますが、非機能的なスタイルでプログラミングすることもできます。


4
この基準を使用して、Smalltalkにはブロックがあるので機能していると思いますか?
OscarRyz 2010

良い答えですが、1つのヒントがあります。関数型には、高次関数厳密には必要ありません。たとえば、関数オブジェクトを定義し、それらを構成して高次関数と同じ効果を得ることにより、Java(第1クラス/高次関数を持たない)で関数スタイルを実現できます。
mikera

2
ちょうど、@ peterが尋ねたIs ruby a functional language?、そして正直な答えは単純なノーであると述べたいです。Rubyは、いくつかの機能を備えたオブジェクト指向言語です。
エリアスペレス

58

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

意味のある質問は、「Rubyは関数型プログラミングの論文を達成するのにどの程度順応できるか」です。答えは「非常に悪い」です。

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


3
あなたが提出したスライドは Rubyが「FPの論文を達成するのに非常に弱い」理由を述べていませんでした。C#がJavaよりも使いやすいのはなぜですか(わかりやすく、匿名関数が簡単ですか?)Rubyでグローバル変数を持つことができるからですか?
kizzx2

7
これは非常に広範なトピックであるため、スライドはこの詳細には入りません。たとえば、過度に単純化するリスクがある場合、Rubyはプログラムの非構成性を保証する評価モデル(値渡し)を適用します。この影響は簡単に過小評価される可能性があります。Rubyはまた、プログラムは一連の効果であるという考えと結婚しています。つまり、Rubyは他の計算モデルを使用することを困難/扱いにくいものにするための道を踏み出します。この短いコメントがお役に立てば幸いです。
Tony Morris

2
+1は、言語を関数型として分類する際のあいまいさを指摘します。地獄、私は関数型Cを書きました!
Eli

1
C#がRubyよりも使いやすいのはなぜですか?
dan_l 2013年

1
説明の重要な部分(実際には説明全体)を外部リンクに外部委託するため、リンクのみの回答が効果的です。リンクが消えたので、答えは役に立たなくなりました。
ivan_pozdeev

34

Rubyはより高いレベルの関数(Array#map、inject、&selectを参照)をサポートしていますが、それでもやはり必須のオブジェクト指向言語です。

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

関数型言語のもう1つの重要な特徴は、「方法」ではなく「何」でプログラムを定義することに焦点を当てていることです。オブジェクト指向言語でプログラミングするとき、実装(「方法」)を「何」(クラス/メソッド名)から隠すためにクラスとメソッドを記述しますが、結局これらのメソッドは一連のステートメントを使用して記述されます。関数型言語では、たとえ最下位レベルであっても、実行のシーケンスを指定しません。


3
私はあなたの発言のほとんどに同意しますが、「関数型言語には、Javaなどのように変数の概念がありません」には同意しません。haskellでは、純粋な関数で変数を使用できます。関数を変数に割り当てることもできます。最大の違いは、変数が割り当てられると、後で変更できないことです。
HHC 2013

6
HHCは、定義により、変数は変更可能な値です。あなたが話しているのは価値観です。
Scala Newb 2014

実際、Haskellの「変更不可能な変数」は、パラメーター(定義)のない定数関数です。
raindev 2014

16

私は、関数言語でサポートする、または言語でプログラムする能力を持つことは、関数言語が作成するものではないと提出します。

同僚や自分自身を数か月傷つけたい場合は、関数型のJavaコードを書くこともできます。

関数型言語を持つことは、高階関数、ファーストクラスの関数、カリー化など、できることだけではありません。それはまた、純粋な関数の副作用のように、あなたができないことについてでもあります。

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

Rubyは、その中心がオブジェクト指向であるため、関数型スタイルをある程度サポートしているにもかかわらず、それ自体が関数型言語ではありません。

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

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

本当の差別化要因は、実行において命令的であるかどうかです。関数型言語は、その主要な言語構成要素として式を持ち、実行の順序は、多くの場合、定義されていないか、遅延であると定義されています。厳密な実行が可能ですが、必要な場合にのみ使用されます。命令型言語では、厳密な実行がデフォルトであり、遅延実行は可能ですが、実行するのが難しい場合が多く、多くのエッジケースで予期しない結果が生じる可能性があります。

さて、それは私の非科学的な意見です。


Rubyよりも関数型の呼び出しの方がJavaよりもはるかに優れていると思います...いいえ、Rubyは厳密に機能しているわけではありませんが、関数型スタイルを使用するのは非常に簡単です...非関数型スタイルの同僚は簡単に機能しない状態に戻す
Mike Stone

1
はい、マイク、関数型のスタイルでコーディングしたい場合、RubyはJavaを大幅に改善したものです。私はJavaを使用して、要点を誇張して叩きました。
Chris Vest、

Dには純粋な関数があるので、Dを関数型言語と呼びますか? digitalmars.com/d/2.0/function.html#pure-functions
ピーターバーンズ

3
多くの人々は、主に匿名関数が広く使用されているため、LispおよびScheme関数型言語を検討しています。しかし、それらには保証された純粋な関数が欠けています。純粋な関数をサポートする言語に用語を限定することは、あまりにも制限が厳しすぎるようです。
2008年

13

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

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

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

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

カリー化:高次関数によって可能になるカリー化は、複数の引数を取る関数を1つの引数を取る関数に変換します。これは、複数の引数を持つ関数を、元の引数よりも引数の少ない関数に変換する部分的な関数の適用と連動しています。

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

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

提案(ちょうど考え) 私はある種の定義を持っていると素晴らしいと思いますmode機能的なパラダイムを使用してファイルを宣言するディレクティブをことです。例

モード「機能的」


2
どういたしまして。関数型言語についてお読みください。Lispは、すべての関数型言語、ML(CAML)およびErlang / Elixirの祖父母です。それは本当に物事のあなたの見方を変えます。私はまったく専門家ではありませんが、コンピュータサイエンスの常連の学生は、新しいものを読んだり、楽しんだりしています。
エリアスペレス

よく整理された答え。ルビーがこれらのものをどれだけうまくサポートしているかについての追加の探求が大好きだったでしょう。高次関数、カレー、再帰はすべてルビーでサポート/可能であると思います。間違っている場合は修正してください。
Michael Dorst、


4

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

例:

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

ここまたはここを読んでください


「すべてがオブジェクトである」ことがRubyをよりオブジェクト指向にする方法を本当に理解したことがありません。Rubyは主にOOであることに同意しますが、「すべてがオブジェクト」は、「プリミティブ」タイプがないことを意味するだけです。これは、プリミティブの存在を前提として、OOスタイルでプログラムを作成する開発者の能力にほとんど影響を与えません。タイプは一般に、メソッドを持たないタイプが4つまたは5つあることを意味します。
Michael Dorst、

4

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

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

一方、CプログラマーはCLを関数型言語と見なすことがよくあります。Lisp方言で記述されたほとんどのコードは、結局のところ、通常のCコードブロックよりもスタイルがはるかに機能的です。同様に、SchemeはHaskellと比較して非常に重要な言語です。したがって、明確なイエス/ノーの答えはあり得ないと思います。言語を関数型と呼ぶかどうかは、あなたの見方次第です。


Haskellは純粋に関数型言語ではないのですか?または、ミランダ(あまり知られていない関数型プログラミング言語)はどうですか?courses.cs.washington.edu/courses/cse505/99au/functional/…「Haskell は標準の純粋な関数型言語です」
barlop

2

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

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


4
言語のタイプは、サポートするプログラミングスタイルによって定義されます。これは、その機能によって決まります。ファーストクラスの匿名関数=最小限の関数型プログラミング。RubyはOOプログラミングをサポートしますが、それを必要としません。クラスを定義する必要はありません。したがって、マルチパラダイム。
2008年

2

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

関数型プログラミング言語は、末尾再帰を最適化でき、一定の空間でそのようなコードを実行できます。Rubyの実装には、末尾再帰を最適化するものとそうでないものがありますが、一般に、Rubyの実装はTCOを実行する必要はありません。Rubyが末尾呼び出しの最適化を実行するかを参照してください

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


TCOは興味深いものです。これは、プログラムの動作を本質的に変更するためです。場合によっては、これはプログラムからは見えませんが、例外バックトレースなどの場合もあります。したがって、常に適切な最適化とは限りません。
ioquatix 2014年

2

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

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

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

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

「言語__は命令型プログラミングをサポートしていますか?」と尋ねる方が少し意味があるかもしれません。たとえば、Lispでの答えは「いいえ」です。


1

「A-Great-Ruby-eBook」という本の冒頭をご覧ください。それはあなたが求めている非常に具体的なトピックについて説明します。Rubyではさまざまなタイプのプログラミングを行うことができます。機能的にプログラミングしたい場合は、それを行うことができます。命令的にプログラミングしたい場合は、それを行うことができます。結局のところ、Rubyがどのように機能するかという定義の問題です。ユーザーcamflanの返信をご覧ください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.