公共Lisp类型检查两个变量

公共Lisp类型检查两个变量,lisp,common-lisp,Lisp,Common Lisp,嗨,我是一个普通口齿不清的初学者。我想检查两个变量是否是整数。如果n和m都是整数,我希望它返回-如果它是负数,0如果它是零,+如果它是正数,NIL如果它不是n和m的整数。我知道如何用一个变量来实现这一点,但我似乎不知道如何用两个变量来实现这一点。谢谢 这是一段代码,它接受一个数值参数,如果它为负,则返回-;如果它为零,则返回0;如果它为正,则返回+;如果它不是整数,则返回NIL: (defun sign (n) (if(typep n 'integer) (cond ((< n

嗨,我是一个普通口齿不清的初学者。我想检查两个变量是否是整数。如果n和m都是整数,我希望它返回
-
如果它是负数,
0
如果它是零,
+
如果它是正数,
NIL
如果它不是n和m的整数。我知道如何用一个变量来实现这一点,但我似乎不知道如何用两个变量来实现这一点。谢谢

这是一段代码,它接受一个数值参数,如果它为负,则返回
-
;如果它为零,则返回
0
;如果它为正,则返回
+
;如果它不是整数,则返回
NIL

(defun sign (n)
 (if(typep n 'integer)
    (cond ((< n 0) '-)
          ((= n 0) 0)
          ((> n 0) '+))))
这是我用来检查两个变量的代码,我想让它检查n和m是整数,n和m是正的、负的还是零:

(defun sign (n m)
 (if (and (typep n 'integer) (typep m 'integer))
  (cond (and ((< n 0) '-) ((< m 0) '-))
        (and ((= n 0) 0) ((= m 0) 0))
        (and ((> n 0) '+) ((> m 0) '+)) ))))
(除符号(n m)
(if(and(typep n'整数)(typep m'整数))
(第(和(n0)+(>m0)+))

看起来您的方法是正确的,只是在括号中迷失了方向。您的每个
cond
案例

(and ((< n 0) '-) ((< m 0) '-))
(和(
我想你是说

((and (< n 0) (< m 0)) '-)
((和(

另外两种情况也是一样。

记住基本的Lisp语法。函数调用和一些基本表达式编写为

(operator argument-0 argument-1 ... argument-n)
对吧?

开括号,运算符,参数-0参数-1。。。参数-n,右括号

现在,如果我们有
表达式会是什么样子

(and (< n 0) (< m 0))
所以不是

(defun sign (n m)
  (if (and (typep n 'integer) (typep m 'integer))
      (cond (and ((< n 0) '-) ((< m 0) '-))
            (and ((= n 0)  0) ((= m 0)  0))
            (and ((> n 0) '+) ((> m 0) '+)))))
(除符号(n m)
(if(and(typep n'整数)(typep m'整数))
(第(和(n0)+(>m0)+)))
顺便说一句,结尾有一个额外的括号

我们写道:

(defun sign (n m)
  (if (and (typep n 'integer) (typep m 'integer))
      (cond ((and (< n 0) (< m 0)) '-)
            .... )))
(除符号(n m)
(if(and(typep n'整数)(typep m'整数))
(cond((和(

还可以使用诸如
integerp
minssp
zerop
plusp
之类的谓词。您可以使用已经运行并经过测试的
符号
定义,这是lispers程序的典型方式。第一个简单的解决方案是:

(defun sign-for-two (n m)
  (when (eql (sign n) (sign m)) 
    (sign n))

;; (if (condition) return-value NIL)
;; is equivalent to 
;; (when (condition) return-value)
注意,在common lisp中,这一点很重要, 您选择的平等性测试:

;; only symbols - for object identity        eq
;; symbols or numbers - for object identity  eql
;;   (in most tests the default)
;; eql for each component? also in lists     equal
;; equal not only lists but also
;; arrays (vectors, strings), structures, hash-tables
;; however case-insensitive in case of strings
;;                                           equalp
;; mathematical number equality              =
;; specifically characters                   char=
;; case-sensitive string equality            string=
在我们的例子中,eql就足够了

;; to avoid `(sign n)` to be evaluated twice,
;; you could store it using `let` 
;; and call from then on the stored value
;; (which is less costly).

(defun sign-for-two (n m)
  (let ((x (sign n)))
    (when (eql x (sign m))
      x)))
或者创建一个相等性测试仪(默认测试函数:
#'eql
) 它返回相同的测试值 如果不相等,
NIL

(defun equality-value (x y &key (test #'eql))
   (when (funcall test z y) z)))

;; and apply this general solution to our case:
(defun sign-for-two (n m)
   (equality-value (sign n) (sign m)))
您可以应用
相等值
函数 在将来的函数中 测试为“相等”时返回值 您可以通过
:test
任何等式给出函数 除了
eql
之外的函数适用于这种情况,如

(equality-value string1 string2 :test #'string=)

另一种编写
符号的简洁方法是使用标准函数

根据数字是否为负数返回-1、0或1中的一个, 零,还是正

代码可能如下所示:

(defun sign (n)                                                                                                                                                                                                                                                     
  (when (integerp n)                                                                                                                                                                                                                                                            
    (case (signum n)                                                                                                                                                                                                                                                              
      (-1 '-)                                                                                                                                                                                                                                                                     
      (0   0)                                                                                                                                                                                                                                                                       
      (1  '+))))

let
内部的
相等值
不是必需的,但更重要的是,调用
test
应该使用funcall完成。@coredump啊,谢谢你-我总是喜欢你的答案和评论我在控制台上更正了这个(funcall),但忘了在文本中更正它。诚然,let inside
相等值是多余的-我将删除它。我对以前的代码:D考虑得太多了。
(defun equality-value (x y &key (test #'eql))
   (when (funcall test z y) z)))

;; and apply this general solution to our case:
(defun sign-for-two (n m)
   (equality-value (sign n) (sign m)))
(equality-value string1 string2 :test #'string=)
(defun sign (n)                                                                                                                                                                                                                                                     
  (when (integerp n)                                                                                                                                                                                                                                                            
    (case (signum n)                                                                                                                                                                                                                                                              
      (-1 '-)                                                                                                                                                                                                                                                                     
      (0   0)                                                                                                                                                                                                                                                                       
      (1  '+))))