CLでSRFI-39 — #:g1

Posted 2011-12-29 14:44:00 GMT

CLでSRFI、今回は、SRFI-39の「Parameter objects」です。
Parameter objectsとはCLでいうスペシャル変数のようなダイナミックな変数を実現するオブジェクトでSRFI 39では、Parameter objectを作るmake-parameterと、let的な束縛構文のparameterizeが用意されています。

動作

(let ((radix (make-parameter 10)))

(defun f (n) (format nil "~VR" (funcall radix) n))

(list (f 10) (parameterize ((radix 8)) (f 10)) (parameterize ((radix 2)) (f 10)))) ;=> ("10" "12" "1010")

移植について

通常のスペシャル変数と比べて速度的にはどんな感じになるのかなと思ったので、takのスペシャル変数版であるstakと、parameter版のptakを作って比べてみました。
(defvar stak-x)
(defvar stak-y)
(defvar stak-z)
(proclaim '(fixnum stak-x stak-y stak-z))

(defun stak (stak-x stak-y stak-z) (stak-aux))

(defun stak-aux () (if (not (< stak-y stak-x)) stak-z (let ((stak-x (let ((stak-x (the fixnum (1- stak-x))) (stak-y stak-y) (stak-z stak-z)) (stak-aux))) (stak-y (let ((stak-x (the fixnum (1- stak-y))) (stak-y stak-z) (stak-z stak-x)) (stak-aux))) (stak-z (let ((stak-x (the fixnum (1- stak-z))) (stak-y stak-x) (stak-z stak-y)) (stak-aux)))) (stak-aux))))

(stak 24 16 8)
;⇒ 9
----------
Evaluation took:
  0.101 seconds of real time
  0.100007 seconds of total run time (0.100007 user, 0.000000 system)
  99.01% CPU
  241,744,959 processor cycles
  0 bytes consed

Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz


(let ((ptak-x (make-parameter 0))
      (ptak-y (make-parameter 0))
      (ptak-z (make-parameter 0)) )

(defun ptak (x y z) (declare (optimize (safety 0) (speed 3) (debug 0))) (parameterize ((ptak-x x) (ptak-y y) (ptak-z z) ) (ptak-aux) ))

(defun ptak-aux () (declare (optimize (safety 0) (speed 3) (debug 0)) (function ptak-x ptak-y ptak-z) ) (flet ((ptak-x () (the fixnum (funcall ptak-x))) (ptak-y () (the fixnum (funcall ptak-y))) (ptak-z () (the fixnum (funcall ptak-z))) ) (declare (inline ptak-x ptak-y ptak-z)) (if (not (< (ptak-y) (ptak-x))) (ptak-z) (parameterize ((ptak-x (parameterize ((ptak-x (the fixnum (1- (ptak-x)))) (ptak-y (ptak-y)) (ptak-z (ptak-z)) ) (ptak-aux) )) (ptak-y (parameterize ((ptak-x (the fixnum (1- (ptak-y)))) (ptak-y (ptak-z)) (ptak-z (ptak-x)) ) (ptak-aux) )) (ptak-z (parameterize ((ptak-x (the fixnum (1- (ptak-z)))) (ptak-y (ptak-x)) (ptak-z (ptak-y)) ) (ptak-aux) ))) (ptak-aux) )))))

(ptak 24 16 8)
;⇒ 9
----------
Evaluation took:
  2.387 seconds of real time
  2.368149 seconds of total run time (2.348147 user, 0.020002 system)
  [ Run times consist of 0.428 seconds GC time, and 1.941 seconds non-GC time. ]
  99.20% CPU
  5,714,999,793 processor cycles
  1,156,928,608 bytes consed

Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz

最適化のされ具合からしてptakには不利でそれ程チューニングもされていないので、ぼんやりとした目安という感じですが、ptakは20倍程度の遅さになりました。

comments powered by Disqus