gpt4 book ai didi

common-lisp - 如何定义一个 &key 参数来取代 Lisp 中的 &optional 参数

转载 作者:行者123 更新时间:2023-12-04 03:06:28 26 4
gpt4 key购买 nike

我刚开始写这个函数,我想知道是否有办法,如果只输入 &key 参数, &optional 列表可以被忽略。

(defun test (&optional arg (i 0) &key (size s))
...)

我希望能够运行
(test arg)

或者
(test arg i)

但是也
(test :size)

现在这是一个更好的模型,但我不知道将 :size 放在参数列表中的位置
    (defun test (&optional arg (i 0))
(cond ((eq arg nil) (return-from test (test-1)))
((listp arg)
(return-from test (test-2 arg)))
((pointerp arg) (mem-aref (test-3 arg) :int i))
(:size (size-test arg))
(t nil)))

so i can run (test) and get:

<output of (test-1)>


I can run (test '(1 2 3)) and get:


<output of (test-2 arg)>


I can run (test <pointer> 0)

and output is:

<output of (mem-aref (test-3 arg) :int i)>

I can run (test :size) and get:

<output of (test-size arg)>

最佳答案

混合可选参数和关键字参数

混合可选参数和关键字参数仍然不是那么容易做到的。如果函数接受可选参数,则除非还提供了可选参数,否则您将无法使用关键字参数。否则,第一个关键字将被解释为可选参数,依此类推。例如,请参阅此堆栈溢出问题: How can I have optional arguments AND keyword arguments to the same function? 。正如该问题的答案所指出的那样,混合可选参数和关键字参数通常是一种容易出错的做法。 Common Lisp 使用 read-from-string 来做到这一点,它经常给人们带来麻烦。

但是,您所提议的不仅仅是一个同时使用关键字和可选参数的函数,而且,从它的声音来看,实际上是在对参数类型进行一些检查,并在一种情况下采取一种行为,另一个在另一个。在这种情况下,如果 i 应该是一个数字,那么你可以检查第一个参数,如果它是一个数字,则将其视为可选参数,其余视为关键字参数,如果它不是数字,则将整个列表视为关键字参数。您可以使用以不同方式解构的 &rest 参数来做到这一点:

(defun frob (&rest args)
(flet ((frob-driver (i size)
(list i size)))
(if (or (endp args) (numberp (first args)))
;; no args, or the first argument is a number (and thus
;; not a keyword argument)...
(destructuring-bind (&optional (i 'default-i) &key (size 'default-size)) args
(frob-driver i size))
;; otherwise, there are some non-numeric arguments at
;; beginning, so it must be the keyword list, and that the
;; "optional" wasn't provided.
(destructuring-bind (&key (size 'default-size) &aux (i 'default-i)) args
(frob-driver i size)))))
(frob 10 :size 50)             ; give i and size
;=> (10 50)

(frob :size 60) ; give size, but not i
;=> (default-i 60)

(frob 40) ; give i, but not size
;=> (40 default-size)

(frob) ; give neither
;=> (default-i default-size)

没有关键字符号的关键字参数

在评论中,您提到您希望能够使用非关键字符号作为参数列表中的关键字。这很容易。在 HyperSpec 中, §3.4.1 Ordinary Lambda Lists 描述了关键字参数的语法:
[&key {var | ({var | (keyword-name var)} [init-form [supplied-p-parameter]])}* [&allow-other-keys]] 

这意味着您可以像这样定义函数:
(defun frob (&key foo ((bar-keyword bar-variable) 'default-baz))
(list foo bar-variable))
(frob :foo 1 'bar-keyword 2)
;=> (1 2)

(frob :foo 3)
;=> (3 default-baz)

(frob 'bar-keyword 2)
;=> (nil 2)

关于common-lisp - 如何定义一个 &key 参数来取代 Lisp 中的 &optional 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23201668/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com