Seriesを引数に取ってSeriesを返す関数 — #:g1

Posted 2010-11-02 14:10:00 GMT

前回のエイリアスを作ってみた時の

(COLLECT-SUM (EVECTOR #(1 2 3 4)))
Non-series to series data flow from:
(EVECTOR #(1 2 3 4))
のような警告は、どうも最適化の指定が無かったためのようです。
Seriesを引数に取ってSeriesを返す関数は、
(DECLARE (OPTIMIZABLE-SERIES-FUNCTION))
のように指定してあげると最適化指定時には最適化される様子。
OPTIMIZABLE-SERIES-FUNCTIONには整数が指定できて、多値で返すSeriesの個数を指定します(デフォルトは1で省略可能)
この指定をして
(in-package :series)

(defun Rsum (Z) (declare (optimizable-series-function)) (collect-sum Z))

(defun Evector (vector) (declare (optimizable-series-function)) (scan 'vector vector))

と定義したところ
(funcall #'Rsum (Evector #(1 2 3 4)))
;⇒ 10
のようにしても警告は出なくなりました。
そして、この式をマクロ展開すると、
(funcall #'Rsum (Evector #(1 2 3 4)))
;⇒
(CL:LET* (#:ELEMENTS-5
          (#:LIMIT-3 (ARRAY-TOTAL-SIZE #(1 2 3 4)))
          (#:INDEX-2 -1)
          (#:SUM-0 0))
  (DECLARE (TYPE VECTOR-INDEX+ #:LIMIT-3)
           (TYPE -VECTOR-INDEX+ #:INDEX-2)
           (TYPE NUMBER #:SUM-0))
  (TAGBODY
    #:LL-8
    (INCF #:INDEX-2)
    (LOCALLY
        (DECLARE (TYPE VECTOR-INDEX+ #:INDEX-2))
      (IF (= #:INDEX-2 #:LIMIT-3)
          (GO END))
      (SETQ #:ELEMENTS-5
            (ROW-MAJOR-AREF #(1 2 3 4) (THE VECTOR-INDEX #:INDEX-2))))
    (SETQ #:SUM-0 (+ #:SUM-0 #:ELEMENTS-5))
    (GO #:LL-8)
    END)
  #:SUM-0)
となります。
なんでFUNCALLがマクロ展開されるのか、DEFUNで定義した筈のRsumもマクロ等々、色々突っ込みどころは多いですが、とりあえずSeriesを入出力する関数(マクロ)はOPTIMIZABLE-SERIES-FUNCTIONの指定が大事らしいということは分かりました。
また、Series系関数/マクロを定義する場合、関数が良いのかマクロが良いのか悩むこともありましたが、これで悩みも解消(勝手にマクロになってるので…)

comments powered by Disqus