嗨,我是Common Lisp的初学者。我想检查两个变量是否为整数。如果n和m均为整数,我希望它返回-
如果它为负,0
如果它为零,+
如果它为正,NIL
如果它为负对于n和m都不是整数。我想出了如何使用一个变量来执行此操作,但似乎无法弄清楚如何使用两个变量来执行此操作。谢谢。
这是一个采用数字参数的代码,如果为负,则返回-
;如果为零,则返回0
;如果为正,则返回+
;如果为负,则返回NIL
它不是整数:
(defun sign (n)
(if(typep n 'integer)
(cond ((< n 0) '-)
((= n 0) 0)
((> n 0) '+))))
每种情况的输出为:
CL-USER> (sign 3)
+
CL-USER> (sign -3)
-
CL-USER> (sign 0)
0
CL-USER> (sign 3.3)
NIL
这是我检查两个变量的代码,我希望它检查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) '+)) ))))
答案 0 :(得分:3)
记住基本的Lisp语法。函数调用和一些基本表达式写为
(operator argument-0 argument-1 ... argument-n)
对吗?
开括号,运算符,参数0,自变量1 ...自变量-n,右括号。
现在,如果我们拥有(< n 0)
和(< m 0)
,AND
表达式将如何?
(and (< n 0) (< m 0))
但是你写:
and ((< n 0) '-) ((< m 0) '-)
您有以下错误:
'-
混入了参数表达式。现在COND
期望:
(COND (testa1 forma0 forma1 ... forman)
(testb1 formb1 formb1 ... formbn)
...
(testm1 formm0 formm1 ... formmn))
所以不是
(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) '+)))))
顺便说一句,最后还有一个括号。
我们写:
(defun sign (n m)
(if (and (typep n 'integer) (typep m 'integer))
(cond ((and (< n 0) (< m 0)) '-)
.... )))
还可以使用integerp
,minusp
,zerop
和plusp
之类的谓词。
答案 1 :(得分:2)
您可以使用已经运行且经过测试的sign
定义-这是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)
请注意,一般来说,这很重要, 您选择哪种平等测试:
;; 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)))
,您可以应用equality-value
函数
将来用于您想要的功能
测试为“相等”时返回值
并且您可以通过:test
赋予函数任何相等性
eql
以外的其他函数也适合这种情况,例如
(equality-value string1 string2 :test #'string=)
答案 2 :(得分:1)
您似乎使用了正确的方法,只是迷惑了括号。您的每个cond
案例看起来都是
(and ((< n 0) '-) ((< m 0) '-))
我想你的意思
((and (< n 0) (< m 0)) '-)
对于其他两种情况,都是相同的。
答案 3 :(得分:0)
编写sign
的另一种紧凑方式是使用标准函数signum
根据数字是否为负数,返回-1、0或1中的一个, 零或正数
代码如下:
(defun sign (n)
(when (integerp n)
(case (signum n)
(-1 '-)
(0 0)
(1 '+))))