Haskellをまたちょっと書いてブチ切れ
昨日のことなんだが...
Haskellは難しすぎる.いや違うな,難しいんじゃなくて使い辛い.所詮は型理論の実証実験で,実用的なソフトウェアをそれで書いて経済活動するようなものではないと思った.サーバ・サイドならまだしも,パッケージで配るクライアント・アプリでは特にね.
まず数時間悩んだのは
- cmd.exe を立ち上げる
- その cmd.exe に vcvars32.bat を call させる
- その cmd.exe に
echo %PATH%
を実行させることで,2.で設定された%PATH%
の値を読み取る - 読み取った値を
;
で分割してディレクトリの列を得る - 列の中で cl.exe を含む最初のディレクトリを返す
というプログラム.System.Directory.doesFileExist
がIOアクションなのでめんどい.まぁ確かに,まさにIOのアクションなんだけど,ディレクトリ構造を読むってフィーリング的には純関数的なlookupなんだよね... あと大抵の関数型言語って map を使えって口うるさいけど,ループを途中で抜ける系とは本質的に相性悪いんだよな(本来の言葉の意味に立ち返れば,それって "map" じゃないし).Monadと遅延評価でイディオムがあったように思うが,foldとMaybeで誤魔化してしまった.
とりあえず %PATH%
の値が手に入ってから後はこんな感じで一応実現できた:
import Control.Monad as CM import System.Directory as SD import System.FilePath as SF findExe :: String -> String -> IO (Maybe String) findExe exeName pathEnvVarVal = CM.foldM (\mb -> \dir -> case mb of Just _ -> return mb Nothing -> do exist <- SD.doesFileExist $ dir `SF.combine` exeName if exist then return $ Just dir else return Nothing ) Nothing (SF.splitSearchPath pathEnvVarVal)
(注意: ブラウザ上で手編集してるのでコンパイル通らないかも)
とりあえずIOアクションの do では,C互換の for, while, do-while を用意してくれないかな... 全てモナドで統一的に! とか気張らなくていいからさ.
cmd.exe とのやりとりは popen(2)
的な System.Cmd.runInteractiveProcess
で可能.
- id:sirocco:20090527:1243393335 Haskell から Ruby を呼ぶ - sirocco の書いてもすぐに忘れるメモ
System.IO.hGetContents
って何? という話なんだが.リファレンスを読んでもいまいちピンと来ない.POSIXの言葉で説明してくれないと分からないよ...
100行以上のプログラムをHaskellで書こうとなるとインデントルールがウザすぎる... *1 Pythonは改行位置を強制的に定めているからまだインデントしやすいんだよな.do 大先生を始めとして if-then-else とか case-of とか,みんなどうしてるんだ? とにかく,自由形式の言語が最高だよ.Lispとかね.
さて現在,実行ファイルのフルパスをどう取得すればよいかで悩んでいる.Cで言う argv[0]
はググったら方法が見つかったんだけど.
- http://hackage.haskell.org/trac/ghc/ticket/3199 #3199 (System.Environment provides no access to argv[0]) – GHC
Cレベルでは以下のように(可搬性はないが)多くのプラットフォームで解が見いだされている.
追記: popen
はCランタイムの関数だった... (syscall すなわち (2) でなく (3) ) 死にたい...
*1:See also id:camlspotter:20100521:1274446264