簡體   English   中英

如何將“或”應用於elisp中的列表

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM