零客痩地 このページをアンテナに追加 RSSフィード Twitter

2009-10-03

Joel Spolskyの「試してみよう」をelispで解いてみた

結城浩さんのエントリーを見て、これはやらなくては!と思ったので解いてみました。これから解く人で答えがわかっちゃうのが嫌な人は見ないでくださいね。

リストの平方和を計算するsum-of-squaresを実装せよ - 結城浩のSICP日記 - sicp

試してみよう - The Joel on Software Translation Project

やったこと

まずは問題で使用する関数elispに書き直す。

(defun accumulate (combiner null-value l)
  (if (null l)
      null-value
    (funcall combiner (car l)
             (accumulate combiner
                         null-value
                         (cdr l)))))
=>accumulate

読んでみてこの関数の内容は分かったが、勘違いしていたら嫌なので、次はこの関数の試運転。

(defun test-of-accumulate (func l)
  (accumulate func nil l))
=>test-of-accumulate

(test-of-accumulate 'cons '(1 2 3))
=>(1 2 3)

OK、間違ってなかったようだ。次にいよいよ問題の関数を実装してみることにする。

(defun sum-of-squares (l)
  (apply '+ (accumulate (lambda (x y) (cons (* x x) y)) nil l)))
=>sum-of-squares

(sum-of-squares '(1 2 3 4 5))
=>55

うーん、なんとなくダメダメ感が漂うので実装し直し。

(defun sum-of-squares (l)
  (accumulate (lambda (x y) (+ (* x x) y)) 0 l))
=>sum-of-squares

(sum-of-squares '(1 2 3 4 5))
=>55

これで当たってるといいんだけど……。

やったー!当たったぞ!

反省

関数関数を渡すときやfuncallでの関数呼び出しで、バインド変数をクォートするのかしないのかでかなり引っ掛かった。

・lambdaを使って関数を生成して他の関数に渡す場合のインデントの付け方がよくわからない。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証