[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: About `setf' with macro call
From: |
Tassilo Horn |
Subject: |
Re: About `setf' with macro call |
Date: |
Wed, 17 Apr 2013 16:06:42 +0200 |
User-agent: |
Gnus/5.130006 (Ma Gnus v0.6) Emacs/24.3.50 (gnu/linux) |
xfq <xfq.free@gmail.com> writes:
> In (info "(cl) Setf Extensions"), there is a example about using `setf'
> on a macro call:
>
> (defmacro wrong-order (x y) (list 'aref y x))
> (setf (wrong-order A B) 17)
>
> I evaluated these two expressions, and debugger entered:
>
> Debugger entered--Lisp error: (void-variable B)
> (let* ((v B) (v A)) (aset v v 17))
> (setf (wrong-order A B) 17)
> eval((setf (wrong-order A B) 17) nil)
> eval-last-sexp-1(nil)
> eval-last-sexp(nil)
> call-interactively(eval-last-sexp nil nil)
> command-execute(eval-last-sexp)
>
> I understand that `A' and `B' are two invalid S-expressions here. But
> I don't understand the `let*' expression in the backtrace.
You need to have a look at the macro expansions to understand the
problem.
--8<---------------cut here---------------start------------->8---
ELISP> (macroexpand '(wrong-order A B))
(aref B A)
ELISP> (macroexpand '(setf (wrong-order A B) 17))
(let*
((v B)
(v A))
(aset v v 17))
--8<---------------cut here---------------end--------------->8---
Now that explains the let* in the backtrace, but the setf-expansion
looks totally wrong! v is set to B (the index) and then overridden by A
(the array). So aset becomes called with the array, the array again in
place where the index should be, and then the value to be set...
Let's try it with an example:
--8<---------------cut here---------------start------------->8---
ELISP> (defvar my-array (make-vector 10 1))
my-array
ELISP> my-array
[1 1 1 1 1 1 1 1 1 1]
ELISP> (setf (aref my-array 4) 3)
3
ELISP> my-array
[1 1 1 1 3 1 1 1 1 1]
ELISP> (setf (wrong-order 4 my-array) 17)
17
ELISP> my-array
[1 1 1 1 17 1 1 1 1 1]
--8<---------------cut here---------------end--------------->8---
Strange. Although the macro expansion looks broken, it works anyhow?!
Now let's test the macro expansion manually.
--8<---------------cut here---------------start------------->8---
ELISP> (let* ((v 4) (v my-array)) (aset v v 19))
*** Eval error *** Wrong type argument: integerp, [1 1 1 1 17 1 1 1 1 1]
--8<---------------cut here---------------end--------------->8---
Yes, that's what I expected also from the macro version...
Can anyone explain what's going on here?
Bye,
Tassilo