help-gnu-emacs
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]