BeforeLISPs
Just Part of the Past
〜 #8 Rindoh 〜
Motivation 1
beginner
(defun stride-mapcar (stride fn lst) (labels ((rec (lst acc) (if (<= stride (length lst)) (rec (drop lst stride) (cons (funcall fn (car lst)) acc)) (nreverse acc)))) (rec lst nil)))
Motivation 1
beginner
(stride-mapcar 2 #'symbol-name '(alpha a beta b)); => (“ALPHA” “BETA”)
(defun stride-mapcar (stride fn lst) (labels ((rec (lst acc) (if (<= stride (length lst)) (rec (drop lst stride) (cons (funcall fn (car lst)) acc)) (nreverse acc)))) (rec lst nil)))
Motivation 1
beginner
(defun stride-mapcar (stride fn lst) (labels ((rec (lst acc) (if (<= stride (length lst)) (rec (drop lst stride) (cons (funcall fn (car lst)) acc)) (nreverse acc)))) (rec lst nil)))
Motivation 1
beginner
(defun stride-mapcar (stride fn lst) (labels ((rec (lst acc) (if (nth (1- stride) lst) (rec (drop lst stride) (cons (funcall fn (car lst)) acc)) (nreverse acc)))) (rec lst nil)))
Motivation 1
beginner
(defun stride-mapcar (stride fn lst) (labels ((rec (lst acc) (if (nth (1- stride) lst) (rec (drop lst stride) (cons (funcall fn (car lst)) acc)) (nreverse acc)))) (rec lst nil)))
(stride-mapcar 2 #'symbol-name '(alpha a beta b)); => (“ALPHA” “BETA”)
Motivation 1● たまに短い値が返ってくる● とりあえず以前の定義で同じ値を返すのかが知りたい
– 同じ値を返すなら、アルゴリズムを見直す
– 違う値を返すなら、書き換えるときに無茶な仮定をしていないか見直す
● 関数定義を一時的に前の定義に戻して使う構文が欲しい– 呼び出し連鎖の中から値を取り出すのは面倒なので、レキシカルではなく大域的に(with-version ((stride-mapcar 0)) (foo ...)) ; FOO indirectly uses STRIDE-MAPCAR
beginner
Motivation 1● たまに短い値が返ってくる● とりあえず以前の定義で同じ値を返すのかが知りたい
– 同じ値を返すなら、アルゴリズムを見直す
– 違う値を返すなら、書き換えるときに無茶な仮定をしていないか見直す
● 関数定義を一時的に前の定義に戻して使う構文が欲しい– 呼び出し連鎖の中から値を取り出すのは面倒なので、レキシカルではなく大域的に(with-version ((stride-mapcar 0)) (foo ...)) ; FOO indirectly uses STRIDE-MAPCAR
beginner
Motivation 1● たまに短い値が返ってくる● とりあえず以前の定義で同じ値を返すのかが知りたい
– 同じ値を返すなら、アルゴリズムを見直す
– 違う値を返すなら、書き換えるときに無茶な仮定をしていないか見直す
● 関数定義を一時的に前の定義に戻して使う構文が欲しい– 呼び出し連鎖の中から値を取り出すのは面倒なので、レキシカルではなく大域的に(with-version ((stride-mapcar 0)) (foo ...)) ; FOO indirectly uses STRIDE-MAPCAR
beginner
Motivation 1● たまに短い値が返ってくる● とりあえず以前の定義で同じ値を返すのかが知りたい
– 同じ値を返すなら、アルゴリズムを見直す
– 違う値を返すなら、書き換えるときに無茶な仮定をしていないか見直す
● 関数定義を一時的に前の定義に戻して使う構文が欲しい– 呼び出し連鎖の中から値を取り出すのは面倒なので、レキシカルではなく大域的に(with-version ((stride-mapcar 0)) (foo ...)) ; FOO indirectly uses STRIDE-MAPCAR
beginner
Motivation 1● たまに短い値が返ってくる● とりあえず以前の定義で同じ値を返すのかが知りたい
– 同じ値を返すなら、アルゴリズムを見直す
– 違う値を返すなら、書き換えるときに無茶な仮定をしていないか見直す
● 関数定義を一時的に前の定義に戻して使いたい – 呼び出し連鎖の中から値を取り出すのは面倒なので、レキシカルではなく大域的に(with-version ((stride-mapcar 0)) (foo ...)) ; FOO indirectly uses STRIDE-MAPCAR
beginner
Motivation 2
fledgling
Motivation 2
fledgling
Motivation 2
fledgling
● 定義を修正した時には既に期待していた答えを忘れている– ユニットテスト書く?
– 引数と返り値を全部保存しといたらいいんじゃ...
Motivation 2
fledgling
● 定義を修正した時には既に期待していた答えを忘れている– ユニットテスト書く?
– 引数と返り値を全部保存しといたらいいんじゃ...
Motivation 2
fledgling
● 定義を修正した時には既に期待していた答えを忘れている– ユニットテスト書く?
– 引数と返り値を全部保存しといたらいいんじゃ...
Motivation 1
fledgling
beginner
関数定義に細工して定義を保存する
Motivation 2
fledgling
beginner
関数定義に細工して実行時に
引数列と返り値を保存する
Motivation 1&2
関数定義に細工する
fledglingnovice
RINDOH:VDEFUN● vdefun name lambda-list form* => name● DEFUNフォームが保存される
● 適用のたびに引数とその評価結果が保存される
● VDEFUNフォームを評価すると、テストを実施する
● テストケース全てをパスしないと定義を更新できない
beginner
RINDOH:VDEFUN● vdefun name lambda-list form* => name● DEFUNフォームが保存される
● 適用のたびに引数とその評価結果が保存される
● VDEFUNフォームを評価すると、テストを実施する
● テストケース全てをパスしないと定義を更新できない
fledgling
RINDOH:VDEFUN● vdefun name lambda-list form* => name● DEFUNフォームが保存される
● 適用のたびに引数とその評価結果が保存される
● VDEFUNフォームを評価すると、テストを実施する
● テストケース全てをパスしないと定義を更新できない
fledgling
RINDOH:VDEFUN● vdefun name lambda-list form* => name● DEFUNフォームが保存される
● 適用のたびに引数とその評価結果が保存される
● VDEFUNフォームを評価すると、テストを実施する
● テストケース全てをパスしないと定義を更新できない
fledglingbeginner
RINDOH:WITH-VERSION● with-version (version-spec*) form* => result
● 指定されたバージョンの関数を使ってformを評価する
(with-version ((iota 3) (stride-mapcar 1)) (stride-mapcar 2 #'twice (iota 10)))
beginner
その他● WITH-RAW-FN● DEFINE-TEST-FORM, DEFINE-TEST-CASE
● RUN-TEST● STDIFF
– 意外と見辛い
● 版管理?
課題● 関数定義構文を囲むレキシカル環境が見えない
– (let ((counter -1)) (vdefun gen-id () (incf counter)))
● 呼び出しフォームを捕まえるために&RESTパラメータを強制して
いる
– (vdefun iota (n &optional (start 0)) ...)=> (defun iota (&rest params) ...)
● テストや定義をファイルに保存する形式
– VDEFUNフォーム vs エントリ (MAKE-LOAD-FORM)
課題● 関数定義構文を囲むレキシカル環境が見えない
– (let ((counter -1)) (vdefun gen-id () (incf counter)))
● 呼び出しフォームを捕まえるために&RESTパラメータを強制して
いる
– (vdefun iota (n &optional (start 0)) ...)=> (defun iota (&rest params) ...)
● テストや定義をファイルに保存する形式
– VDEFUNフォーム vs エントリ (MAKE-LOAD-FORM)
課題● 関数定義構文を囲むレキシカル環境が見えない
– (let ((counter -1)) (vdefun gen-id () (incf counter)))
● 呼び出しフォームを捕まえるために&RESTパラメータを強制して
いる
– (vdefun iota (n &optional (start 0)) ...)=> (defun iota (&rest params) ...)
● テストや定義をファイルに保存する形式
– VDEFUNフォーム vs エントリ (MAKE-LOAD-FORM)