関数 "greaterthan" は(< NUM1 NUM2)
、2 つの値を比較するために t/nil を返すことのみを許可します。
(var1 > var2 < var3 < var4) をテストしたいのですが、Lisp で 1 つの関数だけを使用してそれを行う方法はありますか? そうでない場合、最善の手順は何ですか?
最良の手順は気にしないことです:あなたのチェーン(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))))
以下は可変長引数のマクロ実装です<
(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)
すべての関数は 1 回呼び出されていますが、短絡のために呼び出す必要がなかったものを除き0
ます (短絡が本当に良いアイデアかどうかは 100% 確信が持てません... #'<
Common Lisp では、通常の関数であり、すべての引数はすべて、短絡することなく、左から右の順序で正確に 1 回評価されます)。
(defun << (arg1 arg2 arg3 arg4)
(when (and (< arg1 arg2) (< arg2 arg3) (< arg3 arg4)))
)
(<< 1 2 3 4)
おそらく、任意の数の引数で拡張することは可能ですが、そのような一般的な形式は便利に思えます。