1

I'm just starting to learn LISP and I'm trying to create a program that prints out the letter grade when it is given a number.

(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") ) ) 

I cant figure out why its printing NIL after I execute the program.

1
  • You should also give the test which fails, according to you Commented Sep 21, 2016 at 17:14

2 Answers 2

4

The NIL part is addressed in Kaz's answer.

Some remarks

  • <= is variadic, you can write (<= x y z) to check whether x, y and z are sorted according to <=. The same applies to other operators.

  • You have a lot of repetition. Since your conditions are exclusive, you can replace all your IFs by a single COND.

  • Moreover, you can factor the call to print outside of the test.

  • Your code is badly formatted. Don't put parenthesis on their own lines. See for example https://google.github.io/styleguide/lispguide.xml or other resources.

Rewrite

(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")))) 

Besides, in a real program I would signal an error instead of printing directly the error message like this, but since it is only an example I guess it is ok here.

Test

(number-to-letter 30) 

... prints and returns "F", because PRINT returns the value being printed.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, this helped a ton!
3

When you have a function which prints something and you call it from the Lisp listener, you will not only see the printed output, but also the value returned by the expression. It might look something like this:

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

If you evaluate a failing if which has no alternative expression (only two arguments), it yields nil:

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

We can add an alternative form, whose value is then produced, say 42:

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

If we put these if form into functions and call those functions, the same thing happens.

We can have two or more forms in the body of a function. The behavior is that they are evaluated as if in an "implicit progn". progn is a form which evaluates its argument forms one by one, and then returns the value of the last one. We can use it directly:

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 

What's happening? The first if has a test which is true and so the print form is evaluated and produces output. That form also produces a result, but since it is not the last form of the progn, that result is thrown away. The next form is then evaluated. It's a another if form, whose test fails. So it yields NIL. Since it is the last form in the progn, that NIL becomes the result value of the progn itself and is printed by the listener.

And that's possibly how you might be getting NIL when you call your function; the last test in the function is failing, causing it to return that value which is then printed not by the function, but by your interactive Lisp listener.

Depending on the behavior of the Lisp listener we are using (which depends on the implementation), we may be able to get rid of that NIL. What we can do is put the form (values) at the end of the function body (or in our case, the progn form):

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

The values function in Lisp specifies zero or more result values. If it is given no arguments, then it yields no value at all. If we put that at the end of a function body or a progn or other construct which has a progn-like body, then it yields no value.

The CLISP implementation of ANSI Common Lisp, for instance, has a listener which prints nothing but a blank line when (values) is evaluated:

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.