Misalkan saya memiliki fungsi

(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

Dan saya ingin menulis pembungkus bar:

(defun foo (a &optional (b nil bp))
  (declare (optimize speed))
  (apply #'bar a (nconc (when bp (list b)))))

Sambil mempertahankan nilai bp dalam panggilan dari foo ke bar, dan juga menjaga argumen b terlihat di minibuffer / eldoc-mode emacs. Saya ingin tahu apakah ada kemungkinan non-portable non-consing cara untuk mempertahankan nilai bp dalam panggilan ini.

Sebagai contoh,

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

Jika saya mengabaikan b-visibility-in-eldoc, saya mungkin dapat menggunakan argumen &rest, tetapi saya ingin argumen tersebut terlihat.

Meskipun ada cara lain untuk mencapai ini dalam kasus khusus ini, saya ingin mempertimbangkan kasus ketika ada beberapa argumen &opsional (atau &kata kunci).

0
digikar 4 April 2021, 20:21

2 jawaban

Jawaban Terbaik

Gunakan formulir cond untuk memutuskan cara memanggil 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

Memeriksa argumen yang diteruskan ke 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)
3
ad absurdum 4 April 2021, 20:15

Saya tidak yakin apa yang seharusnya dilakukan bar dan foo, tetapi bagaimana dengan:

(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
-1
Martin Buchmann 4 April 2021, 18:52