- クロージャって何がいいの? [転載禁止]©2ch.net
25 :デフォルトの名無しさん[sage]:2014/11/09(日) 18:24:28.78 ID:KOr7L+hP - >>20,21
関数型言語ではなく関数型プログラミングの話だと考えれば、 すでに多くの言語でクロージャという概念は幅広く普及していると言えるのではないかと たとえば C#、Java8、C++11、JavaScript、Ruby 等々 もちろん Python のように、クロージャが存在しない手続き型言語も広く使われているけどね また、C++ や Java でも古い規格だとクロージャは存在していなかった
|
- クロージャって何がいいの? [転載禁止]©2ch.net
28 :デフォルトの名無しさん[sage]:2014/11/09(日) 18:55:58.44 ID:KOr7L+hP - >>26
>>25 で挙げたクロージャを備えた言語は、どれも外の環境を掴んで ローカル変数に代入できる(=局所環境内の識別子に束縛できる) それに対して,Python のラムダ式では外の環境を掴めないからクロージャではない つまり Python は、クロージャを持たない手続き型言語 (ラムダ式ではなく)関数で外の環境を掴めるのは当たり前の話であり、嘘は良くない
|
- クロージャって何がいいの? [転載禁止]©2ch.net
29 :デフォルトの名無しさん[sage]:2014/11/09(日) 18:59:22.34 ID:KOr7L+hP - >>28 を訂正、ラムダ式(匿名関数)の話であるのを書き忘れていた
X:>25 で挙げたクロージャを備えた言語は、どれも外の環境を掴んで O:>25 で挙げたクロージャを備えた言語は、どれもラムダ式の中で外の環境を掴んで
|
- クロージャって何がいいの? [転載禁止]©2ch.net
36 :デフォルトの名無しさん[sage]:2014/11/09(日) 19:39:55.45 ID:KOr7L+hP - >>30
C#、Java8、C++11、JavaScript、Ruby 等々の関数型プログラミングが可能な言語では、 どれも「ラムダ式の中であっても外の環境を参照し、それを局所環境に保存」できる それに対して、Python だと「ラムダ式の中では外の環境を参照する」ことしかできない つまり、手続き型言語の Python は関数型プログラミングには不向きである、と言える >>31 >> 引数以外の変数を実行時の環境ではなく、 >> 自身が定義された環境(静的スコープ)において解決することを特徴とする。 クロージャを備えた言語ではクロージャ自身が局所環境を持つということだね(>>4 も参照) だから、関数内でもラムダ式内であっても局所環境で変数を解決できる それに対して(クロージャを備えず、代わりに)関数という実行環境しか持たない Python では、 関数内では変数を解決できてもラムダ式内で変数を解決できない つまり、Python はクロージャを持たない手続き型言語
|
- クロージャって何がいいの? [転載禁止]©2ch.net
38 :デフォルトの名無しさん[sage]:2014/11/09(日) 19:44:17.88 ID:KOr7L+hP - >>33
もちろん見えるよ ただしクロージャが無いから、その(ラムダ式の中から)見えた値を局所環境に保存できない 関数の中ならば(関数が持つ)局所環境に保存できるんだけどね....
|
- クロージャって何がいいの? [転載禁止]©2ch.net
42 :デフォルトの名無しさん[sage]:2014/11/09(日) 20:10:51.52 ID:KOr7L+hP - >>39
>・「変数を解決する」という用語が未定義 失礼、言語処理系や言語意味論を知らない人には難しい表現だった 「変数を解決する」とは、変数に束縛された値を求めることを意味する 単純な実装では、変数と値の対(ペア)の集合である環境から、変数をキーに値を探索することで実現できる >・「ラムダ式のみクロージャと認める」というのは>>31とは異なる定義だが、そのような定義をしている文献が引用されてない 「ラムダ式のみクロージャと認める」とは言っていないよ C#、Java8、C++11、JavaScript、Ruby 等々の一般的な言語では関数でもラムダ式でも局所環境を持てる これは「クロージャ自身が局所環境を持つ(>>4)」というクロージャ定義からすれば、自然な結果である それに対して、ラムダ式では局所環境を持てない Python にはクロージャの概念が欠落しているんじゃないのか? と指摘しているだけ あるいは処理系への実装を失敗した?、あるいは言語設計上の欠陥を見落とした?という指摘と言い換えてもいい Python の言語設計者達はクロージャの概念を知っているつもりだったのかもしれないけどね......
|
- クロージャって何がいいの? [転載禁止]©2ch.net
47 :デフォルトの名無しさん[sage]:2014/11/09(日) 20:34:00.52 ID:KOr7L+hP - >>43
言葉を「変数の再束縛」へ言い換えただけでは、結論は同じだよ C#、Java8、C++11、JavaScript、Ruby 等々の一般的な言語では関数やラムダ式はクロージャを元に 設計されているから、外の環境を参照した値を「局所変数に再束縛」できる それが当たり前で、自然な関数型プログラミングができる それに対して(クロージャを元にしていない)手続き型言語の Python では、 ラムダ式の中だと「局所変数に再束縛」できない 従って、手続き型言語の Python は関数型プログラミングには不向きである
|
- クロージャって何がいいの? [転載禁止]©2ch.net
52 :デフォルトの名無しさん[sage]:2014/11/09(日) 21:05:06.25 ID:KOr7L+hP - >>47
クロージャを備えた言語であれば、ラムダ式を入れ子にした複雑なコードを書かなくても、 単純明瞭で可読性の高いコードが書ける f = function(x) { y = 2 * x; z = x * y; return function(w) { return w * (y + z) } } g = f(2); print(g(3)); これがクロージャを備えた C#、Java8、C++11、JavaScript、Ruby 等々の普通の言語と 関数型プログラミングに不向きな手続き型言語 Python との違い
|
- クロージャって何がいいの? [転載禁止]©2ch.net
56 :デフォルトの名無しさん[sage]:2014/11/09(日) 21:14:02.40 ID:KOr7L+hP - (>>52 の続き)
もちろん関数型言語であれば、>>52 の JavaScript より更に簡潔になるのは当たり前の話 以下は Standard ML val f = fn x => let val y = 2 * x val z = x * y in fn w => w * (y + z) end val g = f 2 g 3
|
- クロージャって何がいいの? [転載禁止]©2ch.net
57 :デフォルトの名無しさん[sage]:2014/11/09(日) 21:18:46.76 ID:KOr7L+hP - >>53
>ラムダ式の入れ子は分かりにくいから >関数型プログラミングに向いてない 添削しよう: ラムダ式の入れ子は分かりにくいから、 ラムダ式の入れ子や関数内関数を多用しなければならない手続き型言語の Python は 関数型プログラミングに向いてない それに対して、クロージャを備えた C#、Java8、C++11、JavaScript、Ruby 等々の普通の言語では、 クロージャ自身が持つ局所環境内の変数に代入(=束縛)できるから、 関数型プログラミングに向いている
|
- クロージャって何がいいの? [転載禁止]©2ch.net
58 :デフォルトの名無しさん[sage]:2014/11/09(日) 21:25:01.25 ID:KOr7L+hP - >>50
Python ができるのは、引数に再束縛することだけ 局所変数(>>52,56 の y と z)には代入できない Python でも「ラムダ式では局所変数に再束縛できる」と主張したいのなら、 ラムダ式の入れ子や関数内関数を使わずに、可読性の悪い >>47 のコードを書き直しなさい もし Python に真のクロージャが存在するのなら、簡単な仕事のはずだ できるよね? できないのなら、嘘つきは君のほうだよ
|
- クロージャって何がいいの? [転載禁止]©2ch.net
62 :デフォルトの名無しさん[sage]:2014/11/09(日) 21:44:14.34 ID:KOr7L+hP - >>59,60
ぐだぐだ屁理屈を言うより、さっさと >>47 のコードを書き直した方がいいんじゃね? それとも Python コミュニティでは >>47 みたいな ラムダ式を入れ子にしたカッコだらけ のコードが可読性のある美しいコードなのかなあ 自分には、>>52,56 のほうが可読性の高いコードだと思うけどね
|
- クロージャって何がいいの? [転載禁止]©2ch.net
65 :デフォルトの名無しさん[sage]:2014/11/09(日) 21:50:58.85 ID:KOr7L+hP - >>61
>>4 で書いたように、クロージャは抽象的な概念だよ 言語の意味論を定義したり言語処理系を設計する時に用いられる抽象構文で現れる この抽象構文上のクロージャは、具象構文では一般にラムダ式とか無名関数(匿名関数)と呼ばれる たとえば Java 8 のラムダ式がそうだし、JavaScript の具象構文では function() { .... } と書き、 Standard ML では fn <id> => <expr> という具象構文で表現される
|
- クロージャって何がいいの? [転載禁止]©2ch.net
67 :デフォルトの名無しさん[sage]:2014/11/09(日) 21:58:19.30 ID:KOr7L+hP - >>64
自分も聞いたことないね そんなこと言ってるお馬鹿さんはいるのかな? まあ正確に言うと、クロージャを識別子に束縛したものが関数だから、 束縛されていない無名関数(=ラムダ式)と区別することが必要な文脈もあるけどね(>>4)
|
- クロージャって何がいいの? [転載禁止]©2ch.net
70 :デフォルトの名無しさん[sage]:2014/11/09(日) 22:10:31.90 ID:KOr7L+hP - >>63
普通は局所変数に代入するだろ、>>52 みたいに y = 2 * x z = x * y それとも、Python ではこんな単純な代入文も書かずに(書けずに?)、 わざわざ関数定義するのが当たり前なのかなあ?
|
- クロージャって何がいいの? [転載禁止]©2ch.net
72 :デフォルトの名無しさん[sage]:2014/11/09(日) 22:21:17.10 ID:KOr7L+hP - >>68
Yes/No であれば No だ 繰り返しになるけど、 真のクロージャを備えた C#、Java8、C++11、JavaScript、Ruby 等々におけるクロージャの定義と、 手続き型言語の Python におけるクロージャの定義は異なっている Python では識別子に束縛したクロージャ、いわゆる関数しか存在できず、 局所環境を伴うラムダ式を表現できない このため、>>47 のような ラムダ式が入れ子になったカッコだらけ の汚いコードしか書けない 結果として、Python は関数型プログラミングには不向きである
|
- クロージャって何がいいの? [転載禁止]©2ch.net
76 :デフォルトの名無しさん[sage]:2014/11/09(日) 22:31:31.78 ID:KOr7L+hP - >>71
>>38における「値を局所環境に保存」とは、識別子と値の対(ペア)を局所環境に追加すること(>>42 も参照) ここで、追加の時に既に同じ名前の識別子が存在していた場合、手続き型言語では値を破壊的に更新するけど、 関数型言語では新たに局所環境が生成される(=破壊的に更新しない)点が異なる ただし、この追加時の振る舞いの差異は、クロージャが存在する/しないとは無関係、ごっちゃにするのは間違い
|
- クロージャって何がいいの? [転載禁止]©2ch.net
77 :デフォルトの名無しさん[sage]:2014/11/09(日) 22:45:45.31 ID:KOr7L+hP - >>73
たとえば JavaScript なら、ラムダ式だけ(>>52)と関数定義との併用、 それらのどちらでも簡潔なコードが書けるよ function f(x) { y = 2 * x z = x * y return function(w) { return w * (y + z) } } g = f(2) g(3) 結局、Python では「ラムダ式を放棄して」関数定義しなければ簡潔なコードを書けない、 ということが実証されてしまったようだね つまり、真のクロージャを備えた C#、Java8、C++11、JavaScript、Ruby 等々のふつうの言語では、 ラムダ式だけでも関数定義との併用でも、ケースバイケースで選択して簡潔で可読性のあるコードを「書ける」けど、 手続き型言語の Python だとラムダ式だけでは「入れ子になったカッコだらけ」の汚いコード(>>47)しか書けないから、 常に関数定義で「書かなければならない」という違いがある
|
- クロージャって何がいいの? [転載禁止]©2ch.net
83 :デフォルトの名無しさん[sage]:2014/11/09(日) 22:56:21.23 ID:KOr7L+hP - >>73
ナゼ Python では、以下のような簡潔なコードが構文エラーになるんだろうね? f = lambda x: y = 2 * x z = x * y return lambda w: w * (y + z) g = f(2) g(3) これじゃあ「Python は関数型プログラミングに向かない」と評価されてもしかたないよね だって、真のクロージャを備えた C#、Java8、C++11、JavaScript、Ruby 等々のふつうの言語では、 >>52 みたいなラムダ式だけを使ったコードが何の苦もなく自然に書けるんだから
|
- クロージャって何がいいの? [転載禁止]©2ch.net
86 :デフォルトの名無しさん[sage]:2014/11/09(日) 23:08:28.24 ID:KOr7L+hP - >>80
>で、なぜ関数定義でクロージャが作れる >Pythonにクロージャがない事になるの? >>72 で書いたように、真のクロージャを備えた C#、Java8、C++11、JavaScript、Ruby 等々の ふつうの言語では(関数定義だけではなく)ラムダ式でもクロージャが作られるという違いがあるからだ 対して、Python のラムダ式ではクロージャが作られない(だから、局所変数へ値を代入できない) もし「Pythonにクロージャがない」という主張が不適切であるのならば、 >>42 の最後で書いたように、 「Python の言語設計者達は、処理系への実装を失敗した、あるいは言語設計上の欠陥を見落とした」 と言い換えてもいいよ こんな使い物にならないラムダ式で満足しなければならないとは、最大の被害者は Python プログラマだよね だって、他のふつうの言語であれば「ふつうに書ける」ことが、Python じゃ「書けない」のだから....(>>83)
|
- クロージャって何がいいの? [転載禁止]©2ch.net
88 :デフォルトの名無しさん[sage]:2014/11/09(日) 23:16:00.89 ID:KOr7L+hP - >>84
ラムダ式が引数に値を束縛できるのは、関数型言語を知っていれば常識だよ そんなことも知らないの? で、引数以外の局所変数に値を束縛するには、純粋なラムダ式に加えてクロージャが必要になるって話だよ
|
- クロージャって何がいいの? [転載禁止]©2ch.net
93 :デフォルトの名無しさん[sage]:2014/11/09(日) 23:27:54.79 ID:KOr7L+hP - >>90
>>88で書いたのは >>41 のラムダ式だけで書かれた Python コードだ 失礼した >>73 は関数定義でクロージャが作られているね ただし、Python だけがラムダ式ではクロージャが作られず、 Python におけるクロージャの定義が他の「普通の言語」と異なっている事実に変わりはない
|
- クロージャって何がいいの? [転載禁止]©2ch.net
95 :デフォルトの名無しさん[sage]:2014/11/09(日) 23:33:02.09 ID:KOr7L+hP - >>92
Python には真のクロージャが存在しない、という指摘は事実だよ(嘘ではない) もし「Python にも真のクロージャが存在する」と主張したいのなら、 >>83 のコードが構文エラーとならないように添削しなさい もし「Python にも真のクロージャが存在する」のなら、たやすい作業のはずだ 真のクロージャを備えた普通の言語では、何の苦も無く >>52 みたいなコードが書けるんだからね 君が嘘つきでなければ、書けるはず
|
- クロージャって何がいいの? [転載禁止]©2ch.net
100 :デフォルトの名無しさん[sage]:2014/11/09(日) 23:40:53.08 ID:KOr7L+hP - >>94
クロージャという概念を正しく理解していないと、 Python みたいなラムダ式に欠陥のある言語が設計されてしまうというお話だよ 言い換えると、クロージャという概念を用いると、 なぜ Python のラムダ式が欠陥品なのかを明解に説明できる このクロージャの利点は、このスレの主旨からは逸脱していないと思うよ
|
- クロージャって何がいいの? [転載禁止]©2ch.net
102 :デフォルトの名無しさん[sage]:2014/11/09(日) 23:57:43.62 ID:KOr7L+hP - >>98
No だね あえていえば「クロージャもどき」とか「なんちゃってクロージャ」だね 真のクロージャであれば無名関数でも間数定義でも作られ、 無名関数であってもクロージャを構成する局所環境を持つことができる これが、 C#、Java8、C++11、JavaScript、Ruby 等々の 「ふつうの言語」における「ふつうのクロージャ」だ おそらくクロージャを正しく理解していなかったんだろね、Python 言語設計者達は....
|