(car ''abracadabra) is equivalent to (car (quote (quote abracadabra)), and it evaluates to (car (quote abracadabra)) --> quote
On the othe hand (car (quote (a b))) evaluates to a, which to me makes sense intuitively.
So my question is, why does Scheme not evaluate the second quote in (car (quote (quote abracadabra)) (i.e. evaluate (car (quote abracadabra)) to (car abracadabra)), but does evaluade the quote in (car (quote (a b))) (i.e. why isn't the answer quote)?
In this expression:
(car (quote (quote abracadabra)))
=> 'quote
The inner quote doesn't get evaluated, it's just a symbol, with no particular meaning. You might as well change it for anything else, with the same results:
(car (quote (foobar abracadabra)))
=> 'foobar
Inside a quoted expression, other expressions won't get evaluated. We could use quasiquoting to force evaluation, now this will attempt to evaluate the inner quote, resulting in a different error for each case:
(car (quasiquote (unquote (quote abracadabra)))) ; (car `,(quote abracadabra))
=> car: contract violation expected: pair? given: 'abracadabra
(car (quasiquote (unquote (foobar abracadabra)))) ; (car `,(foobar abracadabra))
=> foobar: unbound identifier in module in: foobar
Scheme doesn't evaluate the inner quote because the inner quote is inside the outer quote and expressions inside a quote aren't evaluated. That is if you write (quote foo), then foo will never be evaluated - even if foo is another call to quote.
When scheme evaluates a combination it evaluates the operator. Then it will apply if it's a special form or macro. If not, it will evaluate each operands before applying.
(car (quote (quote abracadabra)))
Can be evaluated like this*
car evaluates to #<proc car>. since it's a procedure evaluate all operands in any order
(quote (quote abracadabra)) is a combination, thus
quote is evaluated => #<macro quote> and since its a macro/special form do macro-apply
apply-macro (#<macro quote> (quote abracadabra))) => (quote abracadabra)
apply-proc (#<proc car> (quote abracadabra)) => quote
*Actually Scheme can shadow any keyword so the context is very important. E.g.:
(let ((quote list) (abracadabra 'simsalabim))
(car (quote (quote abracadabra))))
==> (simsalabim)
Related
I have a struct spider:
(defstruct spider omegas values k)
And an instance spider:
(set '*spider* (make-spider
:omegas '()
:values (list *input*)
:k '(#'omegashift #'dec #'dupval '((0 . #'dec) (1 . #'inc) (2 . #'dec)))))
But when I run the expression: (listp (car (spider-k *spider*)) on Emacs and SBCL (and SLIME is involved but I'm not sure what it is.)
The REPL returns T. This is obviously confusing as (car (spider-k *spider*) correctly returns #'OMEGASHIFT and (listp (function OMEGASHIFT)) properly returns NIL.
Why is (listp (car (spider-k *spider*)) true? Shouldn't it be false?
#'omegashift is a reader-macro that expands to the list (function omegashift).
When you evaluate (function omegashift) you get a function, but you're not evaluating it because you quoted the list. So you're just getting the list that the reader-macro expands to.
You'd see the same thing if you did (listp (car '('foo))). 'foo expands to the list (quote foo). This evaluates to the symbol foo, but the quote before the list prevents evaluation.
To get functions instead of lists, you need to evaluate the function expressions. You can do this by calling the function list rather than quoting a list.
(setq *spider* (make-spider
:omegas '()
:values (list *input*)
:k (list #'omegashift #'dec #'dupval (list (cons 0 #'dec) (cons 1 #'inc) (cons 2 #'dec)))))
You can also use backquote to simplify this:
(setq *spider* (make-spider
:omegas '()
:values (list *input*)
:k `(,#'omegashift ,#'dec ,#'dupval '((0 . ,#'dec) (1 . ,#'inc) (2 . ,#'dec)))))
Inside a backquoted expression, you use comma to mark the sub-expressions that you want to evaluate.
BTW, you should use setq to assign variables, not set with a quoted symbol. They're equivalent for global variables, but you can't use set with a local variable.
I'm trying to understand the following two snippets of code:
(defun make-adder1 (n) `(lambda (x) (+ ,n x)))
(defun make-adder2 (n) (lexical-let ((n n)) (lambda (x) (+ n x))))
These both seem to produce callables:
(funcall (make-adder1 3) 5) ;; returns 8
(funcall (make-adder2 3) 5) ;; returns 8
These both work. I have two main questions:
1) I don't understand the disparity in "quoting level" between the two approaches. In the first case, the lambda expression is quoted, which means the "symbol itself" is returned instead of the value. In the second case, it seems like the statement with the lambda will get evaluated, so the value of the lambda will be returned. Yet, these both work with funcall. When using funcall on a defun'ed function, it has to be quoted. Is lexical-let doing some kind of quoting automatically? Isn't this, kind of surprising?
2) Reading other posts on this topic, I'm given to understand that the first approach will break down under certain circumstances and deviate from what one would expect from working with lambdas and higher order functions in other languages, because elisp has dynamic scoping by default. Can someone give a concrete example of code that makes this difference apparent and explain it?
In the first example there is no variable n in the resulting function, which is just (lambda (x) (+ 3 x)). It does not need lexical binding because there is no free variable in the lambda, i.e., no variable that needs to be kept in a binding of a closure. If you don't need the variable n to be available, as a variable in uses of the function, i.e., if its value at function definition time (=3) is all you need, then the first example is all you need.
(fset 'ad1 (make-adder1 3))
(symbol-function 'ad1)
returns:
(lambda (x) (+ 3 x))
The second example creates what is, in effect, a function that creates and applies a complicated closure.
(fset 'ad2 (make-adder2 3))
(symbol-function 'ad2)
returns
(lambda (&rest --cl-rest--)
(apply (quote (closure ((--cl-n-- . --n--) (n . 3) t)
(G69710 x)
(+ (symbol-value G69710) x)))
(quote --n--)
--cl-rest--))
A third option is to use a lexical-binding file-local variable and use the most straightforward definition. This creates a simple closure.
;;; foo.el --- toto -*- lexical-binding: t -*-
(defun make-adder3 (n) (lambda (x) (+ n x)))
(fset 'ad3 (make-adder3 3))
(symbol-function 'ad3)
returns:
(closure ((n . 3) t) (x) (+ n x))
(symbol-function 'make-adder1)
returns:
(lambda (n)
(list (quote lambda)
(quote (x))
(cons (quote +) (cons n (quote (x))))))
(symbol-function 'make-adder2)
returns:
(closure (t)
(n)
(let ((--cl-n-- (make-symbol "--n--")))
(let* ((v --cl-n--)) (set v n))
(list (quote lambda)
(quote (&rest --cl-rest--))
(list (quote apply)
(list (quote quote)
(function
(lambda (G69709 x)
(+ (symbol-value G69709) x))))
(list (quote quote) --cl-n--)
(quote --cl-rest--)))))
(symbol-function 'make-adder3)
returns
(closure (t) (n) (function (lambda (x) (+ n x))))
I have a function that replaces all instances of a symbol in a list:
(defun replace-symbol-in-sexp-fn (symbol-to-replace new-symbol sexp)
(if (eq sexp nil)
sexp
(cons
(if (listp (car sexp))
(replace-symbol-in-sexp-fn symbol-to-replace new-symbol (car sexp))
(if (eq (car sexp) symbol-to-replace)
(setf (car sexp) new-symbol)
(car sexp)))
(replace-symbol-in-sexp-fn symbol-to-replace new-symbol (cdr sexp)))))
(defmacro replace-symbol-in-sexp (symbol-to-replace new-symbol sexp)
`(replace-symbol-in-sexp-fn ,symbol-to-replace ,new-symbol ,sexp))
(macroexpand-1 (replace-symbol-in-sexp '+ '* (+ 2 3)))
; => TYPE-ERROR "The value 5 is not of type LIST" if sexp has comma,
; => UNBOUND-VARIABLE "The variable SEXP is unbound" if sexp has no comma
I'm getting either a type error or an undefined-variable error when attempting to evaluate the final expression, depending upon whether sexp is comma'd or not in the last line. I've tested and replace-symbol-in-sexp-fn works when given, say:
(replace-symbol-in-sexp-fn '+ '* '(+ 2 3)) ; => (* 2 3)
I'm trying to now produce this with a macro so that the sexp doesn't have to be quoted like '(+ 2 3), and so I can run replace-symbol-in-sexp-fn with arbitrary lisp code. Obviously, I could eval and pass in a sexp quoted to replace-symbol-in-sexp-fn, like:
(eval (replace-symbol-in-sexp-fn '+ '* '(+ 2 3))
But that's a clunky attempt to imitate macros, so I'd prefer to actually just use a macro. Is there a clean way to do what I'm trying to do with macros? What am I missing?
So you reimplemented the Common Lisp function nsubst. subst is the normal version and n indicates that it is the destructive version (non-consing).
Note that in portable Common Lisp it is not a good idea to modify literal data. The effects are undefined. Ignoring that for a while:
(macroexpand-1 (replace-symbol-in-sexp '+ '* (+ 2 3)))
But probably you wanted to macroexpand the expression and not the result? Probably should be:
(macroexpand-1 '(replace-symbol-in-sexp '+ '* (+ 2 3)))
But that macro makes no sense. The generated code is false, since the last argument does not evaluate to a list. The macro has to create useful code. As you see the last expression is unquoted, which make no sense.
CL-USER 14 > (macroexpand-1 '(replace-symbol-in-sexp '+ '* (+ 2 3)))
(REPLACE-SYMBOL-IN-SEXP-FN (QUOTE +) (QUOTE *) (+ 2 3))
Let's introduce a quote:
(defmacro replace-symbol-in-sexp (symbol-to-replace new-symbol sexp)
`(replace-symbol-in-sexp-fn ,symbol-to-replace ,new-symbol ',sexp))
CL-USER 17 > (macroexpand-1 '(replace-symbol-in-sexp '+ '* (+ 2 3)))
(REPLACE-SYMBOL-IN-SEXP-FN (QUOTE +) (QUOTE *) (QUOTE (+ 2 3)))
Is that macro useful? I have my doubts.
It seems that you do not want to expand to the function invocation, but use the function to expand your code. You should not quote it then:
(defmacro replace-symbol-in-sexp (symbol-to-replace new-symbol sexp)
(replace-symbol-in-sexp-fn symbol-to-replace new-symbol sexp))
I have the impression that you are just trying to re-implement something like symbol-macrolet.
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 am new to LISP programming and it is the end of semester and our teacher asked us to do this project and I have been trying to make it but I am stuck so any help would be appreciated. the Project is to write an eval (expr) function in Lisp to overwrite the already existing function. here is the details:
Project Description: Items in an arithmetic expression separated by spaces;
; Input:
; 1. The form of arithmetic expression given in prefix notation like LISP
; Assumptions:
; 1. binary operations for +, -, *, and /
; 2. integer division, no reals
; 3. an arithmetic expression occupies only one line
; 4. nested arithmetic expressions permitted
; 5. all given inputs are syntax correct
; 6. no need for error handling
I wrote a code that can do eval of the simple arithmetic expressions and it works!! but I COULD NOT get it to work on nested arithmetic operations. I think I have an issue with the recursion part i am doing something wrong but what is it exactly idk :(
here is my code :
; Assign a character string to a global variable input-prompt
; treat input-prompt as a constant global variable
(setf input-prompt "Please input an arithmetic expression: ")
(setf output-prompt "The value is: ")
(defun prompt-for-input (msg)
(format t msg)
(format t "~%")) ; ~% new line
(defun prompt-for-output (msg)
(format t msg))
(defun output-msg (result)
(format t "~S" result) ; ~S takes the result into the print message
(format t "~%"))
(defun eval (expr)
(print "My EVAL Function is Working *_*")
(if (numberp expr) expr)
(cond
((eq (car expr) '+)
(if (and (numberp (cadr expr))
(numberp (caddr expr))) ;to check if we have simple expression
(+ (cadr expr) (caddr expr)) ;in case both are numbers we add normally
(if (not (numberp (cadr expr)))
;in case the second argument is not number
;we need to call eval again to check the expression
((eval (cadr exp)))
(if (not (numberp (caddr expr)))
;in case the third argument is not a number
;we need to call eval again to check the expression
((eval (caddr exp)))
(0)))))
((eq (car expr) '-)
(if (and (numberp (cadr expr))
(numberp (caddr expr))) ;to check if we have simple expression
(- (cadr expr) (caddr expr)) ;in case both are numbers we add normally
(if (not (numberp (cadr expr)))
;in case the second argument is not number
;we need to call eval again to check the expression
((eval (cadr exp)))
(if (not (numberp (caddr expr)))
;in case the third argument is not a number
;we need to call eval again to check the expression
((eval (caddr exp)))
(0)))))
((eq (car expr) '*)
(if (and (numberp (cadr expr))
(numberp (caddr expr))) ;to check if we have simple expression
(* (cadr expr) (caddr expr)) ;in case both are numbers we add normally
(if (not (numberp (cadr expr)))
;in case the second argument is not number
;we need to call eval again to check the expression
((eval (cadr exp)))
(if (not (numberp (caddr expr)))
;in case the third argument is not a number
;we need to call eval again to check the expression
((eval (caddr exp)))
(0)))))
((eq (car expr) '/)
(if (and (numberp (cadr expr))
(numberp (caddr expr))) ;to check if we have simple expression
(/ (cadr expr) (caddr expr)) ;in case both are numbers we add normally
(if (not (numberp (cadr expr)))
;in case the second argument is not number
;we need to call eval again to check the expression
((eval (cadr exp)))
(if (not (numberp (caddr expr)))
;in case the third argument is not a number
;we need to call eval again to check the expression
((eval (caddr exp)))
(0)))))))
; it should have eval(expr) function which returns the value of the
; arithmetic expression
; for instance,
; (+ 2 3) outputs 5
; (+ (* 3 2) (/ 4 2))) outputs 8
; (* (- 2 3) 5) outputs -5
; driver accepts the input arithmetic expression
; evaluate the arithmetic expression
; output the reulst of the evaluation of the arithmetic expression
; execution is in the loop; to exit the loop; type cntrl-c
(defun driver ()
(prompt-for-input input-prompt)
;to print "Please input an arithmetic expression
(let ((expression (read)))
(output-msg expression)
(let ((result (eval expression)))
(prompt-for-output output-prompt)
(output-msg result)))
(driver))
First of all, the basic call that does the trick is ... drum roll ... -
(apply (symbol-function (car expr)) (cdr expr))
this assuming - for a moment - that all the arguments in the expression are already numbers.
This one line replaces all four cases in your code which are all exact copies of one another, up to the operation to be performed.
Now, to make sure we have numbers, we just need to call same eval on each of them. If they were numbers, they will stay as is, and if not - they'll get evaluated.
Let's just call our new function calc, for "calculate", instead:
(defun calc (expr) ; our "eval"
(cond
((numberp expr) expr)
(T (call (car expr)
(mapcar #'calc (cdr expr))))))
(defun call (op args) ; our "apply"
(apply (symbol-function op)
args))
That's all. If you consider this cheating, you can call the operation by hand, but still you don't need to copy the same block of code four times for that. :)
If you indeed write the call yourself to call the operation by hand, do note that the default value for (*) is 1, not 0; and that there's no default value for (-) and (/) in Common Lisp (as tested in CLisp). Also, (/ 2) should return 1/2.
a few hints:
Expressions like (0) are not meaningful. 0 is not a function. Similar ((foo)) also makes no sense.
you should properly format and indent Lisp code. The editor helps.
Avoid functions like CAR, CDR, CADR, ... - use FIRST, REST, SECOND, ...
don't call the function EVAL. That's a built-in function in Common Lisp.