1

関数 "greaterthan" は(< NUM1 NUM2)、2 つの値を比較するために t/nil を返すことのみを許可します。

(var1 > var2 < var3 < var4) をテストしたいのですが、Lisp で 1 つの関数だけを使用してそれを行う方法はありますか? そうでない場合、最善の手順は何ですか?

4

4 に答える 4

6

最良の手順は気にしないことです:あなたのチェーン(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))))
于 2013-02-10T22:35:06.763 に答える
2

以下は可変長引数のマクロ実装です<

(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 回評価されます)。

于 2013-02-11T08:57:55.170 に答える
0
(defun << (arg1 arg2 arg3 arg4)
 (when (and (< arg1 arg2) (< arg2 arg3) (< arg3 arg4)))
)

(<< 1 2 3 4)

おそらく、任意の数の引数で拡張することは可能ですが、そのような一般的な形式は便利に思えます。

于 2013-02-11T07:15:49.977 に答える