内部defineの振る舞い (2)

id:jun0さんがtoplevel defineの問題を指摘してくれた。なるほど。これを読んで色々考えてはみたが、SICPの"原理"を達成する為には結局solverを実装しないと駄目な気がするなぁ。実用に耐えうる言語になる為に理想を捨てた暗黒の部分を垣間見た気がする。

しかし何かひっかかる。なんだろうこの気持ち悪い感じ。

ところで他の言語ではどうなってるんだろうという事で、"purely functional"なHaskellで試してみる。

ubuntu% cat test.hs 
b = a + 10
a = 5

f :: Int -> Int
f x = a + b
      where b = a + x
            a = 5

f2 = x
     where x = y + 5
           y = 3 * x + 1

main :: IO ()
main = do putStrLn ("b    = " ++ (show b))
          putStrLn ("f 10 = " ++ (show (f 10)))
          putStrLn ("f2   = " ++ (show f2))
ubuntu% ghc test.hs
ubuntu% ./a.out 
b    = 15
f 10 = 20
a.out: <<loop>>

Haskellではtop level environmentにおいて同じ名前を宣言する事は出来ない。これでtop level environmentにおける宣言の順序依存を無くしているように見える。しかしHaskellだとinteractive shell上でa = 1とか出来ないんではなかろうかと思いghciを起動してみた所、実際出来なかった。ソースコードがfixされた状態でないと評価出来ないという事は、コードをdynamicに変化させる事が出来ないという事にも繋がる。ちゅう事はHaskellにおいてマクロ相当の機能を実装する事は不可能なのか?

ghcのwhere文はdependency resolutionをしている。流石に循環参照は解いてくれない訳だが、面白いのは循環参照のエラーがコンパイル時ではなくループ時に起こっている点である。コンパイル時にエラーを出しても良さそうなモノだが、何故実行時エラーにするんだろうか...。うーん...。