Reputation: 39
Sorry to ask this question, but I was learning optional parameters in LISP Hence I created a function called "calculate-bill" which will take two parameters :
So as you can guess if the discount is passed to the function it will cut its value from the amount else just print the amount.
Code :
(defun calculate-bill (amount &optional discount)
(if (null discount)
(format t "Total bill is ~d." amount))
(if discount
(format t "Total bill is ~d." (- amount discount))))
(write (calculate-bill 200 50))
(terpri)
(write (calculate-bill 200))
Here I had added null condition in if blocks.
I want my expected output to be :
Total bill is 150.
Total bill is 200.
But the current output is :
Total bill is 150.NIL
Total bill is 200.NIL
How can I avoid that "NIL" ?
Upvotes: 1
Views: 348
Reputation: 1934
The function calculate-bill
prints out the message "Total amount is...", but this is just a side effect. The value returned by the function is, when there is no explicit return <value>
, the value of the last executed function, which in this case is format
, and the value of format
is always nil when the output stream is T. So what the write function does is to print the value returned by calculate-bill
which is nil. If you want calculate-bill
to return the string then change the output stream of format to nil:
(format nil "Total bill is ~d." amount)
This creates a string which is not printed until you pass it to an output function like e.g. write
.
As an extra suggestion, the function if
can take three parameters: the test, the code to execute when the test is t, and the code to execute when the test is nil. So, in your case, it is far better to write:
(if (null discount)
(format t "Total bill is ~d." amount)
(format t "Total bill is ~d." (- amount discount)))
Upvotes: 2
Reputation: 9865
Choose default for discount as 0
then you save the null
testing.
Further, I would format
to nil
to just return the strings.
(defun calculate-bill (amount &optional (discount 0))
(format nil "Total bill is ~d." (- amount discount)))
write
prints and returns. Only printing you achieve by (format t "~a" x)
.
(progn
(format t "~a" (calculate-bill 200 50))
(terpri)
(format t "~a" (calculate-bill 200)))
Alternatively you can include "~%"
into format
string instead using (terpri)
.
(progn
(format t "~a~%" (calculate-bill 200 50))
(format t "~a~%" (calculate-bill 200)))
I would optionally let display the result but return the string.
(defun calculate-bill (amount &key (discount 0) (verbosep nil))
(let* ((result (- amount discount))
(res (format nil "Total bill is ~d." result)))
(if verbosep
(format t "~a~%" res))
res))
Then set :verbosep t
if you want the output visible in the terminal.
(calculate-bill 200 :discount 50 :verbosep t)
(calculate-bill 200 :verbosep t)
Upvotes: 1
Reputation: 38809
Optional parameter admit a default value, you could for example have a default discount of zero.
(defun calculate-bill (amount &optional (discount 0))
(check-type discount real)
(- amount discount))
Upvotes: 1
Reputation: 139261
You are doing double output. You call FORMAT and WRITE.
Now you need to find out whether you really want to do double output and, if not, which function to keep and which not.
Upvotes: 2