I'm studying Common Lisp: a gentle introduction and want to solve all the exercise.
Sometimes I have a different solution. It confuses me and I can't easily understand the standard answer of the book.
For example, with arith-eval:
My solution is :
(defun arith-eval (x)
(cond
((atom x) x)
(t (eval (cons (cadr x)
(cons (car x)
(list (arith-eval (caddr x)))))))))
The book's solution:
(defun arith-eval (exp)
(cond ((numberp exp) exp)
(t (funcall (second exp)
(arith-eval (first exp))
(arith-eval (third exp))))))
What can I do in this situation?
Your solution is a) not correct and b) using the wrong approach.
Correctness
Your function supports expressions like (1 + (2 + 3)), but not ((1 + 2) + 3).
CL-USER 6 > (arith-eval '((3 * 5) + 1))
Error: Illegal car 3 in compound form (3 * 5).
When you write such a solution, you need to think what possible arithmetic expressions are and whether your code can compute a solution. Additionally it is a good idea to think of useful test cases and run them:
CL-USER 14 > (defparameter *test-cases*
'( ( ((1 + 2) + 3) . 6)
( (1 + 2 + 3) . 6)
( (1 + (2 + 3)) . 6)))
*TEST-CASES*
CL-USER 15 > (loop for (test . result) in *test-cases*
collect (list (ignore-errors (eql (arith-eval test)
result))
test))
((NIL ((1 + 2) + 3)) ; failed
(NIL (1 + 2 + 3)) ; failed, but probably not required
(T (1 + (2 + 3))))
Approach
Your code creates a Lisp form and then calls eval, and is doing it in a recursive fashion.
First rule of solving Lisp exercises: Don't use EVAL
There is a better approach:
Since the operator symbol in the expression is already a valid Lisp function, one can just call that and provide the correct arguments. We can take advantage of the built-in evaluation and compute the arguments by calling arith-eval recursively. That's the solution in the book.
Still there might be a solution where eval makes sense:
Convert the whole expression from infix to prefix once, and then call eval (here eval can make sense).
Something like (eval (infix-to-prefix expression)).
Now one would have to write the function infix-to-prefix.
Let's start with "eval and funcall are very different beasts".
The eval function takes an S-expression and evaluates it in the "null lexical environment" (essentially, only dynamic variables are visible). The funcall function takes a function designator (either a function object or a symbol that has a function binding), and 0 or more arguments. As per normal with functions, the arguments are evaluated in the current lexical environment.
In the general case, I'd advise against using eval unless you absolutely need to, funcall or apply is almost always the right tool for this kind of problem.
Related
I'm attempting to program a simple function that adds integers to a list descending from a range of "high" and "low", incremented by "step"
For example,
if the input is (3 12 3), the expected output is '(12 9 6 3)
Below is the following code:
(define (downSeries step high low [(define ret '())])
(if (< high low)
ret
(cons ret (- high step))
(downSeries (step (- high step) low))))
I'm pretty new to racket, but I'm really not sure why this isn't compiling. Any tips? Thank you.
Since only racket is tagged and no special languages are describes it is expeted the first line in the definition window is #lang racket. Answer will be different for student languages.
1 The last argument is nested in two parentheses and is illegal syntax. Default arguments only have one set:
(define (test mandatory (optional '()))
(list mandatory optional))
(test 1) ; ==> (1 ())
(test 1 2) ; ==> (1 2)
2 You have 4 operands in your if form. It takes maximum 3!
(if prediate-expression
then-expression
else-expression)
Looking at the code you should have the cons expression in the position of ret argument. Having it before the recursion makes it dead code. ret will always be (). Eg this loks similar to a typical fold implementation:
(define (fold-1 combine init lst)
(if (null? lst)
init ; fully grown init returned
(fold-1 combine
(combine (car lst) init) ; init grows
(cdr lst))))
I would like to known how deterministic Racket's evaluation order is when set! is employed. More specifically,
Does #%app always evaluates its arguments from left to right?
If no, can the evaluation of different arguments be intertwined?
Take, for instance, this snippet:
#lang racket
(define a 0)
(define (++a) (set! a (add1 a)) a)
(list (++a) (++a)) ; => ?
Could the last expression evaluate to something different than '(1 2), such as '(1 1), '(2 2) or '(2 1)?
I failed to find a definite answer on http://docs.racket-lang.org/reference.
Unlike Scheme, Racket is guaranteed left to right. So for the example call:
(proc-expr arg-expr ...)
You can read the following in the Guide: (emphasis mine)
A function call is evaluated by first evaluating the proc-expr and all
arg-exprs in order (left to right).
That means that this program:
(define a 0)
(define (++a) (set! a (add1 a)) a)
(list (++a) (++a))
; ==> (1 2)
And it is consistent. For Scheme (2 1) is an alternative solution. You can force order by using bindings and can ensure the same result like this:
(let ((a1 (++ a)))
(list a1 (++ a)))
; ==> (1 2)
I am not very good in Lisp and I need to do a function which allows evaluating of infix expressions. For example: (+ 2 3) -> (infixFunc 2 + 3). I tried some variants, but none of them was successful.
One of them:
(defun calcPrefInf (a b c)
(funcall b a c))
OK, let's do it just for fun. First, let's define order of precedence for operations, since when one deals with infix notation, it's necessary.
(defvar *infix-precedence* '(* / - +))
Very good. Now imagine that we have a function to-prefix that will convert infix notation to polish prefix notation so Lisp can deal with it and calculate something after all.
Let's write simple reader-macro to wrap our calls of to-prefix, for aesthetic reasons:
(set-dispatch-macro-character
#\# #\i (lambda (stream subchar arg)
(declare (ignore sub-char arg))
(car (reduce #'to-prefix
*infix-precedence*
:initial-value (read stream t nil t)))))
Now, let's write a very simple function to-prefix that will convert infix notation to prefix notation in given list for given symbol.
(defun to-prefix (lst symb)
(let ((pos (position symb lst)))
(if pos
(let ((e (subseq lst (1- pos) (+ pos 2))))
(to-prefix (rsubseq `((,(cadr e) ,(car e) ,(caddr e)))
e
lst)
symb))
lst)))
Good, good. Function rsubseq may be defined as:
(defun rsubseq (new old where &key key (test #'eql))
(labels ((r-list (rest)
(let ((it (search old rest :key key :test test)))
(if it
(append (remove-if (constantly t)
rest
:start it)
new
(r-list (nthcdr (+ it (length old))
rest)))
rest))))
(r-list where)))
Now it's time to try it!
CL-USER> #i(2 + 3 * 5)
17
CL-USER> #i(15 * 3 / 5 + 10)
19
CL-USER> #i(2 * 4 + 7 / 3)
31/3
CL-USER> #i(#i(15 + 2) * #i(1 + 1))
34
etc.
If you want it to work for composite expressions like (2 + 3 * 5 / 2.4), it's better to convert it into proper prefix expression, then evaluate it. You can find some good example of code to do such convetion here: http://www.cs.berkeley.edu/~russell/code/logic/algorithms/infix.lisp or in Piter Norvigs "Paradigs of Artificial Intelligence Programming" book. Code examples here: http://www.norvig.com/paip/macsyma.lisp
It's reall too long, to be posted in the aswer.
A different approach for "evaluating infix expressions" would be to enable infix reading directly in the Common Lisp reader using the "readable" library, and then have users use the notation. Then implement a traditional Lisp evaluator (or just evaluate directly, if you trust the user).
Assuming you have QuickLisp enabled, use:
(ql:quickload "readable")
(readable:enable-basic-curly)
Now users can enter any infix expression as {a op b op c ...}, which readable automatically maps to "(op a b c ...)". For example, if users enter:
{2 + 3}
the reader will return (+ 2 3). Now you can use:
(eval (read))
Obviously, don't use "eval" if the user might be malicious. In that case, implement a function that evaluates the values the way you want them to.
Tutorial here:
https://sourceforge.net/p/readable/wiki/Common-lisp-tutorial/
Assuming that you're using a lisp2 dialect, you need to make sure you're looking up the function you want to use in the function namespace (by using #'f of (function f). Otherwise it's being looked up in the variable namespace and cannot be used in funcall.
So having the definition:
(defun calcPrefInf (a b c)
(funcall b a c))
You can use it as:
(calcPrefInf 2 #'+ 3)
You can try http://www.cliki.net/infix.
(nfx 1 + (- x 100)) ;it's valid!
(nfx 1 + (- x (3 * 3))) ;it's ALSO valid!
(nfx 1 + (- x 3 * 3)) ;err... this can give you unexpected behavior
(defun solve (L)
(cond
((null L) nil)
(t(eval (list (car (cdr L)) (car L) (car (cdr (cdr L))))))))
The code I have is a simple evaluate program that works fine as long as the input is something like '(5 + 4). However I want to be able to solve other inputs such as '(5 +( 3 - 1)) and '(6 + 5) - (4 /2 ). My problem obviously being how to handle the parentheses. I tried comparing the literal value of '( as in ((equal (car L) '( ) (solve(cdr L))) but that only throws all of my close parentheses out of whack. Is there a way to check if an atom is a parentheses?
I'm hoping that if this is a homework question, you look at Mars's comments instead of my answer. You're not going to do well if you just take my code. On the other hand, if you actually read through everything and really understand it, that's something.
Like Mars said, we need to recurse. It's simple enough; if we have a number, return it.
(defun solve (expression)
(if (atom expression)
expression
'havent-dealt-with-this-yet))
[22]> (solve '3)
3
If we've got a list, take the second thing, assume it's the operator, and eval it the way you did in our sample:
(defun solve (expression)
(if (atom expression)
expression
(eval (list (second expression)
(first expression)
(third expression)))))
[25]> (solve 3)
3
[26]> (solve '(3 + 4))
7
Cool. But here we're no further than your original code. What happens if we have a nested expression?
[27]> (solve '(3 + (2 * 2)))
*** - EVAL: 2 is not a function name; try using a symbol instead
Well, this isn't working. We can't just assume that either of (first expression) or(third expression)` are values; they may be expressions themselves. But we need to figure out the value of the expression. Let's assume we have a way to take an expression and find its value. Then our code can be:
(defun solve (expression)
(if (atom expression)
expression
(eval (list (second expression)
(find-expression-value (first expression))
(find-expression-value (third expression))))))
Wait! solve is a function that takes an expression and finds its value!
(defun solve (expression)
(if (atom expression)
expression
(eval (list (second expression)
(solve (first expression))
(solve (third expression))))))
[43]> (solve 3)
3
[44]> (solve '(3 + 2))
5
[45]> (solve '((3 + 1) * (6 / 2)))
12
ta-da!
I'm currently working on a LISP exercise for a small project and need severe help. This may be more or less of a beginner's question but I'm absolutely lost on writing a certain function that takes in two unevaluated functions and spits out the result dependent on if the variables were given an assignment or not.
An example would be
(setq p1 '(+ x (* x (- y (/ z 2)))))
Where
(evalexp p1 '( (x 2) (z 8) ))
returns (+ 2 (* 2 (- y 4)))
My goal is to write the evalexp function but I can't even think of where to start.
So far I have
(defun evalexp (e b) )
.. not very much. If anyone could please help or lead me in a good direction I'd be more than appreciative.
Here's a full solution. It's pretty straightforward, so I'll leave out a full explanation. Ask me in the comments if there's anything you can't figure out yourself.
(Using eval to do the actual evaluation might not be what you want in your exercise/project. Look up "meta-circular interpreter" for another way.)
(defun apply-env (exp env)
(reduce (lambda (exp bdg) (subst (cadr bdg) (car bdg) exp))
env :initial-value exp))
(defun try-eval (exp)
(if (atom exp)
exp
(let ((exp (mapcar #'try-eval exp)))
(if (every #'numberp (cdr exp))
(eval exp)
exp))))
(defun evalexp (exp env)
(try-eval (apply-env exp env)))
Here's a hint, this is how you might do it (in pseudocode):
function replace(vars, list):
for each element of list:
if it's an atom:
if there's an association in vars:
replace atom with value in vars
else:
leave atom alone
else:
recursively apply replace to the sublist
There will certainly be some details to work out as you convert this to Lisp code.