为什么LISP在函数中使用和IF语句打印NIL?

时间:2016-09-21 16:48:26

标签: lisp common-lisp

我刚刚开始学习LISP,而我正试图创建一个程序,在给出一个数字时打印出字母等级。

(defun number-to-letter (number)

(if(or(> number 100)(< number 0))
    (print "NUMBER OUT OF RANGE, PLEASE ENTER NUMBER WITHIN RANGE 0-100")
)

(if(and(>= number 80)(<= number 100))
        (print "A")
)

(if(and(>= number 70)(<= number 79))
        (print "B")
)

(if(and(>= number 60)(<= number 69))
        (print "C")
)

(if(and(>= number 50)(<= number 59))
        (print "D")
)

(if(and(>= number 0)(<= number 49))
        (print "F")
)
)

我无法弄清楚为什么在执行程序后打印NIL。

2 个答案:

答案 0 :(得分:4)

NIL部分在Kaz's answer中解决。

一些评论

  • <=是可变参数,您可以编写(<= x y z)来检查xyz是否按照{{1}排序}。这同样适用于other运营商。

  • 你有很多重复。由于您的条件是独占的,因此您可以用COND替换所有IF。

  • 此外,您可以在测试之外调用<=

  • 您的代码格式错误。不要将括号放在自己的行上。请参阅示例https://google.github.io/styleguide/lispguide.xml或其他资源。

重写

print

此外,在一个真实的程序中,我会发出错误信号,而不是像这样直接打印错误信息,但由于这只是一个例子,我猜这里没问题。

测试

(defun number-to-letter (number)
  (print
   (cond
     ((<= 80 number 100) "A")
     ((<= 70 number 79) "B")
     ((<= 60 number 69) "C")
     ((<= 50 number 59) "D")
     ((<= 0 number 49) "F")
     (t "NUMBER OUT OF RANGE, PLEASE ENTER NUMBER WITHIN RANGE 0-100"))))

...打印并返回&#34; F&#34;,因为PRINT返回正在打印的值。

答案 1 :(得分:3)

当你有一个打印东西的函数并从Lisp监听器调用它时,你不仅会看到打印输出,还会看到表达式返回的值。它可能看起来像这样:

LISP> (print "a")
"a" <-- this is the output
"a" <-- this is the return value
LISP>

如果你评估一个没有替代表达式(只有两个参数)的失败if,它会产生nil:

LISP> (if (> 3 4) (print "three is greater than four"))
NIL

我们可以添加一个替代表单,然后生成其值,例如42

LISP> (if (> 3 4) (print "three is greater than four") 42)
42

如果我们将这些if形式放入函数并调用这些函数,则会发生同样的事情。

我们可以在函数体中包含两个或更多个表单。行为是它们被评估为“隐式progn”。 progn是一个逐个计算其参数形式的表单,然后返回最后一个的值。我们可以直接使用它:

LISP> (progn
        (if (< 3 4) (print "three is less than four"))
        (if (> 3 4) (print "three is greater than four")))
"three is less than four"
NIL

发生了什么事?第一个if的测试是真的,因此print形式被评估并产生输出。该形式也会产生结果,但由于它不是progn的最后一种形式,因此该结果将被丢弃。然后评估下一个表格。它是另一种if形式,其测试失败。所以它产生NIL。由于它是progn中的最后一个表单,NIL成为progn本身的结果值,并由侦听器打印。

当你打电话给你的职能时,你可能会得到NIL;函数中的最后一个测试失败,导致它返回该值,然后由函数打印,而不是由交互式Lisp监听器打印。

根据我们使用的Lisp监听器的行为(取决于实现),我们可能能够摆脱NIL。我们可以做的是将表单(values)放在函数体的末尾(或者在我们的例子中,progn形式):

LISP> (progn 1 2 3)
3
LISP> (progn 1 2 3 (values))
LISP>

Lisp中的values函数指定零个或多个结果值。如果它没有给出参数,那么它根本不会产生任何值。如果我们将它放在函数体或progn或其他具有progn类体的构造的末尾,则它不会产生任何值。

例如,ANSI Common Lisp的CLISP实现有一个监听器,在评估(values)时只打印一个空行:

clisp -q
[1]> 1
1
[2]> (list 1 2)
(1 2)
[3]> (values)

[4]>
相关问题