「Write Yourself a Scheme in 48 Hours」 を写経してみる(11) : Env の内容がみたい

「Write Yourself a Scheme in 48 Hours」 を写経してみる(9) : 変数の追加と割り当ての中で define, set!で変数が定義、変更される様子を覗きたかったのですが、IORef が入れ子になっていて簡単には覗けません。そこで、IORefの練習に表示する関数を作ってみました。

type Env = IORef [(String, IORef LispVal)] -- これが定義されている型

showEnv :: IORef [(String, IORef LispVal)] -> IO [(String, LispVal)]
showEnv envRef = readIORef envRef >>= flip readLS []
    where
        readLS :: [(String, IORef LispVal)] -> [(String, LispVal)] -> IO [(String, LispVal)]
        readLS []     out = return out
        readLS (x:xs) out = readTuple x >>= \tuple -> readLS xs (tuple:out)

        readTuple :: (String, IORef LispVal) -> IO (String, LispVal)
        readTuple tuple = readIORef (snd tuple)>>= \val -> return (fst tuple,val)

それではやってみます。

> env <- nullEnv   -- 変数を保存する環境を初期化

>  evalString env "(define x 3)" -- x に 3を定義
defineVar: "x" : Number 3
"Number 3"

>  evalString env "(define y 99)"
defineVar: "y" : Number 99
"Number 99"

> showEnv env
[("x",Number 3),("y",Number 99)]  -- 変数を表示してみる。

>  evalString env "(set! y 0)"
setVar: "y" : Number 0
"Number 0"

> showEnv env
[("x",Number 3),("y",Number 0)]

>  evalString env "(define list '(a 2 3))"
defineVar: "list" : List [Atom "a",Number 2,Number 3]
"List [Atom \"a\",Number 2,Number 3]"

> showEnv env
[("x",Number 3),("y",Number 0),("list",List [Atom "a",Number 2,Number 3])]

日本語版「48時間でSchemeを書こう」がありました・・・。良く見ろよ→オレ。