クロージャって何がいいの?at TECH
クロージャって何がいいの? - 暇つぶし2ch261:デフォルトの名無しさん
14/12/15 22:40:54.50 G9R+2lJx.net
俺が平安時代に読んだ本だと、iteratorはアイテレータって書かれてたな。
あとhierarchyはハイアラーキだった。

262:デフォルトの名無しさん
14/12/15 22:46:59.52 G9R+2lJx.net
そんなにlispに憧れてるなら、lispを使えばいいのに。

263:デフォルトの名無しさん
14/12/15 22:47:19.92 BuhXHDiL.net
> 1.8 の時代に lambda の挙動が変更されメソッドとして独立しました
> その変更の理由は関数型プログラミングと関連する可能性はありますが、詳しい背景を自分は知りません

RubyのProc.newで作られるオブジェクトは
returnの挙動が普通の関数と違ってキモすぎるので
lambdaの方だけでも普通に直したんでしょう

264:デフォルトの名無しさん
14/12/15 23:02:52.91 BuhXHDiL.net
さらに言えば、Rubyのブロック変数のスコープの扱いが1.9で仕様変更されてるけど、
それについてmatz自身が

> それは、Rubyが最初から関数型言語としてスタートしてないからであって、言語が違うからですよね。

と語っているね


URLリンク(www.atmarkit.co.jp)

265:デフォルトの名無しさん
14/12/15 23:10:49.42 eMlPsgxM.net
>>258
>Obj-C が inline Smalltalk が書ける C なのに、Swift が Ruby をまねたみたいなデマはやめてくれる?

スマン、ここは説明が足りなかった、Tailing Closure のことを言いたかった
Objective-C を含むほとんどの言語では、引数をカッコで囲んで関数(or メソッド)へ渡す文法になる
基本的には Swift も同じですが、引数リストの最後がクロージャである場合に限り、
そのクロージャ引数を閉じカッコの直後に置く事ができます
・collection.map({ ..... })  // 一般的(常識的?)な書き方
・collection.map() { ..... }  // クロージャを引数リストの直後へ移動できる
・collection.map { ..... }  // さらには丸カッコ () も省略できる
これを Ruby で書くと、以下のようになります
・collection.map(lambda { ..... })  # Ruby だと一般的ではない
・collection.map() { ..... }  # ブロックを引数リストの直後へ移動できる(ブロック付きメソッド呼び出し)
・collection.map { ..... }  # さらには丸カッコ () も省略できる(これが普通の Ruby らしい書き方)
これと同じ書き方ができる言語を Swift と Ruby の他に自分は知りません
そして発表時期的に Ruby の後に Swift が生まれたから、ここは Ruby の影響ではないかと「推測」しました
Tailing Closure の由来に関するソースは持っていないので、デマと言われてもしかたがありませんね....


>それと、 Ruby で関数型スタイルのプログラムを書けるということを、Ruby で書いたら関数型プログラムになるかのように書くのもやめてくれる?

Ruby は手続き型言語なのだから、プログラマが意識しなければ関数型プログラミングのスタイルにならないのは当たり前
いいかげん説明は面倒なので、以下の文書をよく読んでください:
・Rubyによる関数型プログラミング
 www.h6.dion.ne.jp/~machan/misc/FPwithRuby.html
もし具体的な疑問/質問があれば、個別に返答します

266:デフォルトの名無しさん
14/12/15 23:24:28.86 eMlPsgxM.net
>>263
おそらくその通りだと思います


>>264
もしも Matz が Lisper ではなく Schemer であったなら、
違った結果になっていたかもしれませんね

267:デフォルトの名無しさん
14/12/16 00:31:08.98 IiuX/rSM.net
自己レスになりますが、>>245 では:
> (Python だけでなく、この「お題(>>191)」は Ruby であっても再帰を使えば同じく分かりにくいコードになる)
とカキコしました
で、後から考え直して「手続き型のループ&破壊的代入」ではなく、しかも「関数再帰」も使わずに、
参照透明性がある関数型プログラミングのコードを考えてみました
 URLリンク(ideone.com)
ポイントは「反復に組み込みメソッド loop」を「ブロック脱出に引数付のbreak文」を使った2点です
なおメソッド loop は一般に loop do .... end という手続き型のスタイルで書かれることが多いために
ループ構文の一種と誤解されがちですが、(lambda を構文糖であると >>257 が 勘違いしたように....)
loop はメソッドですので(コードで示したように) inject へチェーンさせることができます

また「参照透明性はあっても、手続き型の制御構造であるbreak文の利用は反則ではないか?」という
指摘を予測して、
同じスタイルで(break文の代わりに)組み込みメソッド catch と throw を使ったコードも書きました
 URLリンク(ideone.com)
ただし、この catch/throw は大域脱出のために用意されたメソッドですから、
今回の「お題」のように単一ブロックを脱出するだけならbreak文を使うのが素直だと考えます

ついでに(catch/throw の代わりに)Scheme 由来の継続(continuation)を使ったコードも書きました
 URLリンク(ideone.com)

268:デフォルトの名無しさん
14/12/16 02:54:32.21 178msYck.net
こんな無駄に遠回しなコード沢山書いてどんだけオナニー好きなんだよ。

269:デフォルトの名無しさん
14/12/16 02:58:06.18 178msYck.net
>>200の爪の垢でも煎じて飲めよ。

270:デフォルトの名無しさん
14/12/16 07:18:26.71 /LiRSDzk.net
>>260
もちろん、本当はただのメソッドであってlambdaは文法要素ではない
あたかも「ブロックはlambdaの構文糖」であるかのような主張をするから、その対比としてそう書いたまでだよ
分かりにくかったね、「構文糖のような存在のメソッド」と修正しておくよ

271:デフォルトの名無しさん
14/12/16 07:24:54.85 /LiRSDzk.net
まあ、「構文糖のような存在のメソッド」って用語がおかしいというなら
「真のクロージャ」って用語もおかしいのだと気付いて欲しいな

272:1
14/12/16 07:48:21.23 PApLEh59.net
なんか知らんけど伸びてて嬉しいです
目標はGCスレ超えです

273:デフォルトの名無しさん
14/12/16 08:02:21.01 /LiRSDzk.net
一応lambdaというメソッドの実装された時期について調べてみたら、結構昔から存在自体はしてたのね
元々procと同じなのに字数多い&Procなのにlambdaって覚えにくいのと1.4当時は関数型とか知らんかったからスルーしてたのかな
そこは俺の記憶違いだったわ

274:デフォルトの名無しさん
14/12/16 08:45:33.81 7mh816Ug.net
クロージャがなければ参照カウント型のGCで済むんじゃないか説があるし
ワンチャンあるよ

275:デフォルトの名無しさん
14/12/16 08:47:53.04 7mh816Ug.net
構文糖衣とかいいながら
ラムダって名前から甘そうな印象をうけない
名前が悪いよ考え直すべき

276:デフォルトの名無しさん
14/12/16 08:56:24.06 7mh816Ug.net
クロージャって名前も固いし
意味わかんねえから
貝殻のclamを頑張ってもじって
クリームって名前にするくらいの
努力はあってよかった

277:デフォルトの名無しさん
14/12/16 09:58:24.78 /LiRSDzk.net
>>275
そういう意味ではfunctionを名前ありの関数にもラムダにも使ったJavaScriptは上手いと思う
らむだ何ソレ?な人にも「関数名書かないで使うと無名の関数も作れるよ」って説明で事足りるもんね

278:デフォルトの名無しさん
14/12/16 10:58:59.39 gf3D6lb/.net
ブロックとProc.newとprocとlambdaと->があるRubyはやり過ぎ

279:デフォルトの名無しさん
14/12/16 11:12:47.94 /LiRSDzk.net
>>278
まあ、Rubyは他の組み込みライブラリでも
エイリアスや似たようなメソッド、所属モジュールが違う同様のメソッドとか持つのは普通だからね
俺は昔からproc派、RubyのProcとλ算法は別物だと思うからあの挙動でいいし、早く書けるし

280:デフォルトの名無しさん
14/12/16 22:27:19.26 IiuX/rSM.net
>>270
>あたかも「ブロックはlambdaの構文糖」であるかのような主張をするから、

いや「あるかのよう」ではない、>>247 で以下のように、断定的に明記したとおり:
 > まず >>240 で書いたように、Ruby の「ブロック付きメソッド呼び出し」は構文糖だ
Ruby インタブリタの内部では「ブロック付きメソッド呼び出し」と
「値渡しされた Proc オブジェクト」とは別の表現(C構造体)が用いられ、それらを相互変換している
ただし Ruby プログラマの視点では、値渡しされたProc オブジェクトで「あるかのように」
(すなわちファーストクラスとして)ブロックを扱う事ができる、だから「ブロックは構文糖」になる

ブロックを評価するのにメソッド Proc#call が必須(>>257)なのは、また別の理由....
それらをごっちゃにすべきではない


>>271
>まあ、「構文糖のような存在のメソッド」って用語がおかしいというなら

いや「構文糖のような」という比喩表現であれば、何の問題も無い

>「真のクロージャ」って用語もおかしいのだと気付いて欲しいな

>>4 でクロージャ定義を示してから >>201 までソースを明かすのを遅らせたのは意図的だったけど、
「真のクロージャ」という曖昧な表現でいらぬ混乱を与えたことは余計だったと反省している
最初からストレートに「関数型言語のクロージャ」とすべきだったね

281:デフォルトの名無しさん
14/12/16 23:35:24.13 178msYck.net
関数型言語のクロージャと非関数型言語のクロージャはナニが違うですか。

282:デフォルトの名無しさん
14/12/17 00:34:28.88 NwnPjzlT.net
結局、Pythonのクロージャは本物で、Rubyのブロックは偽物って結論になったんか?

283:デフォルトの名無しさん
14/12/17 06:09:12.08 4QPsGplH.net
>>282
彼の中だけではそういうことらしい

284:デフォルトの名無しさん
14/12/17 06:10:48.27 HxoNcsla.net
環境もちこしてる関数っぽいやつならクロージャでいいじゃん

285:デフォルトの名無しさん
14/12/17 06:13:43.20 4QPsGplH.net
って彼の中だけでは逆か

>>284
と言うか元々環境持ち越すのがクロージャの要件でしょ

286:デフォルトの名無しさん
14/12/17 06:16:00.02 HxoNcsla.net
なんで突っ込まれてるのかさっぱりわからん

287:デフォルトの名無しさん
14/12/17 06:21:06.36 4QPsGplH.net
>>286
突っ込んでないよ、超同意してんだよ

288:デフォルトの名無しさん
14/12/17 07:54:17.64 HxoNcsla.net
まじかよ世界は平和だった

289:デフォルトの名無しさん
14/12/17 20:35:47.86 JUumI3zm.net
>>281
もともとクロージャの概念/用語は関数型言語で生まれたものだから、
「非関数型言語のクロージャ」とは:
  「関数型言語のクロージャ」の定義に対して、どれくらい忠実に実装されているか?
という相対的な評価になるね

290:デフォルトの名無しさん
14/12/17 21:10:46.15 cFsqVLS5.net
そして、オリジナルのクロージャーが
一番優れているとかいう信者が現れるわけかw

普通はオリジナルを改良した方が
優れているんだがな。

291:デフォルトの名無しさん
14/12/17 21:39:32.52 JUumI3zm.net
>>282
でれでは、ここまでの結論をまとめてみる
まず最初は。>>289 の評価結果から:
[Python:X]
  Python の lambda 構文は式しか書けないという制限があるから、
  クロージャ固有の局所環境を持つことができない
  したがって、Python の lambda 構文は「関数型言語のクロージャ」ではない
[Ruby:X]
  Ruby のブロックはオブジェクトであるから、
  その評価にはメソッド Proc#call をコールしなければならない
  したがって、Ruby のブロックは「関数型言語のクロージャ」ではない
[JavaScript:O]
  JavaScript の関数リテラルは任意の書けるからクロージャ固有の局所環境を持てるし、
  なおかつ引数に適用するだけで評価できる
  したがって、JavaScript の関数リテラルは「関数型言語のクロージャ」である
  結果として、最も忠実に「関数型言語のクロージャ」が実装されている(>>277)、と言える

続けて、この評価結果が現実のプログラミングに与える影響をまとめる
ここでは Apple 公式リファレンスに含まれる Swift クロージャのサンプルコードを「お題」とした(>>191)
・高階関数 map に与えるクロージャをインラインで書ける
  [Python:X]
  ・インラインでは関数再帰を使った可読性の低いコードになってしまう(>>208)
  ・このため、一般には(インラインで書くのはあきらめて)関数定義を使わざるをえない
  [Ruby & JavaScript:O]
  ・インラインで自然な while ループを使った(ふつうのプログラマにとって)分かりやすいコードが書ける
・参照透明性のある関数型プログラミングで書ける
  [Python:X] 関数再帰で書けるが、可読性の低いコードになってしまう(>>208)
  [Ruby:O] (関数再帰の代わりに)組み込みの高階関数風メソッドを使うことで、可読性の高いコードが書ける(>>267)
  [JavaScript:?] (書けるか否か、現時点では不明)

292:デフォルトの名無しさん
14/12/17 21:47:14.69 JUumI3zm.net
>>282 を一部訂正

X:JavaScript の関数リテラルは任意の書けるから
O:JavaScript の関数リテラルは任意の文が書けるから

293:デフォルトの名無しさん
14/12/17 22:23:00.08 NwnPjzlT.net
>>291
再帰関数よりwhileループが読みやすいレベルの人間が
関数型プログラミングについて語るなんて滑稽すぎる

294:デフォルトの名無しさん
14/12/17 22:32:56.00 NwnPjzlT.net
>>291
あと、>>208じゃなくて>>203を評価すべきだと思うんだけど、
なんでワザワザ可読性を落としてる方を評価してるの?

まさか、Rubyでinjectは使って良いけど、Pythonでapplyfは使っちゃダメとでも言うつもり?

295:デフォルトの名無しさん
14/12/17 22:42:41.33 KZ4YaCx1.net
可読性の良し悪しなんて定量的ではないものを評価対象にするとか

296:デフォルトの名無しさん
14/12/17 22:47:17.42 ffqYUKYZ.net
> Python の lambda 構文は式しか書けないという制限があるから、
> クロージャ固有の局所環境を持つことができない


def make_f(n): return lambda x: x + n
f = make_f(1)
n = 1000
f(1) #=> 2

こういう風に、(引数以外の変数を)実行時の環境じゃなくて
自身が定義された環境で解決できればクロージャだよ。
この場合は変数nのことね。

297:デフォルトの名無しさん
14/12/17 23:03:51.76 dyHF3Jr0.net
>>289
レキシカルクロージャってSchemeが最初だと思うけど、
Schemeって純粋な関数型言語じゃないよね。

298:デフォルトの名無しさん
14/12/17 23:50:33.95 JUumI3zm.net
>>294
お題に対して「Python だけがわざわざ関数 applyf をユーザ定義しなければならない」ことを問題視している
>>203 のコードは「お題を(勝手に改変せず)インラインで書ける」という観点だと(評価以前に)失格だ

もしも Python コミュニティにおいて関数 applyf が常識的に認知されていたならば、
(map/filter/reduce 等と同様に) applyf は組み込み関数として実装されていたはず
なお、組込み関数の実装レベルは言語によって差異があるものだから、
公平性を考慮して functools のような標準ライブラリを import するのは認める

また Ruby のメソッド Enumerable#inject に対応する Python の関数は reduce だよ
Python で組込み関数 reduce を使うのは、まったく問題無い

299:デフォルトの名無しさん
14/12/17 23:55:13.45 dyHF3Jr0.net
ていうか、さらっと1個の式で書けないような処理はインラインに書こうとするなよ
っていうのがpythonの求めるところなんじゃないの?

300:デフォルトの名無しさん
14/12/18 00:12:23.41 SaitqfQN.net
>>203 はインラインでは書けていないけど、>>208 と比べれば可読性の高いコードであると思うから、
>>294 の主張を受け入れて >>291 を以下のように一部改訂する(* で始まる行を変更している)

改定前:
 ・高階関数 map に与えるクロージャをインラインで書ける
   [Python:X]
   ・インラインでは関数再帰を使った可読性の低いコードになってしまう(>>208)
*  ・このため、一般には(インラインで書くのはあきらめて)関数定義を使わざるをえない
 ・参照透明性のある関数型プログラミングで書ける
*  [Python:X] 関数再帰で書けるが、可読性の低いコードになってしまう(>>208)

改訂後:
 ・高階関数 map に与えるクロージャをインラインで書ける
   [Python:X]
   ・インラインでは関数再帰を使った可読性の低いコードになってしまう(>>208)
*  ・このため、一般には(インラインで書くのはあきらめて)関数定義または変数宣言(>>203)を使わざるをえない
 ・参照透明性のある関数型プログラミングで書ける
*  [Python:X] 関数再帰で書けるが、可読性の低いコードになってしまう(>>203,205)

301:デフォルトの名無しさん
14/12/18 00:16:28.27 5LPNbvYA.net
むしろ標準で用意されてなくてもユーザ定義で拡張できるのは
言語として筋が良いといえる

302:デフォルトの名無しさん
14/12/18 00:18:19.46 wQzGbOYd.net
謎の標準ライブラリ縛りが入りましたw

303:デフォルトの名無しさん
14/12/18 00:22:42.78 Xu+bpXu3.net
1個の式で済む以上の事をやろうとする処理に名前を付ける事が、なぜ可読性の低下につながるの?

304:デフォルトの名無しさん
14/12/18 00:29:24.93 wQzGbOYd.net
再帰は可読性低いって連呼しててワロタ
Rubyユーザって、ブロック使ってるだけで関数型だと思ってるの?

305:デフォルトの名無しさん
14/12/18 00:35:38.77 Xu+bpXu3.net
Schemeは普通ならループで済むような事まで再帰で書くぜ

306:デフォルトの名無しさん
14/12/18 00:44:04.09 4kRgXtNb.net
再帰よりnamed let使おう

307:デフォルトの名無しさん
14/12/18 00:52:42.96 Xu+bpXu3.net
named let は再帰でしょ?

308:デフォルトの名無しさん
14/12/18 01:28:37.32 4kRgXtNb.net
書いた後に思った

309:デフォルトの名無しさん
14/12/18 08:20:12.81 ETi/Ct7F.net
>>304
彼だけだよ

310:デフォルトの名無しさん
14/12/18 08:27:40.63 9iQd+rLQ.net
lispおじさんに言わせれば
全部lispのパクりだから
全部クロージャで問題ないよ

311:デフォルトの名無しさん
14/12/18 09:21:04.09 f+DPSsFx.net
なんでクロージャスレでClojureを話題にしないの?

312:デフォルトの名無しさん
14/12/18 09:50:43.10 ZOTu6c+H.net
>>311
若いときは買ってでもするものなあ~んだ?

313:デフォルトの名無しさん
14/12/18 12:49:08.51 nVA5J83n.net
>>312
ゲーム

314:デフォルトの名無しさん
14/12/18 19:33:48.97 Xo1YvlzDq
ClosureCL…(ボソッ

315:デフォルトの名無しさん
14/12/18 19:41:50.11 5ReW54RD.net
>>191
流れをナナメ読みかつ関数型言語素人なんだけど、
関数型言語だとそのアップルサイトの例はどういうふうに書くもんなの?

let digitNames = [0,"Zero"; 1,"One"; 2,"Two"; 3,"Three"; 4,"Four"; 5,"Five"; 6,"Six"; 7,"Seven"; 8,"Eight"; 9,"Nine"];;
let numbers = [16; 58; 510; 0];;
let strings = List.map (fun n ->
let rec f n acc =
match (n, n / 10) with
(0, 0) -> List.assoc 0 digitNames
| (_, 0) -> List.assoc (n mod 10) digitNames ^ acc
| (_, _) -> f (n / 10) (List.assoc (n mod 10) digitNames ^ acc)
in f n "") numbers;;
List.iter (fun s -> print_endline s) strings;;

言語はOCaml。三つの変数名はオリジナル版を採用。
dictionaryは諸事情でめんどいのでタプルのリストで代用。
関数型言語のことはまったくわからないw

316:デフォルトの名無しさん
14/12/18 22:22:25.63 2b1ZQukZ.net
>>312
SEX

317:デフォルトの名無しさん
14/12/18 23:09:02.06 SaitqfQN.net
>>315
Standard ML で素直に末尾再帰を使って書いてみた
 URLリンク(ideone.com)

318:デフォルトの名無しさん
14/12/19 00:07:27.38 lMWP4GlC.net
>>317
おおっ!わざわざどうも!
SMLとOCamlの関係だからこういう似たような感じになるのかな?
それともループを再帰に置き換えたらどうせどの言語でもこんな感じかな?

それにしても関数型言語なるものを知るにつれて思うのは、
再帰についてはすがすがしいが、
それ以外についてはタイプ量が増えがちってこと。
ハッシュテーブルひとつ準備するのにもウダウダ。
関数型どうのというより、個別の言語によるのかもしれないけど…。

319:デフォルトの名無しさん
14/12/20 00:24:39.20 0cpPf2uS.net
>>318
>SMLとOCamlの関係だからこういう似たような感じになるのかな?

SML も OCaml も同じML族の一員ですから、そんな感じになるのも不思議じゃないと思いますね

>それともループを再帰に置き換えたらどうせどの言語でもこんな感じかな?

SML 以外の関数型言語は触った程度のレベルなので、以下はあくまで私見です:
・Lisp でも似た感じの再帰になる
 ただし Lisp は TCO が保証されていないから、一般的な反復処理であれば
 loop や while マクロ(または、その相当品)で手続き的なループで書く
・Scheme は TCO が言語仕様で保証されているので、普通は再帰で書く(>>305)
 また継続(call/cc)があるので、loop や while の相当品を関数として自前で定義することも可能
・Haskell の場合、初めのうちは(ML や Scheme と同様に)再帰で書く
 ただし Haskell だと文字列は文字型のリストであり、標準ライブラリの unfoldl を使う事を学ぶようになる
 ・関数プログラミングの楽しみ
  URLリンク(www.amazon.co.jp)
  第3章「おりがみプログラミング」で詳しく解説されています
ということで Haskell の定義を参考にして、SML でも関数 unfoldl で再帰を抽象化したコードを書きました:
 URLリンク(ideone.com)
ここで unfold とは、よく知られている fold の双対な概念です
(fold は、Ruby だと inject、Lisp や JavaScript では reduce と呼ばれています)
fold xs が「あるリスト xs を畳んだ値 y」を返すのに対し、
unfold y は「ある値 y を広げたリスト xs」を返します
なお、「畳む/広げる」という言葉よりも「分解する(destruct)/組立てる(construct)」のほうが直感的かもしれません

(* 長いので、続く *)

320:デフォルトの名無しさん
14/12/20 00:32:09.09 0cpPf2uS.net
(* >>319 の続き *)

なお、map や filter といった高階関数を一般化したものが fold であることは
よく知られていますが、ここでリストを代数(群)に見立てた圏論の視点で再構成すると:
・fold を(更に)一般化したものがカタモルフィズム(catamorphism)である
・unfold を(更に)一般化したものがアナモルフィズム(anamorphism)である
という、本質的な形でリスト処理を定義できるようになります
(モナドとは関連しない)圏論を応用したプログラミングについては、以下のプレゼンがお薦めです
・Introduction to Categorical Programming (Revised)
 URLリンク(www.slideshare.net)
 p.18 の図式を使った「圏論でのリスト型の定義」が直感的です
詳細については、以下の記事で紹介されている論文(英語)が分かりやすかったです
・Haskellと圏論を学んできて、そのまとめとしてちょうどよい論文を見つけたのでメモ。
 URLリンク(plus.google.com)

>それにしても関数型言語なるものを知るにつれて思うのは、....

ML や Haskell は静的型付けによる安全性と高速化を主眼に設計された言語ですから、
Ruby や Python といったスクリプト言語の置き換えには成り得ないと考えます
これに関しては、以前に別スレ「LLにおける関数型プログラミング」で説明しています
 スレリンク(tech板:28番)
また ML や Haskell の強力な型推論は、データ型に関する矛盾(=バグ)が存在しないことを(実行の前に)証明しますが、
動かしては書き直す(いわゆるトライ&エラー)が一般的なスクリプトプログラミングには不向きだと考えます

(* これで終わり *)

321:デフォルトの名無しさん
14/12/20 07:17:42.63 tzPxF8Oh.net
長い
3行でまとめろ

322:デフォルトの名無しさん
14/12/20 12:12:13.43 PEBuGla8.net
珍しく普通に相手にしてもらって
うれしくてたまらない
オレオレクロージャくんであった

323:デフォルトの名無しさん
14/12/20 16:08:48.96 5dXZUu33.net
>>319-320
> Lisp は TCO が保証されていないから

TCOが保証されての末尾再帰。何がすがすがしいって、これですよね。
これがあるから書いていける。
保証なしで気軽に再帰なんかしてもスタックオーバーフローでげんなりだし。

> Haskell だと文字列は文字型のリストであり、標準ライブラリの unfoldl を

おったまげですね。初めてunfoldなるもんを知りました。
Rubyでinject、OCamlでfold_left/fold_rightは馴染みがあったんですが。
何かHaskellって…グイグイ来てますよね!(小学生並みの感想)。

> cata, ana, 圏論, 圏論でのリスト型の定義

リンク先拝見しましたが現時点でどうも1ミリも理解できていません。半笑いです。

> URLリンク(ideone.com)

ありがとうございます。よく考えると37行目の「 ^ output」が不要にも見えますね。

324:デフォルトの名無しさん
14/12/20 16:23:01.32 a9XjC0LN.net
源クロウジャ義経

325:デフォルトの名無しさん
14/12/20 19:01:20.98 tzPxF8Oh.net
>>322
分かりやすいですー

326:デフォルトの名無しさん
14/12/21 00:04:04.16 YWufr8fT.net
>>323
>よく考えると37行目の「 ^ output」が不要にも見えますね。

バグ指摘ありがとうございます、変数 output そのものが不要でした
対策を以下へ反映し、ついでに Ruby と Python でも unfold を使って書いてみました
・Standard ML
 URLリンク(ideone.com)
・Ruby
 URLリンク(ideone.com)
・Python
 URLリンク(ideone.com)


>おったまげですね。初めてunfoldなるもんを知りました。

「unfold は fold の双対な概念」であることを知れば、応用範囲は広がります
今回は文字列の unfold でしたが、リスト/配列/辞書/集合/スタック/キューといった
「コレクション・オブジェクトにおける fold/unfold」を考えることから始めませう

327:デフォルトの名無しさん
14/12/21 09:15:25.48 KrmABo99.net
TCO無くて正格評価なPythonでは
unfoldはループ&ジェネレータで実装した方が良いね
それと文字列に限定する意味って無いよね

URLリンク(ideone.com)

328:デフォルトの名無しさん
14/12/21 16:48:41.14 MvQSKDIW.net
この話題クロージャとか特に関係なく、Pythonの無名関数には文を書けず式しか書けないという単純な事実の指摘でOK?
関数型プログラミングのラムダとしては困らないが、手続き型言語における無名関数としては不便だろうな
自分はPythonを使わないので、Pythonでの「普通の」プログラミングスタイルがどっちなのかは知らん

329:デフォルトの名無しさん
14/12/21 17:05:17.75 MvQSKDIW.net
Hackで適当に書いてみたら本体は一行だった。PHPの緩さにラムダ加わるの最強

$strings = array_map($n ==> array_reduce(str_split($n), ($s, $d) ==> $s . $digitNames[$d]), $numbers);

330:デフォルトの名無しさん
14/12/21 17:15:45.30 KrmABo99.net
そんなので良ければPythonでも一行

strings = [''.join(digitNames[x] for x in str(n)) for n in numbers]

331:デフォルトの名無しさん
14/12/21 17:21:26.20 MvQSKDIW.net
あれ、それdigitNames[x]のxに文字列で渡ると思うけど、Pythonも勝手に数値に変換してくれるんだっけ?
整数に変換してやらないと駄目な記憶があっていちいち面倒くさいと思ってた

332:デフォルトの名無しさん
14/12/21 18:11:16.63 axFrURca.net
digitnames = { "0": "Zero" ... } なら>>331
digitnames = { 0: "Zero" ... } なら digitNames[int(x)]になるだけだろ。

Perlなら
my @string = map{ join '', @digit_names{split //, $_} } @numbers;

Javascriptなら
var strings = numbers.map(function(number) {
return number.toString().split("").map(function(x) { return digitNames[x] }).join("");
});

Javascriptはアロー演算子が欲しいところだ。

333:デフォルトの名無しさん
14/12/21 18:21:39.18 MvQSKDIW.net
最強言ったから気に食わなかったならスマンカッタ

PHPの緩さは、こういうのが動くところ。>>329でそのまま動く
$digitNames = ['Zero','One','Two','Three','Four','Five','Six','Seven','Eight','Nine','.'=>'Point','-'=>'Minus'];
$numbers = [1.234, -5.4321];

334:デフォルトの名無しさん
14/12/21 23:04:35.55 YWufr8fT.net
>>327
>>326 と比較すると:
・わざわざジェネレータで「組立てた」シーケンスを
 reduce で「畳み込んで」いて、二重のループになっているから処理効率(=性能)が悪く、
 なおかつ reduce へ渡すラムダ式が増えているからコードも複雑化してしまっている
・そもそも「Haskell の unfold 定義」に従って関数定義していないから
 その関数の命名 unfold は不適切であり、別の名前を考案すべき
 念の為に「Haskell の unfold 定義」を以下に示す(ただし末尾再帰ではなく一般再帰):
  unfold :: (B -> Maybe (A, B)) -> B -> [A]
  unfold f u = case f u of
          Nothing -> []
          Just (x, v) -> x : (unfold f v)
この「Haskell の unfold 定義」に従った unfold の Python 実装を以下に書いた:
  URLリンク(ideone.com)
  ・__unfoldl_string_rec__:一般再帰による実装(>>326 と同じ)
  ・__unfoldl_string_while__:while 文と破壊的代入を使った手続き型実装

あわせて Ruby の実装コードも更新した:
  URLリンク(ideone.com)
コードの要点を示す:
・Python のジェネレータを Ruby では外部イテレータ Enumerator と呼ぶが、
 (Ruby 1.9 以降のメソッド定義マナーに従い)ブロックが渡されていない場合には
 (組込みメソッド Object#to_enum を使って)外部イテレータを返すようにした
・3種類のメソッド定義を示した
 ・String#__unfoldl_rec__:一般再帰による実装(>>326 と同じ)
 ・String#__unfoldl_until__:until 文と破壊的代入を使った手続き型実装
 ・String#__unfoldl_loop__:メソッド loop を使った参照透明性のある関数型実装(>>267

最後に、Ruby と同様な「Haskell の unfold 定義」に従った
Python のジェネレータ実装については、>>327 への宿題としておく
(ML や Haskell といった静的型付け関数型言語に慣れていないと、難しいかもしれないが....)

335:デフォルトの名無しさん
14/12/22 08:52:28.54 6avCYBJ9.net
Pythonの場合リストを返したかったら list(unfold(f, x)) で良くね?
毎回 s += a 等やって組み立てるよりも速いぞ

336:デフォルトの名無しさん
14/12/22 09:03:18.85 6avCYBJ9.net
あ、もしかしてunfoldlじゃないからダメって言ってんの?
unfoldには unfoldr と unfoldl の二種類あって、HaskellではPreludeにあるのはunfoldrだけだぞ

337:デフォルトの名無しさん
14/12/22 09:04:46.38 6avCYBJ9.net
ちなみに>>334が自信満々に貼ってる方のHaskellのunfoldの定義はunfoldrの方なw

338:デフォルトの名無しさん
14/12/22 09:07:58.19 ZCDWZl5G.net
unfold :: (B -> Maybe (A, B)) -> B -> [A]
じゃないから駄目とか言っといて、なんで出してる実装はことごとく
unfold :: (B -> Maybe (A, B)) -> B -> A
なの? バカなの?

339:デフォルトの名無しさん
14/12/22 14:26:58.64 51sTiTTJ.net
またオレオレ定義君がやらかしちゃったかー

340:デフォルトの名無しさん
14/12/22 21:08:27.40 8h2AGQmm.net
cにクロージャくれよっておもってたけど
今ならgoがあるんだよな

341:デフォルトの名無しさん
14/12/22 21:10:47.28 VRBNRD9f.net
C++使ったら?スコープ抜けた際どうなるか、必要ならコピーを持たせよう、とかスマポにするかーとか、考える必要はあるけど

342:デフォルトの名無しさん
14/12/22 21:16:46.96 6skO2mFq.net
>>340
clangならblocksが使えるんじゃないかしら

343:デフォルトの名無しさん
14/12/23 06:28:08.32 pszL50YR.net
ほー objc じゃなくても使えるのか。
まあ objc に c のソースだけ食わせて使ってもいいんだけど。

344:デフォルトの名無しさん
14/12/23 11:28:17.27 St4HMSPr.net
boost lambdaで怖い思いしたから
c++はng
コンパイルエラーから黒魔術なコード出されてもこまる

345:デフォルトの名無しさん
14/12/23 11:30:55.43 0dLhalMI.net
そういうのはreplで対話的に書けたほうがいいな

346:デフォルトの名無しさん
14/12/23 14:09:04.60 Og1JN7U7.net
このスレのおかげでクロージャの良さと
Ruby信者のキモさが分かりました
ありがとうございました

347:デフォルトの名無しさん
14/12/27 00:25:14.89 randw1SU.net
クロージャなんて最近の言語は大抵あるからね
次に関数型言語からパクって欲しいのはパターンマッチ

348:デフォルトの名無しさん
14/12/29 07:25:36.12 Br8mMuyh.net
disると公開される

349:デフォルトの名無しさん
14/12/29 16:50:56.24 9aAL2Pj2.net
まぁ別にいらないっちゃいらないな。
最近の言語はいろいろ付けすぎだわ。
もっと仕様単純でいいよ。

350:デフォルトの名無しさん
14/12/29 17:19:30.86 LxjJzYoX.net
パターンマッチの無い言語にパターンマッチを付けられるような言語がいい

351:デフォルトの名無しさん
14/12/29 19:45:55.93 NKff8BVB.net
>>350
プリプロセッサを使えば、どんな言語でも
なんだって出来るんじゃね?

352:デフォルトの名無しさん
14/12/30 17:09:02.43 AU/nggqJ.net
その万能プリプロセッサがあればいいんだけど

353:デフォルトの名無しさん
14/12/30 18:06:56.67 mxKZGqd3.net
m4通すとか?

354:デフォルトの名無しさん
14/12/30 18:40:21.70 AU/nggqJ.net
その言語処理系を書かた言語のコードを直接書き変えるような書き方じゃなくて
その言語自体で新しい表現(パターンマッチとか)を定義出来るようにするってこと

355:デフォルトの名無しさん
14/12/30 19:32:00.99 tU/2zS2Z.net
>>350
lispおじさんだ!

356:デフォルトの名無しさん
14/12/30 20:40:47.63 LKC757rT.net
lispでマクロ使えばおk

357:デフォルトの名無しさん
14/12/31 23:19:03.80 tqgvohnx.net
>>354
たぶんschemeにドハマリするタイプ

358:デフォルトの名無しさん
15/01/01 00:15:11.77 6s4ScpeL.net
on lispとかlet over lambdaがあるcommon lispの方がいいんじゃね

359:デフォルトの名無しさん
15/01/01 08:49:44.48 Vz2QaCIS.net
あなほりマクロ怖い

360:デフォルトの名無しさん
15/01/01 19:26:59.51 LWrX8qsS.net
やっぱりpythonとかhaskellのコードと比べると
専用の構文があった方がスッキリ書ける
でもそうすると自由度が無くなってマクロがうまく使えないジレンマ

361:デフォルトの名無しさん
15/01/01 19:31:53.89 LWrX8qsS.net
一応リーダマクロを使えば解決するんだけど結局使わなくなる

362:デフォルトの名無しさん
15/01/02 09:58:20.63 ie8IusfS.net
lispおじさんのせいで
すっかりマクロ談義スレになったな

363:デフォルトの名無しさん
15/01/02 10:14:10.05 PL75YfkA.net
真のクロージャとマクロ、どっちがマシか難しいところだな

364:デフォルトの名無しさん
15/01/02 11:28:56.61 Ur5QsT6D.net
二つのいいところを組み合わせたものが最強ではないだろうか?

つまりマクロージャー

365:デフォルトの名無しさん
15/01/02 12:10:26.52 ie8IusfS.net
マクロにコンテクストが付いて回るclの事だよねそれ

366:デフォルトの名無しさん
15/01/02 15:30:32.04 /upm+g4t.net
マクロとクロージャを組み合わせればOOPも継続も後から付けられる

367:デフォルトの名無しさん
15/01/02 15:37:48.79 Ur5QsT6D.net
いろんなことができる。そうマクロージャならね!

368:デフォルトの名無しさん
15/01/02 20:00:41.84 ZuY3pBgY.net
>>366
継続渡しではないですよね?
マクロとクロージャーで継続をどう実装するか
ぱっとは思いつかなかったのでよかったら教えてください。

369:デフォルトの名無しさん
15/01/02 20:28:34.80 UWr+Udi0.net
onlispでは継続を表わすクロージャを引数で渡してそれをマクロで包んでる
これだと使う側が末尾呼出的に書かないといけない縛りがある
cl-contは式をwithマクロで包んでその式をcodewalkしてcps変換してる

370:デフォルトの名無しさん
15/01/02 21:04:50.09 ZuY3pBgY.net
ありがとうございます。On Lisp 読んでみます。

371:1
15/01/09 13:33:15.35 3m5OEfmN.net
そもそも関数が一級オブジェクトである必要があるのかどうか疑問が出てきました
ifelse( aaa, xxx,
ifelse( bbb, yyy,
ifelse( ccc, zzz,
      iii )))
       ↑死ね
IDE使えってことなんでしょうけど認知に負荷をかける言語仕様は間違ってると思うんですよね
これよりはメソッドチェーンの方がかなりスマートだと思う
foo(aaa){xxx}.bar(bbb){yyyy}.baz(ccc){zzz}

372:デフォルトの名無しさん
15/01/11 21:16:33.98 8HLn7hr5.net
それだと全てのメソッドで条件分岐を想定した実装にしなくちゃいけなくなるのでは

373:デフォルトの名無しさん
15/01/16 01:40:03.14 U7RTYgR7.net
Pythonはパターンマッチ以前にSwichtすらない

374:デフォルトの名無しさん
15/01/16 08:39:36.86 oLGQ6wLb.net
>>373
そんなもんがある言語を見たことないが

375:デフォルトの名無しさん
15/01/16 23:23:44.50 obgM8cFp.net
なんかドイツ語?みたいな切り方だな

376:デフォルトの名無しさん
15/01/21 16:33:15.48 Out9u5nx.net
ゲルマンおじさんこわい!

377:デフォルトの名無しさん
15/01/22 01:37:45.45 8pwMw7VT.net
スウィヒトとか読むの?ドイツ語ってよくわからんタイミングで濁るイメージあ?からジットとかかな

378:デフォルトの名無しさん
15/01/22 08:08:05.98 VatMjg6z.net
スヴィヒトだな、あえてカタカナを当てれば

379:デフォルトの名無しさん
15/01/24 00:56:47.04 hSO7J5Oj.net
中二病みたい

380:デフォルトの名無しさん
15/01/27 21:37:55.87 x1TLH4fz.net
ここまでnonlocalなし

381:デフォルトの名無しさん
15/11/26 03:43:18.04 9L/RhMYwv
関数を返す関数を定義するときにはいる

382:デフォルトの名無しさん
16/01/10 19:01:54.47 sdj7zt3O.net
Objective-Cのblocksが便利だというからいろいろ読んでみたが
使い道がよーわからん。他言語のクロージャやラムダだということで
他言語のクロージャやラムダについて読んでたらもっと混迷が深まった。

383:デフォルトの名無しさん
16/03/29 09:21:36.23 /c8bAcK4.net
サッカーブッシュ日本代表日程ぷあたん(しゅっちょうまいくろ教育長交代)春文執行40代売上差額シュガーチョコ
URLリンク(www.youtube.com)宇ドナルドアナリストパワーストーンコーチングとしまえん
サッカーブッシュ日本代表日程古本屋よしたけしゅっちょうちょこしゅがー
ディーラー税務署天才開発者死亡詰みヨミドクターマイクロサービス不足
サッカーブッシュ日本代表日程ぷあたんシフト光金さかい強制バイト人権侵害問題
春分資源執行ニューヨーク低原価ぼったステーキソルトレイク福岡横浜新橋奴隷課金パチシフト強制バイト問題新潟米センター生残
コスメ24チャリティー隠れ40代生活保護プレイボーイバイトレードいたりあん接待問題
マスコミKARDローンケーオーサービス不足婚活パーティー寄付金執行原発ビジネス
FBIチャイニーズタイホテル売上事務所ガチャ決算ガチャキャンペーン(販売報道陣過激派組織向携帯最新情報提供終了
校長発言細心注意ノートン産廃エラー(著作権クレーム中国反応融資高額教育費)(中国捕鯨団体40代社員サッカーコメント
高額入学金ヤフウ新橋大学ヤフウ新橋理事長FX経費 おじや50代資産ガリバズフィード40代エリート

384:デフォルトの名無しさん
16/05/01 14:33:24.76 tKi6j9CT.net
匿名通信(Tor、i2p等)ができるファイル共有ソフトBitComet(ビットコメット)みたいな、
BitTorrentがオープンソースで開発されています
言語は何でも大丈夫だそうなので、P2P書きたい!って人居ませんか?
Covenantの作者(Lyrise)がそういう人と話したいそうなので、よろしければツイートお願いします
URLリンク(twitter.com)
ちなみにオイラはCovenantの完成が待ち遠しいプログラミングできないアスペルガーw

The Covenant Project
概要
Covenantは、純粋P2Pのファイル共有ソフトです
目的
インターネットにおける権力による抑圧を排除することが最終的な目標です。 そのためにCovenantでは、中央に依存しない、高効率で検索能力の高いファイル共有の機能をユーザーに提供します
特徴
Covenant = Bittorrent + Abstract Network + DHT + (Search = WoT + PoW)
接続は抽象化されているので、I2P, Tor, TCP, Proxy, その他を利用可能です
DHTにはKademlia + コネクションプールを使用します
UPnPによってポートを解放することができますが、Port0でも利用可能です(接続数は少なくなります)
検索リクエスト、アップロード、ダウンロードなどのすべての通信はDHT的に分散され、特定のサーバーに依存しません



最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch