関数型プログラミング言語Haskell Part17
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2012/01/02(月) 22:19:28.26ttp://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/
0348デフォルトの名無しさん
2012/01/24(火) 12:33:17.39>>46
0349デフォルトの名無しさん
2012/01/24(火) 12:34:10.82「計算順序を意識」とは言っていない
「計算順序を意識しすぎる」や「計算順序に過剰に縛られた」と言っている
意識しなければ正しい計算ができない事は承知している
0350349
2012/01/24(火) 12:49:06.27> 時間O(1)のtailを実装するには結局seekするしかないんだよ
分かっている
だから私はtailの時間O(1)の実装には一言も触れていない
>>345 では、わざわざ泥臭いことをやってはいけないという空気になりがちな
私なりの理由を述べた(tailの実装といった具体的な対象ではなく一般論)
やってはいけないとは言いすぎだと思うが、アプリの設計開始時から、
または Haskell によるプログラム開始時から
泥臭いことをやってはいけないというくらいの考えでプログラムした方がいいと思う
少なくとも Haskell では
泥臭い事を考えるのは、そうしなければ目標を達成する術が残っていない場合だけ
本当に最後の最後に考える最終手段くらいのもの
本来はもっと抽象度を高める方向に意識を向けた方が良いと思う
例えば seek で1バイトずつ取得したものを文字と解釈して計算するよりも、
getContentsに任せて「ファイルの内容を計算対象にする」方が抽象度は高い
蛇足かも知れんが、ついでに言えば入門書も抽象度を高める考え方や方法を伝授すべきだと思う
0351デフォルトの名無しさん
2012/01/24(火) 14:10:06.15お前がそういう意見なのは全然構わん
>>345が「Haskellは泥臭いことをやるのには向かない」と
言っているように読めたので反論しただけ
個人的には泥臭いのを嫌がっていては実用コードは書けないと思っているから
0352デフォルトの名無しさん
2012/01/24(火) 15:21:05.01TX
クラクラ来た。
0353デフォルトの名無しさん
2012/01/24(火) 15:36:49.63>本当に最後の最後に考える最終手段くらいのもの
最初でも最後でもどっちでもいいんじゃないの
なぜ順序を決めたがるのか
0354デフォルトの名無しさん
2012/01/24(火) 16:01:49.74あざっす^^
0355デフォルトの名無しさん
2012/01/24(火) 19:15:01.19俺は >>350 じゃないので横レスになるが、決める決めないじゃなくて、言語の文化としてより自然なやり方はあると思う。
例えて言うなら、日本語は格助詞があるから語順はある程度自由なはずだが、やっぱり自然な語順はあるだろ。
そんな感じ。
やりたい奴はもちろん最初っから泥臭く書いたってそりゃかまわないが、
たいした理由もないのにあえて泥臭く書くのでは Haskell を使う甲斐が無い。
0356デフォルトの名無しさん
2012/01/24(火) 20:34:12.21トイならそれでもいいけど実用でそれやったらアホだぞ
どれだけキャッシュの無駄遣いすると思ってんだか
0357デフォルトの名無しさん
2012/01/24(火) 20:55:06.07どっちもどっちだな〜。
どっちもあほ。
0358デフォルトの名無しさん
2012/01/24(火) 21:08:23.56(ふりだしにもどる)
数GBあるログをtailするコードをHaskellで書いてみてくれ
0359デフォルトの名無しさん
2012/01/24(火) 21:09:07.58tailFile n h = do
seekable <- hIsSeekable h
if seekable
then do
sz <- hFileSize h
hSeek h AbsoluteSeek $ max 0 (sz - n)
hGetContents h
else do
takeLast n <$> hGetContents h
takeLast n xs = diff xs (genericDrop n xs) where
diff xs [] = xs
diff (_:xs) (_:ys) = diff xs ys
性能は出ているらしい
conduit読めないから俺にはいまいち何やってるか分からんが
0361デフォルトの名無しさん
2012/01/24(火) 23:33:17.890362デフォルトの名無しさん
2012/01/24(火) 23:42:03.260363デフォルトの名無しさん
2012/01/24(火) 23:43:15.57行数指定できないから0点
0364デフォルトの名無しさん
2012/01/24(火) 23:55:11.190365デフォルトの名無しさん
2012/01/24(火) 23:58:01.890366デフォルトの名無しさん
2012/01/25(水) 00:21:24.870367デフォルトの名無しさん
2012/01/25(水) 01:31:32.52なんとなく遅延IO使ってみたよ。Iteratee使えるならそっちの方がいいんじゃないかな。
hGetLinesReversed :: Handle -> IO [String]
hGetLinesReversed h = hFileSize h >>= lazyLoop h [] where
lazyLoop h rest pos = unsafeInterleaveIO $ loop h rest pos
loop h rest pos
| pos < 0 = return [rest]
| otherwise = do
hSeek h AbsoluteSeek (max (pos-blockSize) 0)
xs <- replicateM (fromInteger (min blockSize pos)) (hGetChar h)
let (hd:tl) = lines (xs++rest)
(reverse tl ++) <$> lazyLoop h hd (pos - blockSize)
blockSize = 128
0368デフォルトの名無しさん
2012/01/25(水) 02:10:21.02結局unsafe使う以外に方法って見つかってないんだよね?
0369デフォルトの名無しさん
2012/01/25(水) 04:13:13.510370デフォルトの名無しさん
2012/01/25(水) 06:30:19.08これを使ってO(1)のtailを作れたら神だな。
0371デフォルトの名無しさん
2012/01/25(水) 07:24:35.01「処理速度を出す為」だと思ってるんじゃないだろうか
0372デフォルトの名無しさん
2012/01/25(水) 07:57:17.27普通に書けばファイルサイズに対してO(1)時間になるんじゃね?
0373デフォルトの名無しさん
2012/01/25(水) 21:53:21.47ファイルサイズチェックしてないので、10行無かったり、小さすぎるのは駄目だけどね。
main = do
h <- openFile "test.log" ReadMode
hGetLinesTail h 10 0 >>= putStrLn
hClose h
blockSize = 128
hGetLinesTail h l pos = do
xs <- hGetContentsSeekFromEnd h pos
if l > (length$lines xs) then hGetLinesTail h l (pos + blockSize)
else return xs
hGetContentsSeekFromEnd h pos = do
hSeek h SeekFromEnd (-pos)
replicateM (fromInteger pos) (hGetChar h)
0374デフォルトの名無しさん
2012/01/25(水) 21:58:39.36main = do
h <- openFile "test.log" ReadMode
hGetLinesTail h 10 0 >>= putStrLn
hClose h
blockSize = 128
hGetLinesTail h l pos = do
xs <- hGetContentsSeekFromEnd h pos
if l > (length$lines xs) then hGetLinesTail h l (pos + blockSize)
else return xs
hGetContentsSeekFromEnd h pos = do
hSeek h SeekFromEnd (-pos)
replicateM (fromInteger pos) (hGetChar h)
0375デフォルトの名無しさん
2012/01/26(木) 15:33:16.32プログラムになるだろうけど、
強引に別のパラダイムのものに合わせようとすると悲惨になるのは当然じゃろ?
そのパラダイムに応じた方法を模索していくしかないような。
Haskellって他よりパラダイムが明確なだけに得手不得手があるのは
仕方がなさそうよね。
0376デフォルトの名無しさん
2012/01/26(木) 16:55:41.77関数型言語のパラダイムと親和性があると思うけどな
Broken Pipe
0377デフォルトの名無しさん
2012/01/26(木) 17:41:23.30結局、メタパラダイムとかいうのは的外れってことだね
0379デフォルトの名無しさん
2012/01/26(木) 20:04:34.510380デフォルトの名無しさん
2012/01/26(木) 20:23:58.12標準入出力をストリームとして扱うのはインターフェースの部分
内部では tail が代表するように単純にストリームでは扱っていない
関数型は無限リストや継続などでストリームを上手く表現できるが、
今回話題になっている話はインターフェースじゃなくて内部処理の方
正方向で流れてくる情報を逆方向からたどるというのは、
ある意味ストリームとは対極にある処理だと思う
内部処理もストリームにする事に拘るなら、
逆方向にする時にバッファにため込む必要がある
(たまたま Haskell では遅延評価のおかげでそのバッファ処理を自動化できるが)
0381デフォルトの名無しさん
2012/01/26(木) 20:33:13.400382デフォルトの名無しさん
2012/01/26(木) 20:43:46.18正格評価ではバッファを普通にはできない、
と言っているように感じたのか
それなら申し訳ない
遅延評価という仕組みを実現するためのGHCの実装のおかげで、
バッファを作らなきゃいけないことを意識する必要がない
という意味で言ったのだ
念のために言い添えておくと、処理速度などの話とは全く別のことだ
0383デフォルトの名無しさん
2012/01/26(木) 21:37:21.78少なくとも>374のコードは再帰するたびに毎回ファイル末尾から読み直してるようにみえる。
行のサイズ = blockSizeのファイルに対して、
tail nを計算するのにO(n^2)の処理を行っているのでは?
0384デフォルトの名無しさん
2012/01/26(木) 22:05:50.63> 遅延評価とバッファの関係がよくわからないな。
>>374 のコードは今回の私の話とは全く関係ない
>>376 のストリームの話だ
逆順に指定行数を出力するという処理を「ストリームとして処理」するなら、
順に流入してきたデータを全て一時的にどこかに溜めて(バッファ)、
溜め終わってから、そこのデータの末尾から順に流出させる必要がある
そのバッファをどうやって作るか、どうやってデータの出し入れをするか、
ということが問題になるが、遅延評価を実現する仕組みのおかげで、
Haskell(の大抵の実装)ではそれを意識しなくてもできてしまう
上の方のレスで問題視された「ふつける」に載ってる方法だ
getContents 関数から流出した(リストで表現された)ストリームが
reverse 関数に流入してくる
遅延評価の仕組みにより、reverse 関数はリストの内容は評価しない
後で評価する可能性がある未評価のデータはメモリ内に残り続ける
この部分がストリームを逆順にたどるための「バッファ」の役割を果たしている
0385デフォルトの名無しさん
2012/01/26(木) 22:51:34.19おっしゃるとおり。
とりあえず、unsafe使わずに書けるかやってみただけで効率は良くない。
ついでに、ちょっと間違ってて10行以上取ってきます。
遅延IO使えばもっとシンプルに効率よく取ってこれるよ。
ちなみに、遅延評価とバッファは全く関係ない。
ファイルを逆から読むのにバッファは必要ない。
0386デフォルトの名無しさん
2012/01/26(木) 23:11:31.79> ちなみに、遅延評価とバッファは全く関係ない。
> ファイルを逆から読むのにバッファは必要ない。
ファイルを逆から読むのにバッファを必要としない方法もあることは分かっている
>>384 で私が言ったのは、「ストリームとして扱う場合はバッファを必要とする」
ということだ
ストリームというのは、パケット通信などのように、
ある塊のデータ群が一列に順に一つずつ流れる、あるいは流すこと
順に流入してきたものを逆順に流出させるには、バッファが絶対に必要だ
そのバッファの仕組みをプログラマが意識して自分で作る必要があるかどうかは別だが
確かに遅延評価とバッファに直接の関係はない
だが、上記の「ストリームの逆順流出」において
遅延評価を実現させる為の内部の仕組みがたまたまバッファの役割を果たす
もう一度言うが、あくまで >>376 のレスを受けて、
「内部処理もストリームとして扱う場合」の話をしている
(それが非効率的な事も分かっている)
0387デフォルトの名無しさん
2012/01/26(木) 23:42:32.23もしhGetContentsが遅延評価でなく先行評価だったとしたら、
その「ストリームの逆順流出」プログラムはどう変わるんだ?
どっちにしてもプログラムはhead n $ reverse $ ...
なんじゃないのか。
0388デフォルトの名無しさん
2012/01/27(金) 00:05:03.45> もしhGetContentsが遅延評価でなく先行評価だったとしたら、
> その「ストリームの逆順流出」プログラムはどう変わるんだ?
そんなことは知らん
先行評価だった場合にGHCが内部でどのような実装をしてくるのか俺には分からない
初めの >>380 では端折ったが、>>382 からはずっと、
遅延評価を実現する為に使われている内部の仕組みが、
ストリームとして流れてくるデータ順の逆転という処理において
バッファとして機能することだけを話しているんだが
ちなみに、この目的で内部の仕組みがバッファとして機能するのは、
hGetContents の処理ではなく reverse の処理をGHCが実行ファイルに埋め込む部分だ
0389デフォルトの名無しさん
2012/01/27(金) 00:07:50.19もう少しわかりやすく説明したほうがいいと思うよ。
0390デフォルトの名無しさん
2012/01/27(金) 00:20:31.26了解した、努力する
0391デフォルトの名無しさん
2012/01/27(金) 00:21:30.05一応、WHNF簡約やGHCのSTGマシンあたりの実装は理解してるつもり。
0392デフォルトの名無しさん
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>
どうかよろしくお願いします。
0393デフォルトの名無しさん
2012/01/27(金) 00:55:24.000394デフォルトの名無しさん
2012/01/27(金) 01:05:23.28Prelude> 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!"]
0395デフォルトの名無しさん
2012/01/27(金) 01:13:49.09あんまり難しい話じゃなくて、C言語とかでも、Seekなしで、
ファイルの先頭からシーケンシャルアクセスしかできないとしたら、
最後10行のデータ取ろうと思うと、どうしても直近10行はバッファ
しとかないといけないでしょ?
Haskellは、このバッファを意識しないでも、自動でやってくれる
って言ってるんだと思うよ。
遅延評価がバッファしてるわけじゃないけど、バッファしてるように
見えなくもない。
0396デフォルトの名無しさん
2012/01/27(金) 02:26:27.98設計外のことを無理にやらせれて破綻するんだお
0397デフォルトの名無しさん
2012/01/27(金) 02:49:49.780398デフォルトの名無しさん
2012/01/27(金) 03:01:28.89tail に 10 GB ていどのファイルを食わせても、5 秒もかからないんだよね。
これが分単位になるのなら考えてもいいけど、そうでなければ簡潔さの
ほうが大事だと思う。
“「効率」についてうんぬんする人々は、たいていの場合主として本番計算に
計算機資源がどのくらい使われるか、という点にばかり着目していて、コンパ
イルしたり、虫取りしたり、その他さまざまなやりそこないをしたりしながら
本番計算にそなえるために消費される人間の時間と計算機の時間を考えに入れ
ていないのである。” (ソフトウェア作法 p.132)
0399デフォルトの名無しさん
2012/01/27(金) 03:03:28.540400デフォルトの名無しさん
2012/01/27(金) 03:13:57.42いてみたことがあるけど、
* ファイルが改行で終わる場合と終わっていない場合を分ける
* バッファの先頭から行がはじまっているか、その前からつながっているかを分ける
とか、細かい場合分けがあって、予想したより面倒だった。
0401デフォルトの名無しさん
2012/01/27(金) 05:53:27.42正格評価でも、明示的にバッファ取らなくても、
パラメータ渡しをバッファ代わりにできますし…
0402デフォルトの名無しさん
2012/01/27(金) 05:56:04.14> これが分単位になるのなら考えてもいいけど、そうでなければ簡潔さの
> ほうが大事だと思う。
んなこたーない。
> “「効率」についてうんぬんする人々は、たいていの場合主として本番計算に
> 計算機資源がどのくらい使われるか、という点にばかり着目していて、コンパ
> イルしたり、虫取りしたり、その他さまざまなやりそこないをしたりしながら
> 本番計算にそなえるために消費される人間の時間と計算機の時間を考えに入れ
> ていないのである。” (ソフトウェア作法 p.132)
これは数回実行するだけの研究用プログラムについては正しいが、
UNIXのtailコマンドのように1度書かれたソースを莫大な回数実行する場合には
詰められる無駄は詰めたほうがいい。
0403デフォルトの名無しさん
2012/01/27(金) 06:59:03.58別にC言語でも数分で書けるから特にHaskellを使う利点はないよね
0404デフォルトの名無しさん
2012/01/27(金) 07:36:42.85同じ事を繰り返すが
私は正格評価の事については一言も触れいてない
正格評価ではバッファを意識する必要がある、
なんて私のレスが何処かに書いてあるか?
私は一貫して
・ストリームとして処理するならバッファが必要
・遅延評価を実現する仕組みがバッファとして機能している
この2点しか述べていない
「遅延評価とバッファの関係」を質問されたから、
正格評価の事まで話に絡める必要は無いだろ
別に遅延評価vs正格評価でどちらが有利か戦わせているわけではない
正格評価でも明示的にバッファ取らなくてもいい
と貴方が言うのなら、きっとそうなんだろ
それは私の話とはたぶん関係ないと思うから、
それがどうかしたのか、としか言いようがない
ちなみに、私の話とは別の事として訊くのだが、
> パラメータ渡しをバッファ代わりにする
それはパラメータでバッファを渡しているのではないか?
遅延評価を実現する仕組みでたまたま機能するバッファの方は、
バッファを作っているという意識すら感じずにプログラムできるが
「正格評価+ストリーミング処理+パラメータ渡し」
これでバッファを意識しなくてもいいプログラムを書いてみてくれ
ちょっと興味ある
0405デフォルトの名無しさん
2012/01/27(金) 07:46:54.830406デフォルトの名無しさん
2012/01/27(金) 07:49:56.57以下の部分で遅延評価とバッファの関係を簡単に述べている
どこの部分の詳細な説明を求めているのか具体的に言ってほしい
>>384
> 遅延評価の仕組みにより、reverse 関数はリストの内容は評価しない
> 後で評価する可能性がある未評価のデータはメモリ内に残り続ける
> この部分がストリームを逆順にたどるための「バッファ」の役割を果たしている
0407デフォルトの名無しさん
2012/01/27(金) 08:04:10.58そんなんだからアホ的非効率コードを書くんだよ
0408デフォルトの名無しさん
2012/01/27(金) 08:13:37.12正格評価、遅延評価とかはバッファと関係ないと思います。
というか、バッファされてる時点で評価済みで遅延してない、、、
正格でも遅延でもたぶん同じように書けます。
0409デフォルトの名無しさん
2012/01/27(金) 08:23:27.08これを「ふつうの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秒。
0410デフォルトの名無しさん
2012/01/27(金) 08:30:16.990411デフォルトの名無しさん
2012/01/27(金) 10:25:32.57それよりはunsafeでもIO [String]にしたいってことなのか
0412デフォルトの名無しさん
2012/01/27(金) 10:39:57.790413デフォルトの名無しさん
2012/01/27(金) 11:12:49.26いちいち先頭から1行ずつ読むとか糞遅かったら誰も使わんだろ
用途を満たさない物なんか設計してどうする
言語の作法なんて関係ない
0414デフォルトの名無しさん
2012/01/27(金) 11:16:44.14それは簡単じゃない?
Control.Concurrent の threadWaitRead で待って、サイズが変わってたら
その分を出力するだけでしょ。
0415デフォルトの名無しさん
2012/01/27(金) 11:32:02.970416デフォルトの名無しさん
2012/01/27(金) 12:06:04.37長年GNUがやってきたように、
過去の他人の成果を丸パクリして、
それでも使われるレベルになるのかどうか?
ということだよな
0417デフォルトの名無しさん
2012/01/27(金) 12:47:47.33という成果に期待しよう
0418デフォルトの名無しさん
2012/01/27(金) 14:20:57.31空読みするファイルが分散fs上に乗ってたら悲惨だなw
0419デフォルトの名無しさん
2012/01/27(金) 16:51:25.37仕事でHaskell使っている人が苦心の末発明したcondoitの使い方覚えろよ
0420デフォルトの名無しさん
2012/01/27(金) 17:07:01.500421デフォルトの名無しさん
2012/01/27(金) 17:09:06.720422デフォルトの名無しさん
2012/01/27(金) 18:37:45.13にコードが出てきたのがなんと言っても尊い。
0423デフォルトの名無しさん
2012/01/28(土) 11:33:31.74Template Haskell を少し勉強してみたところ、
やりたいことが実現できそうなことが分かりました
例えば次のように引数をコンパイル時に制限できるんですね
f :: Int -> ExpQ
f x | x < 0 = fail "error"
| otherwise = [| x |]
$(f (-1)) ====> error
$(f 3) ====> 3
このような事を値構築子でできるようにすれば良いわけですね
調べてみます
ありがとうございました
0424デフォルトの名無しさん
2012/01/29(日) 09:15:33.67リストの要素を入れ替えるswap関数は、pythonの方が簡潔なんだな・・・
リストを配列みたいに扱えない言語よりは優位なんだろうけど、そう言う言語と比較するときは配列と比較になるしなぁ・・・
0425デフォルトの名無しさん
2012/01/29(日) 09:30:41.60Data.Sequenceならupdateがあるので簡単
swap :: Int -> Int -> Seq a -> Seq a
swap i j s = update i (s `index` j) $ update j (s `index` i) s
0426デフォルトの名無しさん
2012/01/29(日) 09:37:27.18言いたいことは分かるけど、「具体的な処理」に関して、
処理後に同じ結果が得られる複数の言語間で「簡潔さを比較」する意味って何なの?
>>424 のリストの swap だって、一旦関数にしてしまえば、
あとは Haskell でも同じように簡潔に書けると思うんだが
(それがライブラリの大きな役割の一つだし)
>>424 のリンク先で考察している方法それ自体は面白いし興味あるけどね
0427デフォルトの名無しさん
2012/01/29(日) 09:44:58.64いろいろな具体的な(既知の)処理を簡潔に書ける言語があれば、
アプリケーション固有の(未知の)処理も簡潔に書ける可能性が高いからだろ
未知の処理だって、なんらかの既知の処理に似ていることが殆どだ
ということを加味すればなおさら
0428デフォルトの名無しさん
2012/01/29(日) 09:53:41.16言語の比較は、簡潔に書きやすいとかできるコードが速いとか、デバッグ
しやすいとかになるわ。ライブラリだって簡潔に書けるほうが充実させや
すいしな。
0429デフォルトの名無しさん
2012/01/29(日) 10:07:36.20「ハスケル最強」
ハスケルのほうが煩雑になってしまう時には
「そんな比較意味なくね?」
0430デフォルトの名無しさん
2012/01/29(日) 10:15:41.39それは、逆も同じだけどね。
ハスケルのほうが簡単に書ける時には
「そんなの意味なくね」
ハスケルのほうが煩雑になってしまう時には
「ハスケル使えねぇ」
用途考えずに比較なんて意味ないね。
0431デフォルトの名無しさん
2012/01/29(日) 10:35:32.33いや、だから一度関数になってしまえば、「簡潔さはほぼ同じ」になるわけでしょ
最初に比較して言語Aの方が簡潔だった、でも関数にしたから言語Bも同じなった
>>424 の言う「優位な言語」というのは、どの時点で比較したものなの?
仮に言語Bが関数化した結果、言語Aよりも簡潔になったら、言語間の優位さは逆転するの?
そういうことで逆転してしまうのなら、それはその「具体的な処理に関する」
簡潔さの言語間の比較とは言えないだろう
その具体的な処理に被せるインターフェースの部分のおかげで簡潔になったのだから
また、そんなことで逆転したとは言えないのなら、そもそも比較して
言語Aの方が優位だとか言うことの意義が見いだせない
私の経験上、実用的なアプリ内の数多ある個別具体的な処理に関して、
それらを最も得意とする言語(やパラダイム)は複数に分散する
ある特定の処理をするのに言語Aが優位だからという理由で、
そのアプリを作るのに言語Aを選ぶことは、実際のところ滅多にない
普通は自分やチームが得意としている言語であったり、
個別具体的な処理ではなく全体の求められる処理速度やメンテのしやすさなどで決定される
>>428
今の時代、広く使われている言語なら、どの言語でもライブラリは充実している
充実度の差の理由に言語の簡潔さが関わる割合は、比較して議論するほど高くはないと思うが
0432デフォルトの名無しさん
2012/01/29(日) 10:58:44.59(初めはファイルを分けるのが面倒に思えたから)
あるプログラムを実験するときは別のプログラムをコメントアウトしたりして。
なので、ファイルのトップには import が大量に書かれています。
実験が終わって、採用するプログラムを一つに絞ったので、
それを正式にちゃんとしたファイルに分けて保存したいのですが、
そのプログラムを実行するのにどの import が必要なのか、
ごちゃごちゃしてて分からなくなりました。
とりあえずそのプログラムだけ別ファイルに移してコンパイルしてみて、
モジュール不足の為にコンパイルエラーが出る度に
import を追加していけばいいとは思いますが・・・(以前も同じ様なことをしてた)
もっと簡単に、あるソースファイル内の識別子を評価するのに不足していて、
かつインストール済みであるライブラリのモジュールの一覧を見る方法はありませんか。
0433427
2012/01/29(日) 11:08:59.81俺は>>424じゃないけど、関数化の前の話をしているつもりだった
>また、そんなことで逆転したとは言えないのなら、そもそも比較して
>言語Aの方が優位だとか言うことの意義が見いだせない
>私の経験上、実用的なアプリ内の数多ある個別具体的な処理に関して、
>それらを最も得意とする言語(やパラダイム)は複数に分散する
もちろん。でも、実際的なアプリが色んな処理から成っているからこそ、
言語には極端な苦手分野がないほうが良いし、なるべく広範囲のコードを
簡潔に書けるのが良いということになる
たとえばランダムアクセス可能なデータ構造をすごく扱いにくい言語があったら、
その言語で書き易いアプリはかなり限定される
それから、アプリごとに多用される処理の傾向も違う
行列演算中心のアプリもあるし、DBアクセス中心のアプリもあるし、両方やるのもある
0434デフォルトの名無しさん
2012/01/29(日) 11:13:25.04全部のファイルに全部のimportをコピーして、とりあえずコンパイルを通す
コンパイルが通ったら-fwarn-unused-importsで不要なインポートを一掃
0435デフォルトの名無しさん
2012/01/29(日) 11:16:53.53長くて読む気しないな。
言語比較なんてナンセンスだと思うが。言語の優劣なんて個人個人で違うし。
関数化すれば0になるかもしれないけど、関数化するまでのコストは?
ライブラリになってないところの、作成コストは?
ライブラリの学習コストは?
ライブラリは十分充実してる?そしたら自分でプログラムなんて書かんわ。
0436デフォルトの名無しさん
2012/01/29(日) 11:30:01.60なるほど、逆でしたか
不要な import を省いていくんですね
ありがとうございました
0437デフォルトの名無しさん
2012/01/29(日) 12:41:36.12うーん、同じ処理の関数化の比較は、コードの長さとかだけじゃなく、関数化する際の概念とか手法とかがプログラマ・あるいは初心者に思いつきやすいか?とかの意味でも比較の意味はあると思う。
>>424のURL先ではpythonは配列的にも使えるリストのために、値の交換が得意な配列的な処理になってるけど、配列は配列。リストはリストとして扱う手続き型言語の場合、
1、リストの中身を配列に移す
2、配列で値を交換
3、配列の中身をリストに戻す
と言う処理になる
Haskellだと
>>424の9つの方法の内、初心者にも出来そうな一つ目と二つ目の方法は基本
1.リストを分割する
(iより前のリスト、i、iとjの間のリスト、j、jの後ろのリスト)
2.値bキした状態bフリストとして血牛しなおす
という処理になる
0438デフォルトの名無しさん
2012/01/29(日) 12:53:23.82> 1、リストの中身を配列に移す
> 2、配列で値を交換
> 3、配列の中身をリストに戻す
>
> と言う処理になる
そんな馬鹿なコードを書くのはプログラム初めて1ヶ月とかの初心者だけだろw
0439デフォルトの名無しさん
2012/01/29(日) 12:55:50.74え、確かにリストのままでも配列的に使えるけど、パフォーマンス的にはこちらは今でも有効だと思うけど・・・
0440デフォルトの名無しさん
2012/01/29(日) 13:03:38.330441デフォルトの名無しさん
2012/01/29(日) 13:05:40.34で、swapの実装という単位で比較した結果、言語Aの方が
関数化する際の概念とか手法とかがプログラマ・あるいは初心者に思いつきやすい
と結論づけられたとして、それからどうなるの?
それが何にどのように、どれくらい活かされる?
例えばHaskellという一言語においてリストをswapするいくつかの方法の中で、
簡潔さ、初心者の理解のしやすさ、計算速度、応用の幅・・・
などで互いに比較しすることの意義は分かる
時と場合によって使い分ける際の自分なりの基準になる
しかし、今存在している言語間で、swap処理などの
抽象度の低い低レベルレイヤーの処理の実装を比較して
優劣を考える意義がよく分からない
せいぜい新言語を作る際に、既存言語を分析する時ぐらいしか、
言語間で比較して優劣を考える意義はなくないか?
0442デフォルトの名無しさん
2012/01/29(日) 13:05:46.19じゃあ、どういう処理を1ヶ月以上たったらしてるの?
0443デフォルトの名無しさん
2012/01/29(日) 13:15:46.010444デフォルトの名無しさん
2012/01/29(日) 13:17:38.11リスト処理を解説する初心者レベルの入門書で
スワップ時にリストの中身を配列に移すなんて方法は、普通は教えない
普通は、双方向リスト・単方向リストの要素がリンクで結ばれていることをまず教える
もしスワップ処理を教えるなら当然その後になるが、
その際はリンクを繋ぎ替える処理で実装する方法を教えるだろう
処理速度云々ではなく、その方が初心者が「リスト処理を理解しやすい」からだ
初心者はリストの特徴を学ぶのが大事だからな
だから、一ヶ月と言わず、初めから配列に移すなんて方法は学ばない
0445デフォルトの名無しさん
2012/01/29(日) 13:23:20.30たった1回のswapのために配列にコピってswapしてリストを再構築するとか、アホだろ。
0446デフォルトの名無しさん
2012/01/29(日) 13:23:33.53今はサイト自体(と運営会社)が無くなっちゃったけど、Haskell入門以前という、プログラミング全くの初心者向けのブログ書いてたんだ
(そして、ネット上の友達(プログラミング未経験者)に読んでもらって、理解できるか確認しながら書いてた)
その関係で、PCがどうやって動いてるかも理解できてない人向けの言語を探してたり
そういう意味で、Haskellは割りと有効だとは思ってたんだけど、このswap関数でちょっと心が揺らいでたり
(変数の概念とかも数学から離れていないと言う意味で、数学+α程度の知識でプログラミングできる言語だと思う)
0447デフォルトの名無しさん
2012/01/29(日) 13:24:16.02Array=配列 ですが、何か
0448デフォルトの名無しさん
2012/01/29(日) 13:24:26.38■ このスレッドは過去ログ倉庫に格納されています