函數「greaterthan」,(< NUM1 NUM2)
,只允許返回t/nil來比較2個值。在等式檢查中可能有多於2個值? (> NUM1 NUM2)ELISP
我想測試(var1> var2 < var3 < var4),有什麼辦法可以在lisp中只使用一個函數嗎?如果不是,最好的程序是什麼?
函數「greaterthan」,(< NUM1 NUM2)
,只允許返回t/nil來比較2個值。在等式檢查中可能有多於2個值? (> NUM1 NUM2)ELISP
我想測試(var1> var2 < var3 < var4),有什麼辦法可以在lisp中只使用一個函數嗎?如果不是,最好的程序是什麼?
最好的程序是不要打擾:(and (< var2 var1) (< var2 var3) (< var3 var4))
不難看出你的..>..<..<..
鏈。
這是有道理的測試升序:
(require 'cl)
(defun cl-< (&rest args)
(every '< args (cdr args))
這些天我不猶豫,(require 'cl)
了,但如果你這樣做, 這裏是另一種變體:
(defun cl-< (arg &rest more-args)
(or (null more-args)
(and (< arg (first more-args))
(apply #'cl-< more-args))))
(defun << (arg1 arg2 arg3 arg4)
(when (and (< arg1 arg2) (< arg2 arg3) (< arg3 arg4)))
)
(<< 1 2 3 4)
或許可以用任意數量的參數進行擴展,但這樣的一般形式似乎很有用。
以下是可變參數<
(defmacro << (x y &rest args)
(if args
(if (or (symbolp y)
(numberp y))
`(and (< ,x ,y) (<< ,y ,@args))
(let ((ys (make-symbol "y")))
`(let (,ys)
(and (< ,x (setq ,ys ,y))
(<< ,ys ,@args)))))
`(< ,x ,y)))
對於簡單的情況下的宏實現只是擴展爲(and ...)
鏈
(<< x y z) ==> (and (< x y) (< y z))
其中,表達式不是數字,而不是一個符號擴展到更復雜的形式以避免在存在副作用的情況下進行多次評估
(<< (f x) (g y) (h z)) ==> (let ((gy)) (and (< (f x) (setq gy (g y)))
(< gy (h z))))
例如
(setq foo (list))
nil
(defun call (x) (push x foo) x)
call
(<< (call 1) (call 2) (call 5) (call 4) (call 0))
nil
foo
(4 5 2 1)
每個函數被調用一次,除了0
這並不需要,因爲短路被稱爲(我不是100%肯定,如果短路是一個非常好的想法或不... #'<
Common Lisp是一個常規函數,所有參數都按照從左到右的順序精確評估一次而不會短路)。
@wvxvw:注意在Common Lisp中'#'<'是一個常規函數,因此所有參數總是按照從左到右的順序精確評估一次。最初我喜歡短路的想法(就像Python做'f()<= g()
(defmacro << (&rest args)
(let ((first (car args))
(min (gensym))
(max (gensym))
(forms '(t)) iterator)
(setq args (reverse (cdr args))
iterator args)
`(let ((,min ,first) ,max)
,(or
(while iterator
(push `(setq ,min ,max) forms)
(push `(< ,min ,max) forms)
(push `(setq ,max ,(car iterator)) forms)
(setq iterator (cdr iterator))) `(and ,@forms)))))
(macroexpand '(<< 10 20 30 (+ 30 3) (* 10 4)))
(let ((G99730 10) G99731)
(and (setq G99731 20)
(< G99730 G99731)
(setq G99730 G99731)
(setq G99731 30)
(< G99730 G99731)
(setq G99730 G99731)
(setq G99731 (+ 30 3))
(< G99730 G99731)
(setq G99730 G99731)
(setq G99731 (* 10 4))
(< G99730 G99731)
(setq G99730 G99731) t))
這類似於6502的想法,但是可能會帶來更少的代碼,在一個沒有價值的情況,但它會在一個微不足道的情況下創造更多的代碼。
是的,我認爲這可以分3步完成。儘管如此,想象不得不做一些類似的測試,比如(var1 < var2 > var 3 PascalVKooten 2013-02-11 07:13:42
雖然這很好!甚至有可能在這裏測試不一致的參數。如果不需要'cl',沒有辦法做到這一點嗎? – PascalVKooten 2013-02-11 07:19:12
增加了一個不需要'cl'的變體。一般來說,不使用'cl'編寫更困難,我們在這裏做的是無論如何都添加一個Common Lispish'<'函數(如果更多人需要它,它將成爲'cl.el'的一個*部分) 。 – 2013-02-11 09:51:45