I'm very new to Lisp and am trying to write a program that simply asks a user to enter 3 numbers and then sums them and prints the output.
I've read that you can you a function like:
(defvar a)
(setq a (read))
To set a variable in Lisp, but when I try to compile my code using LispWorks I get the following error:
End of file while reading stream #<Concatenated Stream, Streams = ()>
I feel like this should be relatively simple and have no idea where I'm going wrong.
I've not worked with LispWorks, so it's only a guess.
When compiler traverses your code it gets to the line (setq a (read)), it tries to read input, but there is no input stream while compiling, thus you get an error.
Write a function:
(defvar a)
(defun my-function ()
(setq a (read))
It should work.
This should evaluate properly in your Lisp:
(defun read-3-numbers-&-format-sum ()
(flet ((prompt (string)
(format t "~&~a: " string)
(finish-output)
(read nil 'eof nil)))
(let ((x (prompt "first number"))
(y (prompt "second number"))
(z (prompt "third number")))
(format t "~&the sum of ~a, ~a, & ~a is:~%~%~a~%"
x y z (+ x y z)))))
Simply evaluate the above function definition, then run the form:
(read-3-numbers-&-format-sum)
at your LispWorks interpreter.
Related
It's a simple college problem. I have to get the result using the BMI calc
My code below:
(write-line "BMI CALC")
(defun calc nil
(prog (w h) ; define p e h as local variables init with nil
(print "Weight: ")
(setq w (read))
(print "Height: ")
(setq h (read))
(return (/ w (* h h)))
)
)
(format t "BMI: ~D~%" (calc))
(setq bmi calc)
(cond
((< bmi 18.5) (print "Under weight"))
((< bmi 24.9) (print "Normal weight"))
((< bmi 29.9) (print "Overweight"))
((< bmi 34.9) (print "Obesity 1"))
((< bmi 39.9) (print "Obesity 2"))
(t (print "Obesity 3"))
)
And I got this result below:
BMI CALC
"Weight: " 78
"Height: " 1.7
BMI: 26.989618
*** - SETQ:variable CALC has no value
I really don't understand why this error.
I expected to print the BMI result, like "Under weight" or "Obesity 1".
What value do you think variable calc has on this line: (setq bmi calc)?
Because, as that error says, it doesn't have any.
Also, ending parentheses belong to the same line and you should read about let (a special operator for creating local variables).
Here is an improved version, which you can test by calling (my-bmi):
(defun calc ()
(prog (w h)
(print "Weight: ")
(setq w (read *query-io*))
(print "Height: ")
(setq h (read *query-io*))
(return (/ w (* h h)))))
(defun my-bmi ()
(print "BMI CALC")
(let ((bmi (calc)))
(format t "BMI: ~D~%" bmi)
(print
(cond
((< bmi 18.5) "Under weight")
((< bmi 24.9) "Normal weight")
((< bmi 29.9) "Overweight")
((< bmi 34.9) "Obesity 1")
((< bmi 39.9) "Obesity 2")
(t "Obesity 3")))))
Remarks about your code
You are using a global variable and writing the whole assignment as a script: namely you call (setq bmi ...) where bmi is not introduced by a let. And there is very few reusable parts. It's a bit of a bad practice to have side-effects like that. Here you are only writing a small program for an assignment so it is not very bad but, as you are also learning programming, you should also try to structure your code as small functions that don't have side-effects. This would be cleaner and would help the program grow in a real situation.
This is related to the previous point, but you are mixing different things in functions: parsing input, computing the BMI, outputting the result. In practice we often need to architecture code into layers: here you can have a pure mathematics data layer that computes the BMI, a input/ouptut layer that prompt for values, and a main program that glues all of those parts together.
Regarding I/O, you are likely to experience difficulties later if you don't flush the output or clear the input streams during your interactions with the user: as streams are typically buffered, sometimes format won't display immediately a string and this will be confusing. Using force-output is a way to flush all the buffers and ensure the user sees the text you wrote.
Alternative implementation
This is an example of how I would do it, using intermediate functions to encapsulate different tasks.
For example:
(defun bmi-formula (&key height weight)
(/ weight (* height height)))
This is a function that you can invoke interactively as follows in the REPL:
CL-USER> (bmi-formula :height 1.80 :weight 60)
18.51852
Notice that it only computes a value from numerical values, there is no parsing involved.
Likewise, you can convert a BMI to an obesity judgment as follows (as an aside, using BMI for that is an outdated practice, I am a bit suprised/annoyed that you are being asked to write this function):
(defun bmi-obesity-judgment (bmi)
(cond
((< bmi 18.5) 'underweight)
;; etc.
))
Here the function takes a bmi and returns a symbol. If you want later to localize your application in another language, you can map each symbol to a word in another language (e.g. (ecase judgment (underweight "magro") ...) please forgive my attempt at Portuguese).
Now you can write a function that grabs input from the user. Typically I would write an auxiliary function as follows:
(defun prompt (message type)
(loop
(clear-input *query-io*)
(fresh-line *query-io*)
(write-string message *query-io*)
(let ((value (read *query-io*)))
(when (typep value type)
(return value))
(warn "~a is not of type ~a" value type))))
What it does is ensure the input is cleared (there is no pending/buffered values to be read), it prints a new-line if necessary, a custom message, flush the output stream, then read a value and check if that value matches a given type. If that's not the case the code is executed in a loop.
For example, you can produce a property list as follows:
(defun input-bmi-parameters ()
(list
:weight (prompt "Weight (kgs): " '(integer 0 1000))
:height (prompt "Height (meters): " '(real 0 5))))
Finally you can piece all the functions together, write a title, write the output, etc:
(defun bmi-program ()
(format *query-io* "~&BMI Calculator. Enter weight and height and be judged.~%")
(let ((parameters (input-bmi-parameters)))
...))
Notice how I am using let to introduce a local variable parameters bound to a list (see also in prompt where I use local variable value). Apart from interacting with the *query-io*, the code does not have side-effects, all the state is contained in the function. That means that you could run more than one bmi-program in parallel, without them messing around with the same set of global variables: you could have a server where each connection executes bmi-program in a different thread, in which *query-io* is bound to the current TCP stream.
I am learning Lisp and, just for practice/education, am trying to define a function that will
ask the user to enter a number until they enter an integer > 0 [copied from Paul Graham's Ansi Common Lisp]
print that number and subtract 1 from it, repeat until the number hits 0, then return.
I am trying to do this via passing 2 functions into a higher-order function - one to get the number from the user, and another recursive [just for fun] function that prints the number while counting it down to 0.
Right now my higher-order function is not working correctly [I've tested the first 2 and they work fine] and I cannot figure out why. I am using SBCL in SLIME. My code for the 3 functions looks like this:
(defun ask-number ()
(format t "Please enter a number. ")
(let ((val (read))) ; so val is a single-item list containing the symbol 'read'?
(cond ; no here read is a function call
((numberp val)
(cond
((< val 0) (ask-number))
(T val)))
(t (ask-number))))))
(defun count-down (n)
(cond
((eql n 0) n)
(t
(progn
(format t "Number is: ~A ~%" n)
(let ((n (- n 1)))
(count-down n))))))
(defun landslide (f1 f2)
(let (x (f1))
(progn
(format t "x is: ~A ~%" x)
(f2 x)))))
but calling slime-eval-defun in landslide yields:
; SLIME 2.27; in: DEFUN LANDSLIDE
; (F1)
;
; caught STYLE-WARNING:
; The variable F1 is defined but never used.
; (SB-INT:NAMED-LAMBDA LANDSLIDE
; (F1 F2)
; (BLOCK LANDSLIDE
; (LET (X (F1))
; (PROGN (FORMAT T "x is: ~A ~%" X) (F2 X)))))
;
; caught STYLE-WARNING:
; The variable F1 is defined but never used.
;
; caught STYLE-WARNING:
; The variable F2 is defined but never used.
; in: DEFUN LANDSLIDE
; (F2 X)
;
; caught STYLE-WARNING:
; undefined function: COMMON-LISP-USER::F2
;
; compilation unit finished
; Undefined function:
; F2
; caught 4 STYLE-WARNING conditions
I have tried several [what I consider] obvious modifications to the code, and they all fail with different warnings. Calling the function like (landslide (ask-number) (count-down)), ask-number prompts for user input as expected, but then SLIME fails with
invalid number of arguments: 0
[Condition of type SB-INT:SIMPLE-PROGRAM-ERROR]
I know I have to be missing something really obvious; can someone tell me what it is?
First: You are missing a set of parens in your let:
You have (let (x (f1)) ...) which binds 2 variables x and f1 to nil.
What you want is (let ((x (f1))) ...) which binds 1 variable x to the values of function call (f1)
Second: Common Lisp is a "lisp-2", so to call f2 you need to use funcall: (funcall f2 ...).
Finally: all your progns are unnecessary, and your code is hard to read because of broken indentation, you can use Emacs to fix it.
Before I reach an error in landslide, there are some notes about this code:
Your first function is hard to read- not just because of indentation, but because of nested cond.
You should always think about how to simplify condition branches- using and, or, and if you have only two branches of code, use if instead.
There are predicates plusp and minusp.
Also, don't forget to flush.
I'd rewrite this as:
(defun ask-number ()
(format t "Please enter a number. ")
(finish-output)
(let ((val (read)))
(if (and (numberp val)
(plusp val))
val
(ask-number))))
Second function, count-down.
(eql n 0) is zerop
cond here has only two branches, if can be better
cond has implicit progn, so don't use progn inside cond
let is unnecessary here, you can use 1- directly when you call count-down
Suggested edit:
(defun count-down (n)
(if (zerop n) n
(progn
(format t "Number is: ~A ~%" n)
(count-down (1- n)))))
Also, this function can be rewritten using loop and downto keyword, something like:
(defun count-down (n)
(loop for i from n downto 0
do (format t "Number is: ~A ~%" i)))
And finally, landslide. You have badly formed let here and as Common Lisp is Lisp-2, you have to use funcall. Note that let has also implicit progn, so you can remove your progn:
(defun landslide (f1 f2)
(let ((x (funcall f1)))
(format t "x is: ~A ~%" x)
(finish-output)
(funcall f2 x)))
Then you call it like this:
(landslide #'ask-number #'count-down)
Can anyone explain the part with the flet operator please ? :
(defun read-3-numbers-&-format-sum ()
(flet ((prompt (string)
(format t "~&~a: " string)
(read nil 'eof nil)))
(let ((x (prompt "first number"))
(y (prompt "second number"))
(z (prompt "third number")))
(format t "~&the sum of ~a, ~a, & ~a is:~%~%~a~%"
x y z (+ x y z)))))
Your source for Common Lisp documentation is the Common Lisp Hyperspec, which can be found at different places on the internet.
Look up flet there: http://clhs.lisp.se/Body/s_flet_.htm#flet
It establishes a local function definition. Its scope is its body (i. e. where the let form is in this case). The function definition works like a “normal” function defined with defun otherwise.
I'm reading Peter Norvig's Paradigms of AI. In chapter 6.2, the author uses code like below (not the original code, I picked out the troubling part):
Code Snippet:
(progv '(op arg) '(1+ 1)
(eval '(op arg)))
As the author's original intent, this code should return 2, but in sbcl 1.1.1, the interpreter is apparently not looking up op in the environment, throwing out op: undefined function.
Is this implementation specific? Since the code must have been tested on some other lisp.
p.s Original code
You probably mean
(progv '(op arg) '(1+ 1)
(eval '(funcall op arg)))
Edit(2013-08-21):
PAIP was written in pre-ANSI-Common-Lisp era, so it's possible the code
there contains a few noncompliances wrt the standard. We can make
the examples work with the following revision:
(defun match-if (pattern input bindings)
"Test an arbitrary expression involving variables.
The pattern looks like ((?if code) . rest)."
(and (eval (reduce (lambda (code binding)
(destructuring-bind (var . val) binding
(subst val var code)))
bindings :initial-value (second (first pattern))))
(pat-match (rest pattern) input bindings)))
;; CL-USER> (pat-match '(?x ?op ?y is ?z (?if (eql (?op ?x ?y) ?z))) '(3 + 4 is 7))
;; ((?Z . 7) (?Y . 4) (?OP . +) (?X . 3) (T . T))
;; CL-USER> (pat-match '(?x ?op ?y (?if (?op ?x ?y))) '(3 > 4))
;; NIL
Elements in first positions are not looked up as values, but as functions and there is no concept of dynamic binding in the function namespace.
I'd say after a quick look that the original code was designed to evaluate in a context like
(progv '(x y) '(12 34)
(eval '(> (+ x y) 99)))
i.e. evaluating a formula providing substitution for variables, not for function names.
The other answers so far are right, in that the actual form being evaluated is not the variables being bound by progv (simply (op arg)), but none have mentioned what is being evaluated. In fact, the comments in the code you linked to provide a (very) short explanation (this is the only code in that file that uses progv):
(defun match-if (pattern input bindings)
"Test an arbitrary expression involving variables.
The pattern looks like ((?if code) . rest)."
;; *** fix, rjf 10/1/92 (used to eval binding values)
(and (progv (mapcar #'car bindings)
(mapcar #'cdr bindings)
(eval (second (first pattern))))
(pat-match (rest pattern) input bindings)))
The idea is that a call to match-if gets called like
(match-if '((?if code) . rest) input ((v1 val1) (v2 val2) ...))
and eval is called with (second (first pattern)), which the value of code. However, eval is called within the progv that binds v1, v2, &c., to the corresponding val1, val2, &c., so that if any of those variables appear free in code, then they are bound when code is evaluated.
Problem
The problem that I see here is that, by the code we can't tell if the value is to be saved as the variable's symbol-value or symbol-function. Thus when you put a + as a value to some corresponding variable, say v, then it'll always be saved as the symbol-value of var, not it's symbol-function.
Therefore when you'll try to use it as, say (v 1 2) , it won't work. Because there is no function named v in the functions' namespace(see this).
So, what to do?
A probable solution can be explicit checking for the value that is to be bound to a variable. If the value is a function, then it should be bound to the variable's function value. This checking can be done via fboundp.
So, we can make a macro functioner and a modified version of match-if. functioner checks if the value is a function, and sets it aptly. match-if does the dynamic local bindings, and allows other code in the scope of the bound variables.
(defmacro functioner (var val)
`(if (and (symbolp ',val)
(fboundp ',val))
(setf (symbol-function ',var) #',val)
(setf ,var ,val)))
(defun match-if (pattern input bindings)
(eval `(and (let ,(mapcar #'(lambda (x) (list (car x))) bindings)
(declare (special ,# (mapcar #'car bindings)))
(loop for i in ',bindings
do (eval `(functioner ,(first i) ,(rest i))))
(eval (second (first ',pattern))))
(pat-match (rest ',pattern) ',input ',bindings))))
I'm tring to apply closure in emacs lisp.And I find a post here:
How do I do closures in Emacs Lisp?
with some code like:
(defun foo (x) `(lambda () ,x)) (message (string (funcall (foo
66))))
But following the emacs documentation lambda should be formated like
'(lambda () x) ==> using this format ,I got an ERROR :Symbol's value as variable is void: x
When " , " is add betwenn "()" and "x" ,everything goes right .
Why?
This happens because Emacs Lisp is dynamically scoped thus foo returns a lambda where x is free. That's what the error tells you.
To do a closure in Emacs Lisp you have to use lexical-let which simulates a lexical binding and therefore allows you to make a real closure.
(defun foo (x)
(lexical-let ((x x))
(lambda () x)))
(message (string (funcall (foo 66))))
Here are some links from the Emacs Wiki:
Dynamic Binding Vs Lexical Binding
Fake Closures
Note that you could have defined x with a let like this:
(defun foo (x)
(lambda () x))
(message (string (let ((x 66)) (funcall
(foo 'i-dont-care)))))
This answer gives a bit of detail behind the first part of #Daimrod's correct answer.
Your question is why this works:
(defun foo (x) `(lambda () ,x)) (message (string (funcall (foo 66))))
and this doesn't work:
(defun foo (x) '(lambda () x)) (message (string (funcall (foo 66))))
First, the quote (') is unnecessary in the second, because in Emacs Lisp lambda forms are self-evaluating. That is, '(lambda (...) ...) generally acts the same as (lambda (...) ...).
But what does the backquote (`), instead of quote ('), do?
Inside a backquoted expression, a comma (,) means replace the next expression by its value, that is, evaluate it. So this:
`(lambda () ,x)
means create and return a list whose first element is the symbol lambda (that's not evaluated), whose second element is () (that's not evaluated), and whose third element is the value of variable x. It's equivalent to evaluating this code, which uses function list:
(list 'lambda '() x)
That's what you want: replace x by its current value (in this case, its value inside the function foo, that is, the value of foo's argument).
But this:
'(lambda () x)
(and likewise, because a lambda form is self-evaluating, (lambda () x)) returns this list: (lambda () x). And when that's evaluated using dynamic scoping (the default scoping regime in Emacs Lisp), x is unbound - it has no value. So a void-variable error is raised.