在Common Lisp中,稍微调整成员函数的功能最优雅的方法是什么



成员函数对字符串的作用如下:

CL-USER> (member "a" '("a" "b" "c") :test #'equalp)
("a" "b" "c")
CL-USER> (member "a" '( "b" "c") :test #'equalp)
NIL

我想稍微改变一下它的行为。当元素是列表的而不是部分时,我希望返回元素本身,而不是nil。此外,如果元素确实是列表的一部分,我希望有nil

所以,类似于:

CL-USER> (tweaked-member "a" '("a" "b" "c") :test #'equalp)
NIL
CL-USER> (tweaked-member "a" '( "b" "c") :test #'equalp)
"a"

因此,我采取了这种天真的方法:

(defun so-question (str str-list)
(if (member str str-list :test #'string=)
nil
str))

有更优雅的方法吗?

可能使用member-if-not:key

我不知道这是否更优雅;您的";天真的";解决方案可能更清楚,但您可以这样做:

(defun tweaked-member (needle haystack)
(and (not (member needle haystack :test #'equalp)) needle))
CL-USER> (tweaked-member "a" '("a" "b" "c"))
NIL
CL-USER> (tweaked-member "a" '("b" "c"))
"a"

你可以用find代替member:

(defun tweaked-member (needle haystack)
(and (not (find needle haystack :test #'equalp)) needle))

直到现在,我才注意到我的版本没有像您所要求的那样采用:test参数。但是:

(defun tweaked-member (needle haystack &rest args)
(and (not (apply #'member needle haystack args)) needle))
CL-USER> (tweaked-member "a" '("a" "b" "c") :test #'equalp)
NIL
CL-USER> (tweaked-member "a" '("b" "c") :test #'equalp)
"a"
(defun tweaked-member (&rest args)
(if (apply #'member args) nil (car args)))

它并不更优雅,但它接受了member接受的所有关键字。

最新更新