1 名前:デフォルトの名無しさん [2014/11/08(土) 13:11:47.84 ID:6V2MLUHb.net] 関数型言語に必ずくっついてるこれ いらんでしょ?匿名クラスで充分でしょ
2 名前:デフォルトの名無しさん mailto:sage [2014/11/08(土) 13:17:58.06 ID:rszc5DFq.net] マジレスすると、クロージャーよりも 関数内関数の方がいい。 クロージャーは変数スコープが不必要に広い。 多くの場合、クロージャーの外は見える必要がない。 逆に見えてしまうと不用意に変数を書き換えてしまう。 関数内関数がない言語が多いから 仕方なくクロージャーを使うしかないが、 Java8のラムダの方がまだ安全なコードを書くことが出来る。 (ラムダも外のスコープが参照できる場合があるので完璧ではない) つまり俺がいいたいのは、クロージャーを使うと苦労するのジャー。
3 名前:デフォルトの名無しさん mailto:sage [2014/11/08(土) 13:42:47.14 ID:alIlcZLx.net] ディスクロージャ
4 名前:デフォルトの名無しさん mailto:sage [2014/11/08(土) 14:33:50.79 ID:Wb7Sa5AG.net] >>1 関数型言語の操作的意味論において、クロージャとは: 「ラムダ式と局所環境とを組合せた概念」 を指す このクロージャを具象構文で表したものが一般的な「ラムダ式」であり、 クロージャを識別子に束縛したものが一般的な「関数宣言」である Standard ML という関数型言語だと、 たとえばラムダ式は fn x => x + 1 であり、関数宣言は val succ = fn x => x + 1 である ここで、関数宣言には fun succ x = x + 1 と簡潔に書ける構文糖を用いるのが一般的 だから、あらゆる関数型言語ないし関数型プログラミングが可能なあらゆる言語であれば、 クロージャ(という概念)は必要不可欠に存在である、と言える また Java の「匿名クラス」もクロージャ(という概念)を応用した具象構文の一種である で、Java 8 で導入された「ラムダ式」もクロージャの具象構文だけど、 匿名クラスよりも簡潔に書ける利点があるから、多くのケースで広く利用されるようになるだろう 両者の間には、局所環境と組み合わせる対象が「匿名クラス」ではクラスという単位であるのに対して、 「ラムダ式」では式という(クラスよりも粒の小さな)単位であるという違いがある 目的に応じて適切に両者を使い分けることが望ましい
5 名前:デフォルトの名無しさん mailto:sage [2014/11/08(土) 16:17:08.12 ID:gNjtEENQ.net] / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄\ ∠ ノ 丶 | ノ | | / ̄ ̄ ̄ ̄\ | | / ヽ | | | | | | | | | | | | | / | | / ヽ \_/| |\_/ ヽヘ | / \ /  ̄ ̄ ̄ ̄ ̄ ̄  ̄ ̄ ̄ ̄ ̄ ̄ パンとか止めるやつ
6 名前:デフォルトの名無しさん [2014/11/08(土) 16:19:08.12 ID:gwropNof.net] >>5 それ、パンとか止めるやつだろ!
7 名前:デフォルトの名無しさん mailto:sage [2014/11/08(土) 16:28:06.78 ID:Z0nNiFel.net] / ̄ ̄\ / _ノ ヽ、_ \ . | ( ●)(● ) | ,-,-,-,__ | (__人__) │rヽヽヽヽ__ 「クイックロック バッグ クロージャー!!」 r.l .' ' .'.r_l | `⌒ ´ . | ´l .|/ .ヽ| | | | | /_ ._,,-ーヽ /-‐ ヽ /‐''",' /. `ヽ / /`''‐-',. ヽ ./ rj,.-‐''´`l ./ \ | 二ヽ ヽ三 |ー‐'´ `''‐ヽ ―`ヘ j `―r'´ `T ´ j. ./ j ヽ .ヽ、 ___ / ,' | ./(>)^ ヽ\ i | ./ (_ (<) \ .i / .! ./ /rェヾ__)⌒::: ヾ.\ / ∧i. `⌒´-'´ u; ノ ヽ | .\ヽ 、 , / | .ヽ ',. ー 一 ./ / ', .', ./ / .', ', / / /ヽ、 \ / / / | ヽ―‐/ ./ \ ./ .l 丿 ゝ ( ヽ / / / \ ', ', / /-‐''´ `''‐| ', ./ __| . / .', | `ヽ、 ./ ̄ .| | ヽ / / `"''-,,__ ,,,,丿 ゝ、__,,-''
8 名前:デフォルトの名無しさん [2014/11/08(土) 18:29:54.75 ID:+pW0VlFs.net] >>1 匿名クラスは嫌。 まぁ俺の用途では関数内関数で十分なことが多い。 なのでけっこう>>2 には同意。
9 名前:デフォルトの名無しさん mailto:sage [2014/11/08(土) 18:31:45.04 ID:Z0nNiFel.net] >>8 最後の行に同意してくれてありがとう
10 名前:デフォルトの名無しさん mailto:sage [2014/11/08(土) 21:41:30.87 ID:1bx+kI6Q.net] おもてたんとちゃうこのスレ
11 名前:デフォルトの名無しさん mailto:sage [2014/11/08(土) 22:16:16.20 ID:BzSpEdoH.net] クロージャーってただのメソッド一つのクラスだろ
12 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 01:25:23.88 ID:5LKfT6rZ.net] まじすか
13 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 02:04:06.76 ID:8LiWtrih.net] という見方、扱い方もできるねって話だろ
14 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 03:36:21.74 ID:Rov3GL+Ot] A{B{C}} というスコープがあるとき、一般的には、 C→Bのように、内から外はアクセスできるが、 A→Bのように、外から内はアクセスできない ここで、Aからクロージャで、Bの内部関数Cを返すと、 Cは自分の外部環境Bを保持しており、 CからBをアクセスできるので、その結果、 AからBの環境にもアクセスできる
15 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 05:57:17.96 ID:n2NDOrh4.net] ActionListenerなんて、実装当時にクロージャがあったら存在してたかどうか怪しいクラスだよね
16 名前:デフォルトの名無しさん [2014/11/09(日) 07:54:16.27 ID:6VpE/OBT.net] lispの方言かとおもった
17 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 09:19:55.73 ID:nlmXbEn2.net] >>2 関数型言語では、基本的に変数を書き換えるのは例外的な操作だから 不用意に変数を書き換えることは殆ど無いし、 それなら環境が見えてる事のメリットの方が大きい
18 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 10:23:47.55 ID:gYZvrVR/.net] >>11 複数にできるよ
19 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 16:16:30.86 ID:K4BO8Ja1.net] 関数内で関数が定義できる事とクロージャと何の関係があるんだ? 比較できるものじゃないでしょ
20 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 16:48:40.28 ID:EbU/SVlS.net] まあ、クロージャは関数内関数の用途をも内包することは多いんじゃね?
21 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 17:24:14.45 ID:xhtawW2X.net] >>17 それはあまり使われていない関数型言語限定の話ですね。
22 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 17:32:09.95 ID:PiaxZAwM.net] >>1 は関数型言語の話をしてるんじゃないのか。 > 関数型言語に必ずくっついてるこれ
23 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 17:38:41.70 ID:50xVLBic.net] オレオレ言語仕様を考えてるんだけどさ今どの言語を見てもlambdaだらけじゃない RAII出来る言語だとクロージャに環境掴まれるだけでリソースリークしそうなわけよ ならイランでしょ?というわけでたてた
24 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 18:18:41.40 ID:K4BO8Ja1.net] クロージャだからって外の環境全部掴む必要無いんじゃね クロージャが使用してない変数については各スコープのタイミングで解放すれば十分じゃないの
25 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 18:20:47.86 ID:xhtawW2X.net] evalが使える言語では、使用していないかどうか 実行するまでわからないのでそれは無理。
26 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 18:24:28.78 ID:KOr7L+hP.net] >>21 ,21 関数型言語ではなく関数型プログラミングの話だと考えれば、 すでに多くの言語でクロージャという概念は幅広く普及していると言えるのではないかと たとえば C#、Java8、C++11、JavaScript、Ruby 等々 もちろん Python のように、クロージャが存在しない手続き型言語も広く使われているけどね また、C++ や Java でも古い規格だとクロージャは存在していなかった
27 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 18:40:07.36 ID:lx9et4kr.net] Pythonの関数は外の環境掴んでるからクロージャ 嘘は良くない
28 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 18:40:57.06 ID:nlmXbEn2.net] >>25 クロージャじゃなくてevalを禁止すれば良いんじゃね?
29 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 18:55:58.44 ID:KOr7L+hP.net] >>27 >>26 で挙げたクロージャを備えた言語は、どれも外の環境を掴んで ローカル変数に代入できる(=局所環境内の識別子に束縛できる) それに対して,Python のラムダ式では外の環境を掴めないからクロージャではない つまり Python は、クロージャを持たない手続き型言語 (ラムダ式ではなく)関数で外の環境を掴めるのは当たり前の話であり、嘘は良くない
30 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 18:59:22.34 ID:KOr7L+hP.net] >>29 を訂正、ラムダ式(匿名関数)の話であるのを書き忘れていた X:>26 で挙げたクロージャを備えた言語は、どれも外の環境を掴んで O:>26 で挙げたクロージャを備えた言語は、どれもラムダ式の中で外の環境を掴んで
31 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 19:03:23.62 ID:lx9et4kr.net] >>29 ラムダ式では代入は出来ないけど外の環境は掴んでるからクロージャ 嘘は良くない
32 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 19:08:15.30 ID:nlmXbEn2.net] 不毛だからケンカする前に用語を定義しろよ オレオレ定義じゃないんだったら引用も必要 ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%83%BC%E3%82%B8%E3%83%A3 > クロージャ(クロージャー、英: closure)、関数閉包はプログラミング言語における関数オブジェクトの一種。 > いくつかの言語ではラムダ式や無名関数で実現している。引数以外の変数を実行時の環境ではなく、 > 自身が定義された環境(静的スコープ)において解決することを特徴とする。
33 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 19:13:25.68 ID:nlmXbEn2.net] > (ラムダ式ではなく)関数で外の環境を掴めるのは当たり前の話であり、嘘は良くない とりあえずelispにケンカ売ってるのだけは分かった
34 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 19:19:20.49 ID:5LKfT6rZ.net] pythonのlambdaって外の環境見えないの?
35 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 19:22:02.17 ID:lx9et4kr.net] 見えるよ
36 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 19:25:16.21 ID:5LKfT6rZ.net] そうだよね...
37 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 19:39:55.45 ID:KOr7L+hP.net] >>31 C#、Java8、C++11、JavaScript、Ruby 等々の関数型プログラミングが可能な言語では、 どれも「ラムダ式の中であっても外の環境を参照し、それを局所環境に保存」できる それに対して、Python だと「ラムダ式の中では外の環境を参照する」ことしかできない つまり、手続き型言語の Python は関数型プログラミングには不向きである、と言える >>32 >> 引数以外の変数を実行時の環境ではなく、 >> 自身が定義された環境(静的スコープ)において解決することを特徴とする。 クロージャを備えた言語ではクロージャ自身が局所環境を持つということだね(>>4 も参照) だから、関数内でもラムダ式内であっても局所環境で変数を解決できる それに対して(クロージャを備えず、代わりに)関数という実行環境しか持たない Python では、 関数内では変数を解決できてもラムダ式内で変数を解決できない つまり、Python はクロージャを持たない手続き型言語
38 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 19:44:13.19 ID:5LKfT6rZ.net] pythonのlambdaって単に単純な関数定義のシンタックスシュガーなんじゃないの? lambdaなんて名前が付いてるからアレだけど。
39 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 19:44:17.88 ID:KOr7L+hP.net] >>34 もちろん見えるよ ただしクロージャが無いから、その(ラムダ式の中から)見えた値を局所環境に保存できない 関数の中ならば(関数が持つ)局所環境に保存できるんだけどね....
40 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 19:47:57.23 ID:nlmXbEn2.net] >>37 ・「変数を解決する」という用語が未定義 ・「ラムダ式のみクロージャと認める」というのは>>32 とは異なる定義だが、そのような定義をしている文献が引用されてない やり直し
41 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 19:48:24.99 ID:5LKfT6rZ.net] >>39 ラムダ式を評価した結果も関数定義を評価した結果も同じfunctionだよ。
42 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 20:00:59.51 ID:lx9et4kr.net] >>41 たしかに import inspect def func(x): return lambda n: x * n func(5)(4) #=> 20 (Clojure) inspect.isfunction(func) #=> True inspect.isfunction(func(1)) #=> True
43 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 20:10:51.52 ID:KOr7L+hP.net] >>40 >・「変数を解決する」という用語が未定義 失礼、言語処理系や言語意味論を知らない人には難しい表現だった 「変数を解決する」とは、変数に束縛された値を求めることを意味する 単純な実装では、変数と値の対(ペア)の集合である環境から、変数をキーに値を探索することで実現できる >・「ラムダ式のみクロージャと認める」というのは>>32 とは異なる定義だが、そのような定義をしている文献が引用されてない 「ラムダ式のみクロージャと認める」とは言っていないよ C#、Java8、C++11、JavaScript、Ruby 等々の一般的な言語では関数でもラムダ式でも局所環境を持てる これは「クロージャ自身が局所環境を持つ(>>4 )」というクロージャ定義からすれば、自然な結果である それに対して、ラムダ式では局所環境を持てない Python にはクロージャの概念が欠落しているんじゃないのか? と指摘しているだけ あるいは処理系への実装を失敗した?、あるいは言語設計上の欠陥を見落とした?という指摘と言い換えてもいい Python の言語設計者達はクロージャの概念を知っているつもりだったのかもしれないけどね......
44 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 20:14:38.63 ID:nlmXbEn2.net] >>43 お前こそ良く分かってなくて用語使ってるだろ そういうのは変数の再束縛っていうんだよ そんでお前は変数の再束縛と局所環境が持てない事を混同してる
45 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 20:19:48.73 ID:5LKfT6rZ.net] pythonでは関数=クロージャなんじゃないの? ラムダ式は関数定義の略記方だよ。
46 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 20:27:21.21 ID:5LKfT6rZ.net] 変数に束縛された値を求めることは評価するっていうんだと思う。 再束縛は別の値を束縛すること。
47 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 20:32:25.05 ID:lx9et4kr.net] Lispっぽくクロージャ書けるよ f = (lambda x: (lambda y=2*x: (lambda z=x*y: (lambda w: w * (y + z))))()()) g = f(2) g(3) #=> 36
48 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 20:34:00.52 ID:KOr7L+hP.net] >>44 言葉を「変数の再束縛」へ言い換えただけでは、結論は同じだよ C#、Java8、C++11、JavaScript、Ruby 等々の一般的な言語では関数やラムダ式はクロージャを元に 設計されているから、外の環境を参照した値を「局所変数に再束縛」できる それが当たり前で、自然な関数型プログラミングができる それに対して(クロージャを元にしていない)手続き型言語の Python では、 ラムダ式の中だと「局所変数に再束縛」できない 従って、手続き型言語の Python は関数型プログラミングには不向きである
49 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 20:34:54.87 ID:nlmXbEn2.net] >>46 評価はPythonのラムダの中でも出来るよな?
50 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 20:37:14.94 ID:nlmXbEn2.net] >>48 よし、あとはラムダの中で変数の再束縛ができないと その言語にクロージャが無い事になるという文献を引っ張ってこい
51 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 20:40:33.21 ID:lx9et4kr.net] >>48 Pythonのラムダ式では局所変数に再束縛できない、は間違い(>>47 ) 嘘は良くない
52 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 20:49:43.56 ID:lx9et4kr.net] >>45 そうだよ
53 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:05:06.25 ID:KOr7L+hP.net] >>48 クロージャを備えた言語であれば、ラムダ式を入れ子にした複雑なコードを書かなくても、 単純明瞭で可読性の高いコードが書ける 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 との違い
54 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:08:04.55 ID:lx9et4kr.net] ラムダ式の入れ子は分かりにくいから 関数型プログラミングに向いてない 関数型とは一体…
55 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:09:53.89 ID:5LKfT6rZ.net] そもそも関数型プログラミングって堂々と代入してるようじゃダメなのでは
56 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:12:20.49 ID:lx9et4kr.net] どれだけ間違いを指摘しても Pythonにクロージャが無いって意見を上書きできない これが参照透過性です
57 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:14:02.40 ID:KOr7L+hP.net] (>>53 の続き) もちろん関数型言語であれば、>>53 の 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
58 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:18:46.76 ID:KOr7L+hP.net] >>54 >ラムダ式の入れ子は分かりにくいから >関数型プログラミングに向いてない 添削しよう: ラムダ式の入れ子は分かりにくいから、 ラムダ式の入れ子や関数内関数を多用しなければならない手続き型言語の Python は 関数型プログラミングに向いてない それに対して、クロージャを備えた C#、Java8、C++11、JavaScript、Ruby 等々の普通の言語では、 クロージャ自身が持つ局所環境内の変数に代入(=束縛)できるから、 関数型プログラミングに向いている
59 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:25:01.25 ID:KOr7L+hP.net] >>51 Python ができるのは、引数に再束縛することだけ 局所変数(>>53 ,56 の y と z)には代入できない Python でも「ラムダ式では局所変数に再束縛できる」と主張したいのなら、 ラムダ式の入れ子や関数内関数を使わずに、可読性の悪い >>48 のコードを書き直しなさい もし Python に真のクロージャが存在するのなら、簡単な仕事のはずだ できるよね? できないのなら、嘘つきは君のほうだよ
60 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:31:21.14 ID:lx9et4kr.net] 変数に再束縛できないから、変数に代入できないに意見が変わったね やっと>>31 に追いついたね
61 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:36:16.07 ID:lx9et4kr.net] >>47 の変数は外から見えないという意味で 紛れもなく局所変数
62 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:41:46.54 ID:LUEi6lWE.net] Java 8にクロージャなんかあったっけ? ただのラムダだったような
63 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:44:14.34 ID:KOr7L+hP.net] >>60 ,60 ぐだぐだ屁理屈を言うより、さっさと >>48 のコードを書き直した方がいいんじゃね? それとも Python コミュニティでは >>48 みたいな ラムダ式を入れ子にしたカッコだらけ のコードが可読性のある美しいコードなのかなあ 自分には、>>53 ,56 のほうが可読性の高いコードだと思うけどね
64 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:45:18.38 ID:lx9et4kr.net] 普通は関数定義するよ 当たり前じゃん
65 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:49:19.33 ID:lx9et4kr.net] ところで関数はクロージャじゃないって どこの文化なの? 聞いたことない
66 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:50:58.85 ID:KOr7L+hP.net] >>62 >>4 で書いたように、クロージャは抽象的な概念だよ 言語の意味論を定義したり言語処理系を設計する時に用いられる抽象構文で現れる この抽象構文上のクロージャは、具象構文では一般にラムダ式とか無名関数(匿名関数)と呼ばれる たとえば Java 8 のラムダ式がそうだし、JavaScript の具象構文では function() { .... } と書き、 Standard ML では fn <id> => <expr> という具象構文で表現される
67 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:55:24.38 ID:lx9et4kr.net] 言語的にはJavaのラムダは ただのメソッド一つのクラスだよ
68 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 21:58:19.30 ID:KOr7L+hP.net] >>65 自分も聞いたことないね そんなこと言ってるお馬鹿さんはいるのかな? まあ正確に言うと、クロージャを識別子に束縛したものが関数だから、 束縛されていない無名関数(=ラムダ式)と区別することが必要な文脈もあるけどね(>>4 )
69 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:04:34.10 ID:lx9et4kr.net] >>68 じゃあPythonにクロージャはあるの? Yes/Noで答えて
70 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:05:03.57 ID:TZMLlS/6.net] Java 8のクロージャは「effectively finalに限りキャプチャ可能」 というなんちゃってな局所環境だけどな effectively finalの導入でかろうじて使い物になるかも知れないレベル
71 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:10:31.90 ID:KOr7L+hP.net] >>64 普通は局所変数に代入するだろ、>>53 みたいに y = 2 * x z = x * y それとも、Python ではこんな単純な代入文も書かずに(書けずに?)、 わざわざ関数定義するのが当たり前なのかなあ?
72 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:13:13.99 ID:n2NDOrh4.net] >>39 …Haskellにはクロージャが無いと?
73 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:21:17.10 ID:KOr7L+hP.net] >>69 Yes/No であれば No だ 繰り返しになるけど、 真のクロージャを備えた C#、Java8、C++11、JavaScript、Ruby 等々におけるクロージャの定義と、 手続き型言語の Python におけるクロージャの定義は異なっている Python では識別子に束縛したクロージャ、いわゆる関数しか存在できず、 局所環境を伴うラムダ式を表現できない このため、>>48 のような ラムダ式が入れ子になったカッコだらけ の汚いコードしか書けない 結果として、Python は関数型プログラミングには不向きである
74 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:21:52.15 ID:lx9et4kr.net] >>71 だから普通はこう書くよ あれ?一番簡潔になった? def f(x): y = 2 * x z = x * y return lambda w: w * (y + z) g = f(2) g(3)
75 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:25:17.72 ID:lx9et4kr.net] >>68 そっちが言う馬鹿(>>73 )がいたよ まさかの同一ID⁉︎
76 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:28:55.78 ID:GwhuA7Og.net] >クロージャを識別子に束縛したものが関数だから C#やECMAScriptの匿名関数は関数ではないと。 珍妙な新説ですなふむふむ
77 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:31:31.78 ID:KOr7L+hP.net] >>72 >>39 における「値を局所環境に保存」とは、識別子と値の対(ペア)を局所環境に追加すること(>>43 も参照) ここで、追加の時に既に同じ名前の識別子が存在していた場合、手続き型言語では値を破壊的に更新するけど、 関数型言語では新たに局所環境が生成される(=破壊的に更新しない)点が異なる ただし、この追加時の振る舞いの差異は、クロージャが存在する/しないとは無関係、ごっちゃにするのは間違い
78 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:45:45.31 ID:KOr7L+hP.net] >>74 たとえば JavaScript なら、ラムダ式だけ(>>53 )と関数定義との併用、 それらのどちらでも簡潔なコードが書けるよ 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 だとラムダ式だけでは「入れ子になったカッコだらけ」の汚いコード(>>48 )しか書けないから、 常に関数定義で「書かなければならない」という違いがある
79 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:46:49.16 ID:nlmXbEn2.net] >>77 お前のオレオレ定義なんて興味ねーんだよ まずはその珍説が書いてある文献を引用しろ
80 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:49:23.73 ID:5LKfT6rZ.net] >>78 >>45
81 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:51:44.34 ID:lx9et4kr.net] >>78 関数定義で可読性も簡潔さも失わないから、関数で書ければ良いよ で、なぜ関数定義でクロージャが作れる Pythonにクロージャがない事になるの? >>69 にNoと答えて、>>65 も否定したよね?
82 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:54:09.40 ID:nlmXbEn2.net] >>80 そいつ、関数を定義する特定のシンタックスシュガーに制限があることと その言語自体が持つ機能との区別が付かない馬鹿だから
83 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:56:01.93 ID:5LKfT6rZ.net] でもまあ、pythonの文法が変態なのは間違いない。
84 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:56:21.23 ID:KOr7L+hP.net] >>74 ナゼ 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 等々のふつうの言語では、 >>53 みたいなラムダ式だけを使ったコードが何の苦もなく自然に書けるんだから
85 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 22:59:47.88 ID:QKkGL4h0.net] 83はキチガイなの? >>74 は明らかに実行時のy,zを取り込んだ関数オブジェクトを生成してるからクロージャだろ defと書くかlambdaと書くか文法の些細な決まり事などどうでもいい
86 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:01:05.93 ID:lx9et4kr.net] >>84 同程度に簡潔に書けるなら、書き方は一つの方が良い というのがPythonの理想だから
87 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:08:28.24 ID:KOr7L+hP.net] >>81 >で、なぜ関数定義でクロージャが作れる >Pythonにクロージャがない事になるの? >>73 で書いたように、真のクロージャを備えた C#、Java8、C++11、JavaScript、Ruby 等々の ふつうの言語では(関数定義だけではなく)ラムダ式でもクロージャが作られるという違いがあるからだ 対して、Python のラムダ式ではクロージャが作られない(だから、局所変数へ値を代入できない) もし「Pythonにクロージャがない」という主張が不適切であるのならば、 >>43 の最後で書いたように、 「Python の言語設計者達は、処理系への実装を失敗した、あるいは言語設計上の欠陥を見落とした」 と言い換えてもいいよ こんな使い物にならないラムダ式で満足しなければならないとは、最大の被害者は Python プログラマだよね だって、他のふつうの言語であれば「ふつうに書ける」ことが、Python じゃ「書けない」のだから....(>>84 )
88 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:13:26.40 ID:5LKfT6rZ.net] ラムダ式の構文が残念だと言いたいなら、最初からそう言えばいいじゃん。
89 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:16:00.89 ID:KOr7L+hP.net] >>85 ラムダ式が引数に値を束縛できるのは、関数型言語を知っていれば常識だよ そんなことも知らないの? で、引数以外の局所変数に値を束縛するには、純粋なラムダ式に加えてクロージャが必要になるって話だよ
90 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:18:21.66 ID:G8K4RNhm.net] >ラムダ式が引数に値を束縛できるのは それ束縛じゃねーだろ キミはアホなのか?
91 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:18:59.88 ID:nlmXbEn2.net] >>89 >>74 のy, zのどこが引数なんだよ 既知外は黙ってろよ
92 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:23:03.86 ID:lx9et4kr.net] >>47 の話ならデフォルト引数で値を入れてるから 普通に関数適用で引数に値を入れてるのとは厳密には違うよ? どうでも良いけどね
93 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:26:01.65 ID:lx9et4kr.net] >>87 Pythonにクロージャが無いは嘘ってことね 嘘は良くない
94 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:27:54.79 ID:KOr7L+hP.net] >>91 >>89 で書いたのは >>42 のラムダ式だけで書かれた Python コードだ 失礼した >>74 は関数定義でクロージャが作られているね ただし、Python だけがラムダ式ではクロージャが作られず、 Python におけるクロージャの定義が他の「普通の言語」と異なっている事実に変わりはない
95 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:30:45.91 ID:nlmXbEn2.net] >>94 お前は無名関数って何がいいの?スレを立てて、そこで思う存分Pythonのlambdaを罵倒するべき クロージャ云々は言いたい事と噛み合ってない
96 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:33:02.09 ID:KOr7L+hP.net] >>93 Python には真のクロージャが存在しない、という指摘は事実だよ(嘘ではない) もし「Python にも真のクロージャが存在する」と主張したいのなら、 >>84 のコードが構文エラーとならないように添削しなさい もし「Python にも真のクロージャが存在する」のなら、たやすい作業のはずだ 真のクロージャを備えた普通の言語では、何の苦も無く >>53 みたいなコードが書けるんだからね 君が嘘つきでなければ、書けるはず
97 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:33:22.37 ID:5KptUVSU.net] 使い勝手で一番使い物にならないのはJavaだろ? void m() { int y = f(); y = y + 1; new Thread( () -> {ここでyを使えないKUSO言語} ); }
98 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:33:25.09 ID:5LKfT6rZ.net] ID:KOr7L+hP が言ってるのは、 関数の引数にもう少し複雑な処理をインラインで書きたいのに、 defは値返さねえし、lambdaは1行しか書けねえし、 まったく融通がきかねえな! みたいな字面上の不満であって、関数型プログラミングだのクロージャだの全然関係ない。
99 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:36:58.94 ID:lx9et4kr.net] >>96 関数は局所環境持ってても「真のクロージャ」じゃないってこと? Yes/Noで答えて
100 名前:デフォルトの名無しさん mailto:sage [2014/11/09(日) 23:39:26.26 ID:nlmXbEn2.net] 真のクロージャとかいうオレオレ用語 もちろん引用もなければ定義もない