C.I.CLを眺める(13) MEMQ — #:g1

Posted 2011-04-23 13:29:00 GMT

今回は、C.I.CLのlist.lispから MEMQ です。
MEMQ は CLより前のMacLISPには標準で存在していたものですが、CLでは、比較関数(:TEST)が別に取れるようになったため、比較関数ごとに特化したものはなくなりMEMBER一つとなりました。
それでも、EQに特化したMEMQは割と愛用されているようで、大抵の処理系では内部や拡張パッケージにはMEMQが存在しているようです。
ということで定義は

(DEFUN MEMQ (ITEM LIST)
  "
RETURN:   (MEMBER ITEM LIST :TEST (FUNCTION EQ))
"
  (MEMBER ITEM LIST :TEST (FUNCTION EQ)))
となっています。たまに#'ではなくFUNCTIONと書くのが、Bourguignon氏の特徴ですが何故なのかは謎。
動作は、
(import 'com.informatimago.common-lisp.list:memq)

(memq :bar '(foo :bar baz)) ;=> (:BAR BAZ)

自作する際に注意したいのが最適化の指定ですが、C.I.CLでも
(DECLAIM (INLINE PLIST-PUT PLIST-GET PLIST-REMOVE MEMQ))
のようにインライン展開の指定があります。これがないと
- memq (inline指定なし)
(dotimes (i 100000000)
  (memq :bar '(foo :bar baz)))
;⇒ NIL
----------
Evaluation took:
  0.961 seconds of real time
  0.960000 seconds of total run time (0.960000 user, 0.000000 system)
  99.90% CPU
  2,300,195,133 processor cycles
  0 bytes consed

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

- member
(dotimes (i 100000000)
  (member :bar '(foo :bar baz)))
;⇒ NIL
----------
Evaluation took:
  0.044 seconds of real time
  0.040000 seconds of total run time (0.040000 user, 0.000000 system)
  90.91% CPU
  104,561,685 processor cycles
  0 bytes consed

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

のように大幅に逆効果になってしまうこともあるようなので注意が必要かもしれません。

comments powered by Disqus