- クロージャって何がいいの? [転載禁止]©2ch.net
237 :デフォルトの名無しさん[sage]:2014/12/14(日) 20:48:34.17 ID:lkA9lgpO - >>228
>Rubyのブロックはラムダじゃないしファーストクラスでもないよね? Python や JavaScript のクロージャは、(名前が宣言された)関数と同様に クロージャへ引数を渡すだけで評価される closure = function(x) { return x + 1 } # クロージャを生成して名前に束縛 succ_of_one = closure(1) # クロージャを評価 それに対して Ruby だと、メソッド Proc#call を呼ばなければ評価されない block = lambda { |x| x + 1 } # ブロックを生成して名前に束縛 succ_of_1 = block.call(1) # ブロックを評価 従って >>4(>>199) の関数型言語におけるクロージャ定義に当てはめれば 「Ruby のブロックは(本物の)クロージャではない」あるいは「....はクロージャもどきである」 またRuby のブロックの意味はオブジェクト(Procクラスのインスタンス)だからファーストクラスである >メソッドにラムダを渡すこともできるけど、不格好なんだが? たしかに不格好だ def foo(x, y, &block); .... ; end # メソッドを定義 foo(x, y, lambda { |z| .... }) # メソッドの呼び出し だから Ruby には「ブロック付きメソッド呼び出し」という構文糖が最初から用意されている def foo(x, y); .... ; end # メソッドを定義 foo(x, y) { |z| .... } # メソッドの呼び出し >Pythonの仕様をあげつらうためだけにオレオレ定義をこねくって >>4 のクロージャ定義の引用元(ソース)は >>199 で示したが、まともな反論はない むしろオレオレ定義と騒ぎ立てていた連中がSICP本を読んだ事もないお馬鹿達だったのでは? あるいはSICP本を読んでいなくても、関数型言語の操作的意味論や処理系実装の知識があれば >>4 がオレオレ定義でないことは直ぐに理解できていたはず
| - クロージャって何がいいの? [転載禁止]©2ch.net
241 :デフォルトの名無しさん[sage]:2014/12/14(日) 22:03:54.59 ID:lkA9lgpO - >>229
残念ながら Ruby の関数型プログラミングというスタイルは、 全世界の Ruby コミュニティですでに認知されている ・Functional programming with Ruby http://code.google.com/p/tokland/wiki/RubyFunctionalProgramming ・Rubyによる関数型プログラミング(上記文書の日本語訳) www.h6.dion.ne.jp/~machan/misc/FPwithRuby.html また Ruby の「ブロック付きメソッド呼び出し」とそれらを並べる(=チェーンさせる)スタイルは、 Apple の新言語である Swift にそのまま採用された 他の言語、たとえばラムダ式が導入された Java 8 だと、このスタイルをストリームと呼んでいる ・ラムダ式で本領を発揮する関数型インターフェースとStream APIの基礎知識 (2/3) -- @IT http://www.atmarkit.co.jp/ait/articles/1404/30/news017_2.html 個人的には、Ruby と多くのOOP言語で採用されているメソッドチェーン・スタイルは: ・データの流れ(いわゆるデータフロー)とメソッドの並びが一致し、 ・カッコが入れ子にならない から、可読性が高いと思う table.select { |r| .... }.map { |r| .... }.inject(0) { |n, r| .... } # >>189 を参照 それに対して、Python 伝統的な関数適用スタイルでは: ・データの流れ(いわゆるデータフロー)とメソッドの並びが逆転し、 ・カッコが入れ子になる reduce(lambda n, r: ...., 0, map(lambda r: ...., filter(lambda r: ...., table))) どちらを優れているか?という評価は主観だから、各自で判断してもらいたい (まだ続くので、ここで切る)
| - クロージャって何がいいの? [転載禁止]©2ch.net
242 :デフォルトの名無しさん[sage]:2014/12/14(日) 22:48:49.10 ID:lkA9lgpO - >>238
次に、関数型プログラミングと(文の評価によって起こる)副作用との関連について まず関数型プログラミングで副作用は推奨されていない 基本的には map/filter/reduce (Ruby では map/select/inject) といった高階関数を使った (副作用の無い)参照透明性のあるコードが推奨されている これは >>241 の文書「Rubyによる関数型プログラミング」で具体的なコード例を使って解説されている おそらく誤解したのは >>189 の Swift/Ruby/JavaScript コードで while 文と ローカル変数への破壊的代入を用いていたのを見たからだと思うけど、 これは、「わざわざ」副作用を使った手続き型プログラミングほうが簡潔になる「お題」を選んだからだ 実際、副作用の代わりに再帰を使った Python コード >>205 は「普通のプログラマ」には分かりにくい (Python だけでなく、この「お題」は Ruby であっても再帰を使えば同じく分かりにくいコードになる) また(Ruby を含む)大半の手続き型言語処理系だと、TCO(末尾再帰最適化)は実装されていないか不完全である だから手続き型言語における関数型プログラミングにおいて、 再帰プログラミングには(分かりづらいだけでなく)実用上の制限があるから ツリーのような再帰的データ構造の探索問題などに限定して利用すべき(上記文書の節「再帰」を参照) これらの判断について、上記の文書では以下のように記述されている(節「おわりに」から引用): 「Rubyは基本的には命令型言語であるけれど、 関数型プログラミングへの際立った潜在能力があるのだから、 それらをいつどのように使うか(そして、いつ使わないか)を知っておくべきである。 」
| - クロージャって何がいいの? [転載禁止]©2ch.net
244 :デフォルトの名無しさん[sage]:2014/12/14(日) 23:34:55.92 ID:lkA9lgpO - >>231
>Rubyには「他言語の関数」に相当するものがなく、...... これは(>>237 に書いたけど)、まったくそのとおり >でもRubyのブロックはファーストクラスとは言い難い。 ここの「....とは言い難い」という文章表現は曖昧だね (なぜ「....ではない」と断定的に言い切れなかったのだろうか?) まず >>237 で書いたように、Ruby の「ブロック付きメソッド呼び出し」は構文糖だ (対して、簡潔な構文を追求した Smalltalk では、常にブロックはオブジェクトである) これを構文糖にした理由の一つはメソッド呼び出しコードを簡潔にする目的(>>237)であるが、 ブロックを多用する Ruby のプログラミングスタイルでは、ブロックを評価するたびに Procオブジェクトを生成していたのでは実行効率の面でオーバヘッドが大きいという理由がある このためRubyインタプリタの内部だと、 ブロックは(重いオブジェクトを表すC構造体ではなく)専用の軽量なC構造体で表現されている ただし、(たとえ内部表現が Proc オブジェクトと異なっていても)プログラマから見れば問題にならない なぜなら、渡されたブロックをいつでも Proc オブジェクトへ変換できる構文糖が最初から用意されているから.... たとえば foo(x, y) { |z| .... } という「ブロック付きメソッド呼び出し」に対して(>>237): ・def foo(x, y); .... ; end ・def foo(x, y, &block); .... ; end という2つのメソッド定義は「いつでも」交換できる まとめると: Ruby のブロックは内部表現だと Proc オブジェクトではないが、 プログラマ目線ではファーストクラスのオブジェクトとして扱うことができる
| - クロージャって何がいいの? [転載禁止]©2ch.net
246 :デフォルトの名無しさん[sage]:2014/12/14(日) 23:49:27.85 ID:lkA9lgpO - >>238
つまり「Ruby のブロックはクロージャである」という初歩的なミスについて、 >>102 をレスした時点から数えて >>228 が指摘するまでの間には 誰一人気付けなかった事実が「掲示板にはログが残ってるから明らか」になるわけですね た い へ ん わ か り や す い で す
|
|