[英]How do I apply “or” to a list in elisp
在elisp我可以評估或作為一個函數就像+。
(or nil 0 nil) ==> 0
(+ 1 0 1) ==> 2
我可以使用apply來將+應用到列表中
(apply '+ '(1 0 1)) ==> 2
所以,我會想或者會以同樣的方式工作,但事實並非如此。
(apply 'or '(nil 0 nil)) ==> error: (invalid-function or)
我想這是來自用於實現短路評估的一些內部魔術。 如何使用apply對列表執行或操作?
PS我想要的應用程序是找出命令行上的任何元素是否與特定模式匹配,所以我寫的重要部分是:
(apply 'or (mapcar (lambda (x) (string-match-p "pattern" x)) command-line-args))
但它不起作用
問題是, or
是一個宏(這是所謂的“內部魔術”),你說得對,它可以做短路。 如果or
是一個函數,那么調用它將需要遵循評估函數調用的通常規則:在調用之前需要對所有參數進行求值。
另請參閱這個問題 - 它是關於Scheme的,但它是完全相同的問題。
至於解決方案,你應該使用some
,如:
(some (lambda (x) (string-match-p "pattern" x)) command-line-args)
注意:這使用默認情況下未包含在emacs中的常見lisp。 只需使用(require 'cl)
如果它讓你感覺更好,那你就是一個好伙伴! 這是Lisp FAQ的“常見陷阱”部分中的第三個問題:
這是簡單但不一定令人滿意的答案:AND和OR是宏,而不是函數; APPLY和FUNCALL只能用於調用函數,而不能用於調用宏和特殊運算符。
......當然Eli對他的建議使用SOME
:
Common Lisp函數EVERY和SOME可用於在嘗試應用#'AND和#'OR時獲得您想要的功能。
(FAQ和這個答案主要是關於Common Lisp,但在這種情況下,如果省略#
字符,答案是相同的。)
如果你不關心表現,請使用(eval (cons 'or '(nil 0 nil)))
當我試圖將一個宏“應用”到一個參數列表時,我得到一個錯誤,該函數是未綁定的,這意味着'apply'只接收一個函數而不是宏作為它的第一個參數。
為了解決這個問題,我寫了一個新函數'apply-macro',如下所示:
(defun apply-macro (macro arg-list)
(eval
`(,macro ,@(loop for arg in arg-list
collect `(quote ,arg)))))
例如,我寫了一個宏來連接多個列表:
(defmacro conc-lists (&rest lists)
`(funcall #'concatenate 'list ,@lists))
例如(conc-lists'(ab)'(cd)'(ef));; =>(ABCDEF)
現在嘗試'apply-macro':
(apply-macro 'conc-lists '((a b) (c d) (e f)))
它工作並返回相同的輸出。
事實上,它將擴展為:
(eval
(conc-lists (quote (a b)) (quote (c d)) (quote (e f))))
您還可以將表單傳遞給宏:
(apply-macro 'conc-lists (maplist #'list '(a b c)))
;;=> ((A B C) (B C) (C))
回到你的問題,它已經解決了:
(apply-macro 'or '(nil 0 nil)) ;;=> 0
Eli Barzilay的回答是正確和慣用的。 我想提供一個基於dash.el
的替代答案,我用來編寫簡潔的函數式代碼的庫,當我必須使用列表時。 or
返回第一個非零元素,否則由於短路而返回nil。 因此,只需使用-first
:
(-first 'identity '(nil 0 1 nil)) ; 0
(-first 'identity '(nil nil)) ; nil
identity
函數只返回其參數。 這很聰明,因為-first
應用謂詞直到它返回非零。 如果參數本身是非零的,則identity
返回非nil。 如果您只想測試列表中是否存在非零元素,請使用-any?
代替:
(-any? 'identity '(nil 0 1 nil)) ; t
(-any? 'identity '(nil nil)) ; nil
我只是在這里猜測,但我認為or
可能是lisp中這些20多個'函數'之一並不是真正的函數,因為它們並不總是評估所有參數。
這是有意義的, or
其中之一,因為如果你找到一個真,你可以停止搜索。 換句話說, or
不是作為優化形式的功能。 仍然只是猜測。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.