ついに、Write Yourself a Scheme in 48 Hoursをやりました。
分ったこと
以下のことが、なんとなく分ったり、少なくともどう使うのかを体験できました。
コードの問題点
ファイルとして置いてあるコードですが、以下のような小さな問題があります。
- 2箇所Texのコマンドが残っている
parseString = do char ;\textcolor{string}{\texttt{'"'}};
- cdr の定義が間違っている
cdr [DottedList (_ : xs) x] = return $ DottedList xs x cdr [DottedList [xs] x] = return x
は誤りで、正しくはこう。
cdr [DottedList [xs] x] = return x cdr [DottedList (_ : xs) x] = return $ DottedList xs x
でも、こう書く方が、もっと分りやすいと思います。
cdr [DottedList [_] x] = return x cdr [DottedList (_ : xs) x] = return $ DottedList xs x
- Haskell 98 にない forall が使われている
ghci を使う場合は、ファイルの先頭に以下を入れるといいです。
{-# LANGUAGE ExistentialQuantification #-}
独自拡張
大域の環境とクロージャの環境を表示する Scheme の関数を作ってみました。それぞれ、(show) と (closure "関数名") です。
eval env (List [Atom "show"]) = do pairs <- liftIO $ readIORef env return $ String $ unwords $ map fst pairs eval env (List [Atom "closure", String name]) = do func <- getVar env name pairs <- liftIO $ readIORef $ closure func return $ String $ unwords $ map fst pairs
以下のようにクロージャを作って、
(define acm (lambda (n) (lambda (m) (+ n m)))) (define plus1 (acm 1))
以下のようにクロージャの環境を表示してみると
(closure "plus1")
n が積まれていることが分ります。