I wrote a lisp program that takes two parameters, a destination, and a map in the form of a BST. It searchings the BST for the destination number, and prints (found: path) if the destination is found. If it's not found, it's supposed to print (not found: destination), but for some reason I am getting a contract violation. It's not running through my cond correctly, and I have been messing with it for thirty minutes. Can anyone help.
Here is my program:
(define (robot goal map)
[code hidden for university honour code purposes]
; Test robot function
(robot 64 '(53 () (64 () ())))
(robot 4 '(53 () (64 () ())))
You're missing one case in the procedure (define (robot map path) ...) . What happens if the map parameter is null? fix it like this:
(define (robot map path)
(cond ((not (null? map))
[code hidden for university honour code purposes])
(else '()))) ; this line was missing!
It's exactly the same thing that I mentioned in my answer to your previous question: always the first case to consider, whether you're traversing a list or a tree, is: what happens if it's null?
Related
I am stuck, I did it this way but I feel it is wrong.
(defun (find-min a b))
(cond
(> a b) (find-min b (read))
(< a b) (find-min a (read))
)
(display (find-min (read) (read)))
Code review
The code as given is badly formatted. It is really important to test your code often, to check that at least the syntax is correct. Instead of writing the code in isolation, you should ask the environment, the interpreter, to parse your code and execute it. You'll have a shorter feedback loop, which will help getting the code right.
For example, if you start your interpreter (you mentionned clisp), you are in a Read Eval Print Loop (REPL), where you write Lisp forms, which are evaluated to produce a result, which is printed. So just by writing code, it will get parsed and evaluated, which can quickly inform you about possible errors.
So if you write the code as you wrote it, you will notice that the interpreter first reads this:
(defun (find-min a b))
This is because all parentheses are balanced: the Lisp reader (the R in REPL) will build a list of two elements, namely defun and the list (find-min a b).
When evaluation is performed (the E in REPL), the list will be interpreted as a Lisp form, but this is a malformed defun.
DEFUN expects a function name, followed by a list of variable bindings, followed by the function body. So you can try writing for example:
(defun find-min (a b)
0)
This above defines a function named find-min, which accepts two parameters a and b, and always evaluate as 0 (the body of the function).
In your case you want to write:
(defun find-min (a b)
(cond ...))
You COND form is malformed too:
(cond
(> a b) (find-min b (read))
(< a b) (find-min a (read))
)
Each clause in a cond should be a list containing first a test, then zero or more expressions. So it would be:
(cond
((> a b) ...)
((< a b) ...))
Note that there is a remaining case, namely (= a b), which is not addressed.
Approach
But overall, I do not understand what your code is trying to achieve. Since all inputs are supposed to be obtained with (read), there is no need to accept arguments a and b. The whole thing could be a loop:
(defun read-min ()
(loop
for val = (read)
for zerop = (= val zero)
for min = val then (if zerop min (min min val))
until (= val 0)
finally (return min)))
As suggested by #leetwinski, there is also a shorter alternative:
(loop for val = (read) until (= val 0) minimizing val)
But I suppose you are not expected to use the loop form, so you should try to write a recursive function that does the same.
What you need to do is to pass the current minimum value ever read to your function, recursively, like so:
(defun read-min-rec (min-so-far)
...)
Lisp s-expressions are a concise and flexible way to represent code as an abstract syntax tree. Relative to the more specialized data structures used by compilers for other languages, however, they have one drawback: it is difficult to keep track of the file and line number corresponding to any particular point in the code. At least some Lisps end up just punting the problem; in the event of an error, they report source location only as far as function name, not file and line number.
Some dialects of Scheme have solved the problem by representing code not with ordinary cons cells, but with syntax objects, which are isomorphic to cons cells but can also carry additional information such as source location.
Has any implementation of Common Lisp solved this problem? If so, how?
The Common Lisp standard says very little about these things. It mentions for example that the function ed may take a function name and then open the editor with respective source code. But there is no mechanism specified and this feature is entirely provided by the development environment, possibly in combination with the Lisp system.
A typical way to deal with that is to compile a file and the compiler will record the source location of the object defined (a function, a variable, a class, ...). The source location could for example be placed on the property list of the symbol (the name of the thing defined), or recorded in some other place. Also the actual source code as a list structure can be associated with a Lisp symbol. See the function FUNCTION-LAMBDA-EXPRESSION.
Some implementations do more sophisticated source location recording. For example LispWorks can locate a specific part of a function which is currently executed. It also notes when the definition comes from an editor or a Listener. See Dspecs: Tools for Handling Definitions. The debugger then can for example locate where the code of a certain stack frame is located in the source.
SBCL also has a feature to locate source code.
Notice also that the actual 'source code' in Common Lisp is not always a text a file, but the read s-expression. eval and compile - two standard functions - don't take strings or filenames as arguments. They use the actual expressions:
CL-USER 26 > (compile 'foo (lambda (x) (1+ x)))
FOO
NIL
NIL
CL-USER 27 > (foo 41)
42
S-expressions as code are not bound to any particular textual formatting. They can be reformatted by the pretty printer function pprint and this may take available width into account to generate a layout.
So, noting the structure maybe be useful and it would be less useful to record source lines.
My understanding is that whatever data Scheme stores in the AST is data that can be associated to expressions in a CL environment.
Scheme
(defun my-simple-scheme-reader (stream)
(let ((char (read-char stream)))
(or (position char "0123456789")
(and (member char '(#\newline #\space #\tab)) :space)
(case char
(#\) :closing-paren)
(#\( (loop
with beg = (file-position stream)
for x = (my-simple-scheme-reader stream)
until (eq x :closing-paren)
unless (eq x :space)
collect x into items
finally (return (list :beg beg
:end (file-position stream)
:items items))))))))
For example:
(with-input-from-string (in "(0(1 2 3) 4 5 (6 7))")
(my-simple-scheme-reader in))
returns:
(:BEG 1 :END 20 :ITEMS
(0 (:BEG 3 :END 9 :ITEMS (1 2 3)) 4 5 (:BEG 15 :END 19 :ITEMS (6 7))))
The enriched tree represents syntax objects.
Common-Lisp
(defun make-environment ()
(make-hash-table :test #'eq))
(defun my-simple-lisp-reader (stream environment)
(let ((char (read-char stream)))
(or (position char "0123456789")
(and (member char '(#\newline #\space #\tab)) :space)
(case char
(#\) :closing-paren)
(#\( (loop
with beg = (file-position stream)
for x = (my-simple-lisp-reader stream environment)
until (eq x :closing-paren)
unless (eq x :space)
collect x into items
finally
(setf (gethash items environment)
(list :beg beg :end (file-position stream)))
(return items)))))))
Test:
(let ((env (make-environment)))
(with-input-from-string (in "(0(1 2 3) 4 5 (6 7))")
(values
(my-simple-lisp-reader in env)
env)))
Returns two values:
(0 (1 2 3) 4 5 (6 7))
#<HASH-TABLE :TEST EQL :COUNT 3 {1010524CD3}>
Given a cons cell, you can track back its original position. You can add more precise information if you want to. Once you evaluate a defun, for example, the source information can be attached to the function object, or as a symbol property, which means the information is garbage collected on redefinitions.
Remark
Note that in both cases there is no source file to keep track of, unless the system is able to track back to the original string in the source file where the reader is called.
I am trying to write my own maximum function (with 2 elements in list at present) but getting error while executing simple function as:
(defun max_for_vararg (list)
(if (null list)
(nil))
(if (> (car list) (cdr list))
(car list)
(cdr list)))
Error as:
? (max_for_vararg '(2 4))
> Error: The value (4) is not of the expected type REAL.
> While executing: CCL::>-2, in process listener(1).
> Type :POP to abort, :R for a list of available restarts.
I appreciate if someone can help me understand it. Error seems confusing to me as similar function like below is running fine but not returning max value.
(defun max_for_vararg (list)
(if (null list)
(nil))
(if (> (car list))
(car list)
(cdr list)))
Use cadr instead of cdr. Cdr gets you the rest of the list, which is a single element list. Thus, you have to call car on that list (car (cdr list)). Since this is a common thing to want to do, they made cadr a function that evaluates out to that.
There are several errors in you code. I'll give you some pointers on how to improve it.
You try to call a function named nil.
The first if has a consequence that does (nil), thus call nil as if it is a defined function. nil in other positions is the empty list so this might be an error unless you have made a function called nil.
The first if is dead code
As long as the result of the first if does not throw you into the debugger, the second if will run. Thus when the first if is fixed it will be redundant code. You really should try to have both a consequence and an alternative even though the standard doesn't require it.
(if test-1 ; predicate
test-1-true-expression ; consequent
test-1-false-expression) ; alternative
The second if should of course be one of those expressions and not something that happens unconditional to the first.
In the updated code > needs at least two arguments to be useful.
You can think of > as a function that tests if all the arguments are in descending order. (> 4) is T since all arguments are in descending order. If you find car, cadr and caddr cryptic you may want to try the aliases first, second, third instead. eg
(> (first list) (second list)) ; is first element greater than second element?
Can someone help me understand how push can be implemented as a macro? The naive version below evaluates the place form twice, and does so before evaluating the element form:
(defmacro my-push (element place)
`(setf ,place (cons ,element ,place)))
But if I try to fix this as below then I'm setf-ing the wrong place:
(defmacro my-push (element place)
(let ((el-sym (gensym))
(place-sym (gensym)))
`(let ((,el-sym ,element)
(,place-sym ,place))
(setf ,place-sym (cons ,el-sym ,place-sym)))))
CL-USER> (defparameter *list* '(0 1 2 3))
*LIST*
CL-USER> (my-push 'hi *list*)
(HI 0 1 2 3)
CL-USER> *list*
(0 1 2 3)
How can I setf the correct place without evaluating twice?
Doing this right seems to be a little more complicated. For instance, the code for push in SBCL 1.0.58 is:
(defmacro-mundanely push (obj place &environment env)
#!+sb-doc
"Takes an object and a location holding a list. Conses the object onto
the list, returning the modified list. OBJ is evaluated before PLACE."
(multiple-value-bind (dummies vals newval setter getter)
(sb!xc:get-setf-expansion place env)
(let ((g (gensym)))
`(let* ((,g ,obj)
,#(mapcar #'list dummies vals)
(,(car newval) (cons ,g ,getter))
,#(cdr newval))
,setter))))
So reading the documentation on get-setf-expansion seems to be useful.
For the record, the generated code looks quite nice:
Pushing into a symbol:
(push 1 symbol)
expands into
(LET* ((#:G906 1) (#:NEW905 (CONS #:G906 SYMBOL)))
(SETQ SYMBOL #:NEW905))
Pushing into a SETF-able function (assuming symbol points to a list of lists):
(push 1 (first symbol))
expands into
(LET* ((#:G909 1)
(#:SYMBOL908 SYMBOL)
(#:NEW907 (CONS #:G909 (FIRST #:SYMBOL908))))
(SB-KERNEL:%RPLACA #:SYMBOL908 #:NEW907))
So unless you take some time to study setf, setf expansions and company, this looks rather arcane (it may still look so even after studying them). The 'Generalized Variables' chapter in OnLisp may be useful too.
Hint: if you compile your own SBCL (not that hard), pass the --fancy argument to make.sh. This way you'll be able to quickly see the definitions of functions/macros inside SBCL (for instance, with M-. inside Emacs+SLIME). Obviously, don't delete those sources (you can run clean.sh after install.sh, to save 90% of the space).
Taking a look at how the existing one (in SBCL, at least) does things, I see:
* (macroexpand-1 '(push 1 *foo*))
(LET* ((#:G823 1) (#:NEW822 (CONS #:G823 *FOO*)))
(SETQ *FOO* #:NEW822))
T
So, I imagine, mixing in a combination of your version and what this generates, one might do:
(defmacro my-push (element place)
(let ((el-sym (gensym))
(new-sym (gensym "NEW")))
`(let* ((,el-sym ,element)
(,new-sym (cons ,el-sym ,place)))
(setq ,place ,new-sym)))))
A few observations:
This seems to work with either setq or setf. Depending on what problem you're actually trying to solve (I presume re-writing push isn't the actual end goal), you may favor one or the other.
Note that place does still get evaluated twice... though it does at least do so only after evaluating element. Is the double evaluation something you actually need to avoid? (Given that the built-in push doesn't, I'm left wondering if/how you'd be able to... though I'm writing this up before spending terribly much time thinking about it.) Given that it's something that needs to evaluate as a "place", perhaps this is normal?
Using let* instead of let allows us to use ,el-sym in the setting of ,new-sym. This moves where the cons happens, such that it's evaluated in the first evaluation of ,place, and after the evaluation of ,element. Perhaps this gets you what you need, with respect to evaluation ordering?
I think the biggest problem with your second version is that your setf really does need to operate on the symbol passed in, not on a gensym symbol.
Hopefully this helps... (I'm still somewhat new to all this myself, so I'm making some guesses here.)
I am having a problem with a lisp macro. I would like to create a macro
which generate a switch case according to an array.
Here is the code to generate the switch-case:
(defun split-elem(val)
`(,(car val) ',(cdr val)))
(defmacro generate-switch-case (var opts)
`(case ,var
,(mapcar #'split-elem opts)))
I can use it with a code like this:
(generate-switch-case onevar ((a . A) (b . B)))
But when I try to do something like this:
(defparameter *operators* '((+ . OPERATOR-PLUS)
(- . OPERATOR-MINUS)
(/ . OPERATOR-DIVIDE)
(= . OPERATOR-EQUAL)
(* . OPERATOR-MULT)))
(defmacro tokenize (data ops)
(let ((sym (string->list data)))
(mapcan (lambda (x) (generate-switch-case x ops)) sym)))
(tokenize data *operators*)
I got this error: *** - MAPCAR: A proper list must not end with OPS, but I don't understand why.
When I print the type of ops I get SYMBOL I was expecting CONS, is it related?
Also, for my function tokenize, how many times is the lambda evaluated (or the macro expanded)?
Thanks.
This makes no sense. You trying to use macros, where functions are sufficient.
What you want is similar to this:
(defun tokenize (data ops)
(mapcar (lambda (d)
(cdr (assoc d ops)))
(string->list data)))
CASE is a macro that expects a bunch of fixed clauses. It does not take clauses that are computed at runtime. If list data should drive computation, then use functions like ASSOC.
GENERATE-SWITCH-CASE is also an odd name, since the macro IS a switch case.
GENERATE-SWITCH-CASE also does expect a list as a second argument. But in TOKENIZE you call it with a symbol OPS. Remember, macros compute with Lisp source code.
Next, there are also no ARRAYs involved. Lisp has arrays, but in your example is none.
Typical advice:
if you want to write a MACRO, think again. Write it as a function.
if you still want to write a macro, Go to 1.