1 名前:デフォルトの名無しさん mailto:sage [2012/01/02(月) 22:19:28.26 ] haskell.org ttp://www.haskell.org/ 日本語サイト ttp://www.sampou.org/cgi-bin/haskell.cgi ttp://www.shido.info/hs/ 過去ログ 関数型プログラミング言語Haskell Part1 ttp://pc.2ch.net/tech/kako/996/996131288.html Part2 ttp://pc2.2ch.net/test/read.cgi/tech/1013846140/ Part3 ttp://pc8.2ch.net/test/read.cgi/tech/1076418993/ Part4 ttp://pc8.2ch.net/test/read.cgi/tech/1140717775/ Part5 ttp://pc8.2ch.net/test/read.cgi/tech/1149263630/ Part6 ttp://pc11.2ch.net/test/read.cgi/tech/1162902266/ Part7 ttp://pc11.2ch.net/test/read.cgi/tech/1174211797/ Part8 ttp://pc11.2ch.net/test/read.cgi/tech/1193743693/ Part9 ttp://pc11.2ch.net/test/read.cgi/tech/1211010089/ Part10 ttp://pc12.2ch.net/test/read.cgi/tech/1231861873/ Part11 ttp://pc12.2ch.net/test/read.cgi/tech/1252382593/ Part12 ttp://hibari.2ch.net/test/read.cgi/tech/1272536128/ Part13 ttp://hibari.2ch.net/test/read.cgi/tech/1286706874/ Part14 ttp://hibari.2ch.net/test/read.cgi/tech/1299385928/ Part15 ttp://hibari.2ch.net/test/read.cgi/tech/1310199414/ Part16 ttp://toro.2ch.net/test/read.cgi/tech/1317958045/
386 名前:デフォルトの名無しさん mailto:sage [2012/01/26(木) 23:11:31.79 ] >>385 > ちなみに、遅延評価とバッファは全く関係ない。 > ファイルを逆から読むのにバッファは必要ない。 ファイルを逆から読むのにバッファを必要としない方法もあることは分かっている >>384 で私が言ったのは、「ストリームとして扱う場合はバッファを必要とする」 ということだ ストリームというのは、パケット通信などのように、 ある塊のデータ群が一列に順に一つずつ流れる、あるいは流すこと 順に流入してきたものを逆順に流出させるには、バッファが絶対に必要だ そのバッファの仕組みをプログラマが意識して自分で作る必要があるかどうかは別だが 確かに遅延評価とバッファに直接の関係はない だが、上記の「ストリームの逆順流出」において 遅延評価を実現させる為の内部の仕組みがたまたまバッファの役割を果たす もう一度言うが、あくまで >>376 のレスを受けて、 「内部処理もストリームとして扱う場合」の話をしている (それが非効率的な事も分かっている)
387 名前:デフォルトの名無しさん mailto:sage [2012/01/26(木) 23:42:32.23 ] よくわからん。 もしhGetContentsが遅延評価でなく先行評価だったとしたら、 その「ストリームの逆順流出」プログラムはどう変わるんだ? どっちにしてもプログラムはhead n $ reverse $ ... なんじゃないのか。
388 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 00:05:03.45 ] >>387 > もしhGetContentsが遅延評価でなく先行評価だったとしたら、 > その「ストリームの逆順流出」プログラムはどう変わるんだ? そんなことは知らん 先行評価だった場合にGHCが内部でどのような実装をしてくるのか俺には分からない 初めの >>380 では端折ったが、>>382 からはずっと、 遅延評価を実現する為に使われている内部の仕組みが、 ストリームとして流れてくるデータ順の逆転という処理において バッファとして機能することだけを話しているんだが ちなみに、この目的で内部の仕組みがバッファとして機能するのは、 hGetContents の処理ではなく reverse の処理をGHCが実行ファイルに埋め込む部分だ
389 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 00:07:50.19 ] おれは言わんとしてることがわかったけど、 もう少しわかりやすく説明したほうがいいと思うよ。
390 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 00:20:31.26 ] >>389 了解した、努力する
391 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 00:21:30.05 ] 説明ぷりーず。 一応、WHNF簡約やGHCのSTGマシンあたりの実装は理解してるつもり。
392 名前:デフォルトの名無しさん [2012/01/27(金) 00:43:19.91 ] チュートリアルをやってるのですが、最初で詰まってます。 以下のboomBangsという関数定義でチュートリアルのままなのですが、自分の環境だとエラーになります。 どこが間違ってるのでしょうか。ghci 6.12.1です。 Prelude> boomBangs xs = [if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x] <interactive>:1:13: parse error on input `=' Prelude> どうかよろしくお願いします。
393 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 00:55:24.00 ] Prelude> let boomBangs xs = [if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x]
394 名前:デフォルトの名無しさん [2012/01/27(金) 01:05:23.28 ] 動きました。ありがとうございました。 Prelude> let boomBangs xs = [if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x] *** Parser: *** Desugar: *** Simplify: *** CorePrep: *** ByteCodeGen: Prelude> boomBangs [1,2,3,4,5] *** Parser: *** Desugar: *** Simplify: *** CorePrep: *** ByteCodeGen: ["BOOM!","BOOM!","BOOM!"]
395 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 01:13:49.09 ] >>391 あんまり難しい話じゃなくて、C言語とかでも、Seekなしで、 ファイルの先頭からシーケンシャルアクセスしかできないとしたら、 最後10行のデータ取ろうと思うと、どうしても直近10行はバッファ しとかないといけないでしょ? Haskellは、このバッファを意識しないでも、自動でやってくれる って言ってるんだと思うよ。 遅延評価がバッファしてるわけじゃないけど、バッファしてるように 見えなくもない。
396 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 02:26:27.98 ] Haskellも結局クリーンで美しいカルト言語だったんだお 設計外のことを無理にやらせれて破綻するんだお
397 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 02:49:49.78 ] ということにしたいのれすね?
398 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 03:01:28.89 ] 実際にやってみたけど、「ふつうの」に書いてある元々の「効率の悪い」 tail に 10 GB ていどのファイルを食わせても、5 秒もかからないんだよね。 これが分単位になるのなら考えてもいいけど、そうでなければ簡潔さの ほうが大事だと思う。 “「効率」についてうんぬんする人々は、たいていの場合主として本番計算に 計算機資源がどのくらい使われるか、という点にばかり着目していて、コンパ イルしたり、虫取りしたり、その他さまざまなやりそこないをしたりしながら 本番計算にそなえるために消費される人間の時間と計算機の時間を考えに入れ ていないのである。” (ソフトウェア作法 p.132)
399 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 03:03:28.54 ] ごめん、10GB は嘘だわ。10MB ね。
400 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 03:13:57.42 ] ちなみに自分は後ろから読む tail コマンドを昔 C (Pascal だったかも)で書 いてみたことがあるけど、 * ファイルが改行で終わる場合と終わっていない場合を分ける * バッファの先頭から行がはじまっているか、その前からつながっているかを分ける とか、細かい場合分けがあって、予想したより面倒だった。
401 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 05:53:27.42 ] >>395 正格評価でも、明示的にバッファ取らなくても、 パラメータ渡しをバッファ代わりにできますし…
402 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 05:56:04.14 ] >>398 > これが分単位になるのなら考えてもいいけど、そうでなければ簡潔さの > ほうが大事だと思う。 んなこたーない。 > “「効率」についてうんぬんする人々は、たいていの場合主として本番計算に > 計算機資源がどのくらい使われるか、という点にばかり着目していて、コンパ > イルしたり、虫取りしたり、その他さまざまなやりそこないをしたりしながら > 本番計算にそなえるために消費される人間の時間と計算機の時間を考えに入れ > ていないのである。” (ソフトウェア作法 p.132) これは数回実行するだけの研究用プログラムについては正しいが、 UNIXのtailコマンドのように1度書かれたソースを莫大な回数実行する場合には 詰められる無駄は詰めたほうがいい。
403 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 06:59:03.58 ] 正格な評価でも10行分のキューにストリームから一行読んでは突っ込んでいくだけでしょ 別にC言語でも数分で書けるから特にHaskellを使う利点はないよね
404 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 07:36:42.85 ] >>401 同じ事を繰り返すが 私は正格評価の事については一言も触れいてない 正格評価ではバッファを意識する必要がある、 なんて私のレスが何処かに書いてあるか? 私は一貫して ・ストリームとして処理するならバッファが必要 ・遅延評価を実現する仕組みがバッファとして機能している この2点しか述べていない 「遅延評価とバッファの関係」を質問されたから、 正格評価の事まで話に絡める必要は無いだろ 別に遅延評価vs正格評価でどちらが有利か戦わせているわけではない 正格評価でも明示的にバッファ取らなくてもいい と貴方が言うのなら、きっとそうなんだろ それは私の話とはたぶん関係ないと思うから、 それがどうかしたのか、としか言いようがない ちなみに、私の話とは別の事として訊くのだが、 > パラメータ渡しをバッファ代わりにする それはパラメータでバッファを渡しているのではないか? 遅延評価を実現する仕組みでたまたま機能するバッファの方は、 バッファを作っているという意識すら感じずにプログラムできるが 「正格評価+ストリーミング処理+パラメータ渡し」 これでバッファを意識しなくてもいいプログラムを書いてみてくれ ちょっと興味ある
405 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 07:46:54.83 ] 引数として先頭トークンと継続を渡せばいいんじゃね?
406 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 07:49:56.57 ] >>391 以下の部分で遅延評価とバッファの関係を簡単に述べている どこの部分の詳細な説明を求めているのか具体的に言ってほしい >>384 > 遅延評価の仕組みにより、reverse 関数はリストの内容は評価しない > 後で評価する可能性がある未評価のデータはメモリ内に残り続ける > この部分がストリームを逆順にたどるための「バッファ」の役割を果たしている
407 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 08:04:10.58 ] アホかHaskellでもバッファは意識しろよ そんなんだからアホ的非効率コードを書くんだよ
408 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 08:13:37.12 ] どうでも良くなってきたが、、、 正格評価、遅延評価とかはバッファと関係ないと思います。 というか、バッファされてる時点で評価済みで遅延してない、、、 正格でも遅延でもたぶん同じように書けます。
409 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 08:23:27.08 ] 手元にある一番大きなプレーンテキストは MySQL のダンプ(1.3GB)だったので, これを「ふつうのHaskell」版の tail コマンドに食わせてみたが、メモリオー バーで時間計測できず(笑)。ファイル丸ごと reverse はさすがにないな。 ただ、個人的にはテキストファイルをランダムアクセスするのは(使用言語が何 であれ)プログラムが無意味に複雑化するので反対。sort とかなら高速化の意 味はあるだろうけれど、tail コマンドをそんなに速くしてどうするの、っていう かんじ。 Haskell なら、このていどでいいはず。これなら本にのせても場所を取らないし、 大きなファイルでも動作する。 import System dotail :: Int -> [a] -> [a] dotail n xs = if null (drop n xs) then take n xs else dotail n $ tail xs main = do {args <- getArgs; cs <- getContents; putStr $ unlines $ dotail (read (head args)::Int) (lines cs)} 1.3 GB で 13分だった。Haskell の入出力の遅さを考えればまあまあじゃないかな。 ちなみに同じファイルに対して行数カウント getContents >>= print.length.lines だと 8分35秒。Java (BufferedReader.readLine 使用) や Perl で同じことを やると1分40秒から 1分50秒くらい。wc -l コマンドだと 36秒。
410 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 08:30:16.99 ] おまいらこのあとは tail -f の実装が待ってますよ
411 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 10:25:32.57 ] ふつうに実装するとIO (IO String)が出てくるから それよりはunsafeでもIO [String]にしたいってことなのか
412 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 10:39:57.79 ] System.IO.MMap.Lazy
413 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 11:12:49.26 ] tailなんて巨大ログをすばやく確認したい時ぐらいなんだから いちいち先頭から1行ずつ読むとか糞遅かったら誰も使わんだろ 用途を満たさない物なんか設計してどうする 言語の作法なんて関係ない
414 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 11:16:44.14 ] >>410 それは簡単じゃない? Control.Concurrent の threadWaitRead で待って、サイズが変わってたら その分を出力するだけでしょ。
415 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 11:32:02.97 ] 俺がtail使うのはファイルよりpipeのほうが多いな
416 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 12:06:04.37 ] ここで問われているのは、 長年GNUがやってきたように、 過去の他人の成果を丸パクリして、 それでも使われるレベルになるのかどうか? ということだよな
417 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 12:47:47.33 ] 儲かるレベルにはならないからポジショントークをする人がひとりもいない という成果に期待しよう
418 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 14:20:57.31 ] クソ実装でも十分速いとか言ってる香具師がいるけど、 空読みするファイルが分散fs上に乗ってたら悲惨だなw
419 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 16:51:25.37 ] 標準だけで教科書的に綺麗に書くようなオナニーは卒業して 仕事でHaskell使っている人が苦心の末発明したcondoitの使い方覚えろよ
420 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 17:07:01.50 ] なにそのコンドームみたいなの?
421 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 17:09:06.72 ] conduit
422 名前:デフォルトの名無しさん mailto:sage [2012/01/27(金) 18:37:45.13 ] あれだこれだと意見はいろいろあるだろうが、 にコードが出てきたのがなんと言っても尊い。
423 名前:デフォルトの名無しさん mailto:sage [2012/01/28(土) 11:33:31.74 ] >>288 Template Haskell を少し勉強してみたところ、 やりたいことが実現できそうなことが分かりました 例えば次のように引数をコンパイル時に制限できるんですね f :: Int -> ExpQ f x | x < 0 = fail "error" | otherwise = [| x |] $(f (-1)) ====> error $(f 3) ====> 3 このような事を値構築子でできるようにすれば良いわけですね 調べてみます ありがとうございました
424 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 09:15:33.67 ] jutememo.blogspot.com/2011/04/haskell-swap-9.html リストの要素を入れ替えるswap関数は、pythonの方が簡潔なんだな・・・ リストを配列みたいに扱えない言語よりは優位なんだろうけど、そう言う言語と比較するときは配列と比較になるしなぁ・・・
425 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 09:30:41.60 ] リストのランダムアクセスは遅いから専用の関数が用意されてないだけ Data.Sequenceならupdateがあるので簡単 swap :: Int -> Int -> Seq a -> Seq a swap i j s = update i (s `index` j) $ update j (s `index` i) s
426 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 09:37:27.18 ] よく言語Aより言語Bの方が処理(計算)xを簡単に書ける、というけどさ 言いたいことは分かるけど、「具体的な処理」に関して、 処理後に同じ結果が得られる複数の言語間で「簡潔さを比較」する意味って何なの? >>424 のリストの swap だって、一旦関数にしてしまえば、 あとは Haskell でも同じように簡潔に書けると思うんだが (それがライブラリの大きな役割の一つだし) >>424 のリンク先で考察している方法それ自体は面白いし興味あるけどね
427 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 09:44:58.64 ] >>426 いろいろな具体的な(既知の)処理を簡潔に書ける言語があれば、 アプリケーション固有の(未知の)処理も簡潔に書ける可能性が高いからだろ 未知の処理だって、なんらかの既知の処理に似ていることが殆どだ ということを加味すればなおさら
428 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 09:53:41.16 ] そりゃ、できることを比較したらどれも同じになるから比較にならんだろ。 言語の比較は、簡潔に書きやすいとかできるコードが速いとか、デバッグ しやすいとかになるわ。ライブラリだって簡潔に書けるほうが充実させや すいしな。
429 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 10:07:36.20 ] ハスケルのほうが簡単に書ける時には 「ハスケル最強」 ハスケルのほうが煩雑になってしまう時には 「そんな比較意味なくね?」
430 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 10:15:41.39 ] >>429 それは、逆も同じだけどね。 ハスケルのほうが簡単に書ける時には 「そんなの意味なくね」 ハスケルのほうが煩雑になってしまう時には 「ハスケル使えねぇ」 用途考えずに比較なんて意味ないね。
431 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 10:35:32.33 ] >>427 いや、だから一度関数になってしまえば、「簡潔さはほぼ同じ」になるわけでしょ 最初に比較して言語Aの方が簡潔だった、でも関数にしたから言語Bも同じなった >>424 の言う「優位な言語」というのは、どの時点で比較したものなの? 仮に言語Bが関数化した結果、言語Aよりも簡潔になったら、言語間の優位さは逆転するの? そういうことで逆転してしまうのなら、それはその「具体的な処理に関する」 簡潔さの言語間の比較とは言えないだろう その具体的な処理に被せるインターフェースの部分のおかげで簡潔になったのだから また、そんなことで逆転したとは言えないのなら、そもそも比較して 言語Aの方が優位だとか言うことの意義が見いだせない 私の経験上、実用的なアプリ内の数多ある個別具体的な処理に関して、 それらを最も得意とする言語(やパラダイム)は複数に分散する ある特定の処理をするのに言語Aが優位だからという理由で、 そのアプリを作るのに言語Aを選ぶことは、実際のところ滅多にない 普通は自分やチームが得意としている言語であったり、 個別具体的な処理ではなく全体の求められる処理速度やメンテのしやすさなどで決定される >>428 今の時代、広く使われている言語なら、どの言語でもライブラリは充実している 充実度の差の理由に言語の簡潔さが関わる割合は、比較して議論するほど高くはないと思うが
432 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 10:58:44.59 ] ある処理を実験する複数のプログラムを一つのファイルに書いていました。 (初めはファイルを分けるのが面倒に思えたから) あるプログラムを実験するときは別のプログラムをコメントアウトしたりして。 なので、ファイルのトップには import が大量に書かれています。 実験が終わって、採用するプログラムを一つに絞ったので、 それを正式にちゃんとしたファイルに分けて保存したいのですが、 そのプログラムを実行するのにどの import が必要なのか、 ごちゃごちゃしてて分からなくなりました。 とりあえずそのプログラムだけ別ファイルに移してコンパイルしてみて、 モジュール不足の為にコンパイルエラーが出る度に import を追加していけばいいとは思いますが・・・(以前も同じ様なことをしてた) もっと簡単に、あるソースファイル内の識別子を評価するのに不足していて、 かつインストール済みであるライブラリのモジュールの一覧を見る方法はありませんか。
433 名前:427 mailto:sage [2012/01/29(日) 11:08:59.81 ] >>431 俺は>>424 じゃないけど、関数化の前の話をしているつもりだった >また、そんなことで逆転したとは言えないのなら、そもそも比較して >言語Aの方が優位だとか言うことの意義が見いだせない >私の経験上、実用的なアプリ内の数多ある個別具体的な処理に関して、 >それらを最も得意とする言語(やパラダイム)は複数に分散する もちろん。でも、実際的なアプリが色んな処理から成っているからこそ、 言語には極端な苦手分野がないほうが良いし、なるべく広範囲のコードを 簡潔に書けるのが良いということになる たとえばランダムアクセス可能なデータ構造をすごく扱いにくい言語があったら、 その言語で書き易いアプリはかなり限定される それから、アプリごとに多用される処理の傾向も違う 行列演算中心のアプリもあるし、DBアクセス中心のアプリもあるし、両方やるのもある
434 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 11:13:25.04 ] >>432 全部のファイルに全部のimportをコピーして、とりあえずコンパイルを通す コンパイルが通ったら-fwarn-unused-importsで不要なインポートを一掃
435 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 11:16:53.53 ] >>431 長くて読む気しないな。 言語比較なんてナンセンスだと思うが。言語の優劣なんて個人個人で違うし。 関数化すれば0になるかもしれないけど、関数化するまでのコストは? ライブラリになってないところの、作成コストは? ライブラリの学習コストは? ライブラリは十分充実してる?そしたら自分でプログラムなんて書かんわ。
436 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 11:30:01.60 ] >>434 なるほど、逆でしたか 不要な import を省いていくんですね ありがとうございました
437 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 12:41:36.12 ] >>431 うーん、同じ処理の関数化の比較は、コードの長さとかだけじゃなく、関数化する際の概念とか手法とかがプログラマ・あるいは初心者に思いつきやすいか?とかの意味でも比較の意味はあると思う。 >>424 のURL先ではpythonは配列的にも使えるリストのために、値の交換が得意な配列的な処理になってるけど、配列は配列。リストはリストとして扱う手続き型言語の場合、 1、リストの中身を配列に移す 2、配列で値を交換 3、配列の中身をリストに戻す と言う処理になる Haskellだと >>424 の9つの方法の内、初心者にも出来そうな一つ目と二つ目の方法は基本 1.リストを分割する (iより前のリスト、i、iとjの間のリスト、j、jの後ろのリスト) 2.値を交換した状態のリストとして結合しなおす という処理になる
438 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 12:53:23.82 ] >>437 > 1、リストの中身を配列に移す > 2、配列で値を交換 > 3、配列の中身をリストに戻す > > と言う処理になる そんな馬鹿なコードを書くのはプログラム初めて1ヶ月とかの初心者だけだろw
439 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 12:55:50.74 ] >>438 え、確かにリストのままでも配列的に使えるけど、パフォーマンス的にはこちらは今でも有効だと思うけど・・・
440 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 13:03:38.33 ] たった1組のswapにそんなことしてたら大爆笑だよw
441 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 13:05:40.34 ] >>437 で、swapの実装という単位で比較した結果、言語Aの方が 関数化する際の概念とか手法とかがプログラマ・あるいは初心者に思いつきやすい と結論づけられたとして、それからどうなるの? それが何にどのように、どれくらい活かされる? 例えばHaskellという一言語においてリストをswapするいくつかの方法の中で、 簡潔さ、初心者の理解のしやすさ、計算速度、応用の幅・・・ などで互いに比較しすることの意義は分かる 時と場合によって使い分ける際の自分なりの基準になる しかし、今存在している言語間で、swap処理などの 抽象度の低い低レベルレイヤーの処理の実装を比較して 優劣を考える意義がよく分からない せいぜい新言語を作る際に、既存言語を分析する時ぐらいしか、 言語間で比較して優劣を考える意義はなくないか?
442 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 13:05:46.19 ] >>440 じゃあ、どういう処理を1ヶ月以上たったらしてるの?
443 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 13:15:46.01 ] たまにはArrayのことも思い出してやってください
444 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 13:17:38.11 ] >>442 リスト処理を解説する初心者レベルの入門書で スワップ時にリストの中身を配列に移すなんて方法は、普通は教えない 普通は、双方向リスト・単方向リストの要素がリンクで結ばれていることをまず教える もしスワップ処理を教えるなら当然その後になるが、 その際はリンクを繋ぎ替える処理で実装する方法を教えるだろう 処理速度云々ではなく、その方が初心者が「リスト処理を理解しやすい」からだ 初心者はリストの特徴を学ぶのが大事だからな だから、一ヶ月と言わず、初めから配列に移すなんて方法は学ばない
445 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 13:23:20.30 ] n回のswap処理をするのであれば、1度配列にコピってからn回swapするだろうが、 たった1回のswapのために配列にコピってswapしてリストを再構築するとか、アホだろ。
446 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 13:23:33.53 ] >>441 今はサイト自体(と運営会社)が無くなっちゃったけど、Haskell入門以前という、プログラミング全くの初心者向けのブログ書いてたんだ (そして、ネット上の友達(プログラミング未経験者)に読んでもらって、理解できるか確認しながら書いてた) その関係で、PCがどうやって動いてるかも理解できてない人向けの言語を探してたり そういう意味で、Haskellは割りと有効だとは思ってたんだけど、このswap関数でちょっと心が揺らいでたり (変数の概念とかも数学から離れていないと言う意味で、数学+α程度の知識でプログラミングできる言語だと思う)
447 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 13:24:16.02 ] >>443 Array=配列 ですが、何か
448 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 13:24:26.38 ] まーたこれで数日後にRubyスレが荒れるのか
449 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 13:26:31.49 ] >>444 ん・・・ それって、結局Haskellのやり方と同じことを手続き型言語でもリストのswapの勉強の際には教えるってこと?
450 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 13:28:51.88 ] >>445 何というか・・・ 行間嫁よ そんなの当たり前だろ
451 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 13:31:51.09 ] >>448 rubyの場合、リストっぽく使える配列だね pythonとは名前が逆だけど、実装は何が違うんだろう?
452 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 13:36:38.70 ] >>450 はあ?文脈読んでないのはオマエだろ。 >>424 のリンク先のコードのswap関数の型を書いてみろよ。 どこをどう見たって、リスト/配列中の1組の値のswapだ。 型情報以上に重要な「行間」があるなら書いてみろw
453 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 13:45:07.16 ] >>449 結果としてHaskellのやり方と同じことを初心者には教えることになるが、 そんなことが言いたかったのではないんだ ・一般的にリストと呼ばれている構造をプログラムで表現する方法 ・その表現方法の上での、リストに関する様々な演算方法 リスト処理を初心者に教える入門書はこの2点を分かってもらいたくて書いている Haskell でのプリミティブなリストの表現方法はいわゆる前方参照の単方向リストだが、 概念は他言語で表現されたリストと似ているし、表現方法が同じなら同じ方法が使える もし swap 処理を教えるとしたら、その概念に沿って教えるのが自然だ 概念から外れた方法を理解させようとしている入門書があるなら、 その入門書は(少なくともその部分に関しては)クソだと思う
454 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 14:12:10.92 ] >>452 視野が狭いな・・・
455 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 14:25:57.63 ] >>453 リスト専門の入門書ってのは読んだこと無いんだが、もし在るならそうなるだろうね Haskellでちょっと不便かな?と思ったのは配列も値が変えられないだろうという事。結局、IOモナドなり、Stateモナドなりを頼る事になりそうなのがね・・・ >>425 のupdate関数は初心者にも作れるし、意外と有効かも (全体を2回書き換える事にはなるが、コード上は交換したい値を一つずつ更新してるのは、初心者には分かりやすそう) 最近はリストなんだか配列なんだかという、(コード上の)データ構造の性質がハッキリしない言語が多くなってきたから、楽にはなったけど、データ構造の性質を教えるのにはちょっと不便になってきた気がする (そう言う意味では、Cとかの方が生々しい意味で最適なのかも知れないが、生々しすぎて初心者には敷居が高いし・・・)
456 名前:453 mailto:sage [2012/01/29(日) 14:33:26.96 ] >>449 読み返したら誤解を与えそうな感じがするから言っておくが 一般的なリストの構造とリストの演算を初心者に教える過程で swap を教えるのなら、 結果としてHaskellのやり方と同じことを教えることになる、という事だからな 要素の破壊的な代入が許されるタイプのリストなら、 普通の変数同士のswapのようにテンポラリ変数を使って比較的素早くswapできるし、 そのように解説している入門書もあるだろうが、それは目的が違う その部分の関しては、リストの構造とリストの演算を学ばせるためじゃない (喩えは悪いかもだが、方程式の解法で移項というテクニックを教えるようなもの)
457 名前:453 mailto:sage [2012/01/29(日) 14:34:53.97 ] レス前にリロードしとけば良かった orz
458 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 14:41:52.19 ] >>456 いや、ありがとう 他人に書かれてもドンマイだよ 変数の値が書き換わるのが理解出来ない初心者(かなり稀なパターン)へ手を替え品を替え説明するのに比べれば。。。 変数が箱って言う例えは誰が考えたんだよ。。。
459 名前:453 mailto:sage [2012/01/29(日) 14:48:17.90 ] 数学で式に文字が導入された頃から漠然とした箱のイメージはあったと思う 値と変数を束縛して固定するイメージよりは、 値を入れるための箱のイメージの方が先にあったのではないか と、大して根拠もなく個人的には思ってる
460 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 15:00:35.95 ] >>459 それは分かる。つーか、自分も似た感覚なんだが、箱の中身がコピーされるとか、新しい値を入れると消えちゃうとかの説明がね。。。 箱じゃ無くて1個のみのスタックみたいなところてん式(追い出された値は捨てられる)の説明でもコピーが説明出来ないしね。。。 まあ、そいつがバカ過ぎなのが問題なんだけど、普通の人はメモリって何?が基準だしなぁ。。。と、基本的な事柄は紙の上で説明出来るのがベストなのかなぁ。。。とか考えてhaskellに流れ着いてたり ちょっとコンピュータの仕組み齧れば普通の言語の方が自然なんだが。。。
461 名前:453 mailto:sage [2012/01/29(日) 15:15:26.29 ] >>460 私がC言語を初心者に教えている時は、一般的な「変数=箱」のような喩えではなく、 もう初めから「変数=メモリアドレスの別名」と直に教える そして、メモリとはどういう構造か、その上でどんな事ができるかを教えてる 当然メモリって何?が基準だけど、C言語ならそこから逃げられないし 喩えると余計に分かりにくい Haskellを初心者に教えた事は一度しかないけど、 その時も箱とかの喩え話じゃなく、「変数=値の別名」と直に束縛の概念を教えた
462 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 15:36:15.61 ] >>461 自分も結局、変数=値の別名で教えた おバカなその人はhaskellも無い頃の思い出だが、cpuの仕組み習ってる筈なのに(情報技術科の同級生)、全く理解出来てなかった そこまでのバカは捨て置いても良いと思うんだけど、手続き型だとスコープの問題もあるのよね。。。 関数内でswapしたのに値が変わってない!!とか ガッコの先生じゃ無いから、放っときゃ良いんだけど、なるべくそう言う「?」が無い言語が望ましいんじゃ無いかと 本気でプログラマ目指すなら、多分javaやC#しか使わなくても、Cでメモリの概念を直接覚える必要があるだろうな。とは思う (C#は限定的でもポインタ残してたのは、本当に英断だった)
463 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 18:06:25.05 ] >>454 おまえは心が狭いな 素直に自分の間違いを認めればいいのに
464 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 19:00:27.45 ] >>463 1、リストの中身を配列に移す 2、配列で値を交換 3、配列の中身をリストに戻す って書いてて、値の交換が何度も必要な場面で毎回リストに戻す馬鹿がどこに居るよ 行間嫁ってのは、そう言うこと そんな応用力無い奴はプログラマになれないだろが
465 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 21:03:37.16 ] C言語から入るとやたらとメモリの無駄遣いが 気になるのはあるね。 swapは、配列の発想から抜け出せないから出てこないだけで、 リストだと思えば、切ってポインタ繋ぎかえるだけじゃんと思いつくと思う。 Haskellだと、こんな感じか。 swap i j l = let (cs,d:ds) = splitAt j l (as,b:bs) = splitAt i cs in as++[d]++bs++[b]++ds まぁ、swapくらい標準で用意して欲しい気はする。
466 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 21:20:50.26 ] リストでインデックス指定のswapが必要になる時点で型の選択を間違ってる気がしないでもない 綺麗事だけどさ
467 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 21:50:07.46 ] まぁ、他のリスト計算(++ や fold系、zip系など)に比べると、 swap の需要は圧倒的に少ないわな 正直、今まで必要になった事があったのかどうか思い出せん
468 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 22:09:42.45 ] swapは、Sortに使うね。 Haskellは、Sort簡単だからあまり出番がないのかも。 でも、Sliceは欲しいな。
469 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 22:38:39.26 ] >>468 Haskell のリストのソートに swap は使わないだろ 効率的なマージソートの実装が標準ライブラリに既にあるじゃん ソート関数を自作してまで swap を使う理由は何?
470 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 22:45:28.87 ] >>468 マージソートにも、クイックソートにもswap使わないけどね・・・
471 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 22:52:38.26 ] いや、別にHaskellの話してたわけじゃないけどな。 swapって言ったらCのqsortなんかが真っ先に思いついたわけだ。 でもって、まぁHaskellじゃ使わんなと思って出番がないと書いたんだが、、、 しょうもないことに一々絡まんでも。 というか、C言語とかあんま使ったことないでしょ?
472 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 23:11:17.90 ] >>471 絡むってほどのつもりでもなかったけど・・・ Cは確かにあまり使ってないなぁ・・・ 最近は、データ構造の定義がHaskellと似てるなー・・・とか思いながら、ぼんやり復習してるけど
473 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 23:18:12.48 ] >>471 俺も別に絡むわけじゃないが >>468 では Haskell で swap の出番があまりない理由が 「Haskell では sort が簡単だから」に見たから もし仮に Haskell の標準ライブラリで sort が実装されてなかったら、 swap を使って実装する気だったのかなと思って
474 名前:デフォルトの名無しさん mailto:sage [2012/01/29(日) 23:28:13.17 ] よくよく考えてみると swapの最大の利点はデータの長さを変えずに済むことなんだよな だから配列操作に有難がられるわけだ
475 名前:470 de 472 mailto:sage [2012/01/30(月) 00:04:53.69 ] >>473 ごめん・・・ 標準でsortあるの? Haskell入門中で、マージソートもクイックソートも自作したけど、swap使わんかったんで書き込んだんだけど、sort関数あるの知らんかった・・・ ソートって、基本、交換じゃなくて、並べ替えだから、リストの切り貼りで出来るから、swap要らんという意味だったのかと・・・ たぶん、純粋に交換したい時しかswap使わないと思われ 要素が少なかったら、コード上で直接交換できるし・・・ --3要素のリスト限定。(大抵、こういう処理はタプルでするっぽいけど) swap3rd a:b:c:[] = c:b:a:[]
476 名前:デフォルトの名無しさん mailto:sage [2012/01/30(月) 00:12:01.81 ] >>475 > Haskell入門中で、マージソートもクイックソートも自作したけど それは大変素晴らしいことだ ただ、ソート関数自体は Data.List に既にある ライブラリドキュメントを見てみ (そのドキュメントからソースの中身も見れる)
477 名前:デフォルトの名無しさん mailto:sage [2012/01/30(月) 00:29:00.75 ] >>476 ・・・orz ま、まあ、元々アルゴリズムの勉強不足だったから、良いんですけどね・・・
478 名前:デフォルトの名無しさん mailto:sage [2012/01/30(月) 08:40:36.13 ] マージソートはswapじゃなくてリストを対象としてできるぞ?
479 名前:デフォルトの名無しさん mailto:sage [2012/01/30(月) 10:55:57.11 ] ソートがないと思えるのも、 これまた凄い感覚で好きだぜw
480 名前:デフォルトの名無しさん mailto:sage [2012/01/30(月) 18:27:21.44 ] >>464 おまえ、正真正銘の馬鹿だな。 >>424 のリンク先は1組swapする関数で、以後それをベースにした議論が続いていた。 >>424 とは異なる前提で議論をしたければ、それを示せ。それが議論ってもんだ。 自分の勝手な妄想が他人にも共有されていると思うほうが よほど応用力がないオナニー野郎だ。 自分の勝手な妄想を行間などと呼んで、他人にも自動的に賛同してもらえているなど、 正常な判断能力を持つ人間とは考えられない。病院いけ。
481 名前:デフォルトの名無しさん mailto:sage [2012/01/30(月) 19:37:07.68 ] >>480 それをいうなら、>>445 で最初に前提覆してるのはおまいさんだろ・・・ と言うか、自分もおまいさんと同じ意見のつもりで>>437 書いてたんだが? swapは > 1、リストの中身を配列に移す > 2、配列で値を交換 > 3、配列の中身をリストに戻す の2で使うだけだろ 1と3は前処理と後処理 それをおまいさんが>>438 で煽るから、どんな画期的な手法が出てくるのかと期待してたのに・・・
482 名前:デフォルトの名無しさん mailto:sage [2012/01/30(月) 19:47:22.37 ] >>481 すまんが、>>445 はn回まとめてswapを「否定する」内容だと思うぞ。
483 名前:デフォルトの名無しさん mailto:sage [2012/01/30(月) 19:51:58.64 ] >>481 > swapは > > > 1、リストの中身を配列に移す > > 2、配列で値を交換 > > 3、配列の中身をリストに戻す > > の2で使うだけだろ > 1と3は前処理と後処理 え?1,2,3全部で「リスト要素対のswap」じゃないのか? 実際、>>424 のリンク先のコードも「リスト要素対のswap」だし。 冷静になって論点を整理してみたら?俺は>>438 に同意だ。 「リスト要素対のswap」の実装で配列にコピーしてからswapして またリストを作りなおすとか、最初にeliminateする実装だ。
484 名前:デフォルトの名無しさん mailto:sage [2012/01/30(月) 20:11:13.37 ] >>482 なるほど、合点がいった じゃあ、結局、たった一回リストの中身を交換するswap関数は、Cのようにリストと配列がはっきりデータ構造として区別された言語ではどのような処理を行うのがベテランの手法なのだろう・・・ その回答は出てない気がする 私はベテランではないし、最早、>>438 に初心者認定されてるしな
485 名前:デフォルトの名無しさん mailto:sage [2012/01/30(月) 20:59:22.54 ] >>480 話と全く関係ないが、感動した。そうだ行間、行間だ。 行間を読めというやつは何処か特徴的だ。
486 名前:デフォルトの名無しさん mailto:sage [2012/01/30(月) 22:59:47.18 ] 唐突だが、monad-parallel パッケージってめっちゃ便利だな 例えば複数のIOモナドをひとつのリストに全て入れて Control.Monad.Parallel.sequence_ 呼べば勝手に並列処理してくれる プログラムソースが非常にスッキリした 今まで pseq や par を駆使してたのがアホらしくなったわ (monad-parallel パッケージの中で駆使されているんだが)