Common Lisp:在不使用 &rest 参数的情况下高效地处理提供的 p 参数
Common Lisp: Efficiently handling supplied-p-parameter efficiently without using &rest arguments
假设我有函数
(defun bar (a &optional (b nil bp))
(declare (ignore a b bp)) ; <-- replace it with (list a b bp)
; to check for correctness
)
;; I want to preserve the value of bp here inside bar, and inside foo below
我想围绕 bar
写一个包装器:
(defun foo (a &optional (b nil bp))
(declare (optimize speed))
(apply #'bar a (nconc (when bp (list b)))))
同时在从 foo
到 bar
的调用中保留 bp
的值,并使参数 b
在 emacs 的迷你缓冲区/eldoc 中可见模式。我想知道在这个调用中是否有一种可能不可移植的非强制性方法来保留 bp
的值。
例如,
CL-USER> (time (loop repeat 1000000 do (foo 4 2)))
Evaluation took:
0.040 seconds of real time
0.043656 seconds of total run time (0.043656 user, 0.000000 system)
110.00% CPU
96,380,086 processor cycles
15,990,784 bytes consed <--- plenty of consing
NIL
如果我忽略 b
-visibility-in-eldoc,我可能会使用 &rest
参数,但我确实希望参数可见。
虽然在这种特殊情况下还有其他方法可以实现这一点,但我确实想考虑存在多个 &optional(或 &keyword)参数的情况。
我不确定 bar
和 foo
实际上应该做什么,但是:
(defun foo (a &optional (b nil bp))
(declare (optimize speed))
(funcall #'bar a (when bp b)))
CL-USER> (time (loop repeat 1000000 do (foo 4 2)))
Evaluation took:
0.005 seconds of real time
0.005810 seconds of total run time (0.005804 user, 0.000006 system)
120.00% CPU
8,099,624 processor cycles
0 bytes consed
使用 cond
表格来决定如何调用 bar
:
(defun bar (a &optional (b nil bp) (c nil cp))
(declare (ignore a b bp c cp)))
(defun foo (a &optional (b nil bp) (c nil cp))
(declare (optimize speed))
(cond (cp (funcall #'bar a b c))
(bp (funcall #'bar a b))
(t (funcall #'bar a))))
CL-USER> (time (loop repeat 1000000 do (foo 1 2 3)))
Evaluation took:
0.015 seconds of real time
0.017203 seconds of total run time (0.017148 user, 0.000055 system)
113.33% CPU
41,186,554 processor cycles
0 bytes consed
检查传递给 bar
的参数:
(defun bar (a &optional (b nil bp) (c nil cp))
(list a b bp c cp))
CL-USER> (foo 1 2 3)
(1 2 T 3 T)
CL-USER> (foo 1 2)
(1 2 T NIL NIL)
CL-USER> (foo 1)
(1 NIL NIL NIL NIL)
假设我有函数
(defun bar (a &optional (b nil bp))
(declare (ignore a b bp)) ; <-- replace it with (list a b bp)
; to check for correctness
)
;; I want to preserve the value of bp here inside bar, and inside foo below
我想围绕 bar
写一个包装器:
(defun foo (a &optional (b nil bp))
(declare (optimize speed))
(apply #'bar a (nconc (when bp (list b)))))
同时在从 foo
到 bar
的调用中保留 bp
的值,并使参数 b
在 emacs 的迷你缓冲区/eldoc 中可见模式。我想知道在这个调用中是否有一种可能不可移植的非强制性方法来保留 bp
的值。
例如,
CL-USER> (time (loop repeat 1000000 do (foo 4 2)))
Evaluation took:
0.040 seconds of real time
0.043656 seconds of total run time (0.043656 user, 0.000000 system)
110.00% CPU
96,380,086 processor cycles
15,990,784 bytes consed <--- plenty of consing
NIL
如果我忽略 b
-visibility-in-eldoc,我可能会使用 &rest
参数,但我确实希望参数可见。
虽然在这种特殊情况下还有其他方法可以实现这一点,但我确实想考虑存在多个 &optional(或 &keyword)参数的情况。
我不确定 bar
和 foo
实际上应该做什么,但是:
(defun foo (a &optional (b nil bp))
(declare (optimize speed))
(funcall #'bar a (when bp b)))
CL-USER> (time (loop repeat 1000000 do (foo 4 2)))
Evaluation took:
0.005 seconds of real time
0.005810 seconds of total run time (0.005804 user, 0.000006 system)
120.00% CPU
8,099,624 processor cycles
0 bytes consed
使用 cond
表格来决定如何调用 bar
:
(defun bar (a &optional (b nil bp) (c nil cp))
(declare (ignore a b bp c cp)))
(defun foo (a &optional (b nil bp) (c nil cp))
(declare (optimize speed))
(cond (cp (funcall #'bar a b c))
(bp (funcall #'bar a b))
(t (funcall #'bar a))))
CL-USER> (time (loop repeat 1000000 do (foo 1 2 3)))
Evaluation took:
0.015 seconds of real time
0.017203 seconds of total run time (0.017148 user, 0.000055 system)
113.33% CPU
41,186,554 processor cycles
0 bytes consed
检查传递给 bar
的参数:
(defun bar (a &optional (b nil bp) (c nil cp))
(list a b bp c cp))
CL-USER> (foo 1 2 3)
(1 2 T 3 T)
CL-USER> (foo 1 2)
(1 2 T NIL NIL)
CL-USER> (foo 1)
(1 NIL NIL NIL NIL)