Shammer's Philosophy

My private adversaria

関数を生成するマクロ・その4

関数を生成するマクロ・その3 - Shammerismでは、関数名を直接渡していたが、似たような名前の関数を定義したいときには関数名のうちの違う部分だけを渡せばよいようにしたい。と、いうわけでそのための実装を考えた。ベースは関数を生成するマクロ・その3 - Shammerismのコードで、文字列から関数名を定義し、それを intern するというようにしてみた。

? (defparameter *public-symbol* nil)
*PUBLIC-SYMBOL*
? (defmacro public-symbol (s)
    `(push ',s *public-symbol*))
PUBLIC-SYMBOL
? (defun get-public-symbol () *public-symbol*)
GET-PUBLIC-SYMBOL
? (defun export-public-symbol ()
    (export *public-symbol*)
    (setf *public-symbol* nil))
EXPORT-PUBLIC-SYMBOL
? (unintern *public-symbol*)
NIL
? (defmacro generate-semaphore-getter (name)
    `(let ((semaphore (make-semaphore)))
       (defun ,(intern (string-upcase (concatenate 'string "get-semaphore-for-" name))) () semaphore)
       (public-symbol ,(intern (string-upcase (concatenate 'string "get-semaphore-for-" name))))
       (export-public-symbol)))
GENERATE-SEMAPHORE-GETTER
? (generate-semaphore-getter "test")
NIL
? (get-semaphore-for-test)
#<SEMAPHORE #x30200107503D>
? (get-semaphore-for-test)
#<SEMAPHORE #x30200107503D>
? 

どうやらうまく動作したっぽい。ただ、(string-upcase (concatenate 'string "get-semaphore-for-" name))は冗長なのでなんとかできないかと思ったが・・・これを let の変数に割り当てるとうまく動作させることができなかった。何がいけないのだろうか。目的の動作は実現できたものの課題は残った状態だ。