From: Christian Pohlmann
Subject: Graham's ACL: solution to ex 10.3
Date: 
Message-ID: <pan.2005.07.14.18.16.03.691963@yahoo.com>
Hi,

I am a lisp newbie currently reading Grahams "Ansi Common Lisp".
I have some trouble solving exercise 10.3. The reader is supposed
to write a macro which takes a number n and some expressions and
returns the nth expression evaluated. All other expressions shoud not
be evaluated.
So far I got:

(defmacro nth-expr (n &rest args)
	   `(eval (nth (1- ,n) ',args)))

I doubt this is what Graham had in mind as it uses evil eval.

thanks in advance

regards,
cp

From: Christian Pohlmann
Subject: Re: Graham's ACL: solution to ex 10.3
Date: 
Message-ID: <pan.2005.07.14.18.30.35.976444@yahoo.com>
I probably did no proper searching on google, but exactly this question
was asked here before, so please ignore this thread.
From: Pascal Bourguignon
Subject: Re: Graham's ACL: solution to ex 10.3
Date: 
Message-ID: <87br55gvp6.fsf@thalassa.informatimago.com>
Christian Pohlmann <···········@yahoo.com> writes:

> Hi,
>
> I am a lisp newbie currently reading Grahams "Ansi Common Lisp".
> I have some trouble solving exercise 10.3. The reader is supposed
> to write a macro which takes a number n and some expressions and
> returns the nth expression evaluated. All other expressions shoud not
> be evaluated.

The _student_ is supposed to _write_. The (lisp) _reader_ only reads ;-)

> So far I got:
>
> (defmacro nth-expr (n &rest args)
> 	   `(eval (nth (1- ,n) ',args)))
>
> I doubt this is what Graham had in mind as it uses evil eval.

Indeed.

When it says it returns the nth expression evaluated, it doesn't mean
the _macro_ will evaluatate the nth expression.   It means the macro
will _return_ the nth expression to have it compiled-and-evaluated or
interpreted.

A macro is but a function that returns a s-expression instead of
returning a mere value.


Let's write a function that returns it's nth+1 argument (note, that in
lisp we usually counts from 0):

(defun f-nth-expr (n &rest args)
   (nth n args))

(f-nth-expr 3 '(+ 1 2) '(- 3 4) '(* 5 6) '(/ 7 8))
--> (/ 7 8)

(f-nth-expr 1 '(+ 1 2) '(- 3 4) '(* 5 6) '(/ 7 8))
--> (- 3 4)

None of the s-expressions (+ 1 2), (- 3 4), (* 5 6), (/ 7 8) are
evaluated. One of them is selected and returned.


Now, the macro doesn't need to do more:

(defmacro nth-expr (n &rest args) (apply (function f-nth-expr) n args))

(macroexpand '(nth-expr 2 (+ 1 2) (- 3 4) (* 5 6) (/ 7 8)))
--> (* 5 6)


Of course, since f-nth-expr does nothing more than nth, we could write
instead:
(nth 3 '((+ 1 2) (- 3 4) (* 5 6) (/ 7 8)))
--> (/ 7 8)
and simplify the macro:
(defmacro nth-expr (n &rest args) (nth n args))

(macroexpand '(nth-expr 2 (+ 1 2) (- 3 4) (* 5 6) (/ 7 8)))
--> (* 5 6)

(nth-expr 2 (+ 1 2) (- 3 4) (* 5 6) (/ 7 8))
--> 30

The macro returns the s-expression (* 5 6), and the interpreter evaluates
this expression instead of (nth-expr 2 (+ 1 2) (- 3 4) (* 5 6) (/ 7 8))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Kitty like plastic.
Confuses for litter box.
Don't leave tarp around.
From: Pete Kazmier
Subject: Re: Graham's ACL: solution to ex 10.3
Date: 
Message-ID: <87hdexjeij.fsf@coco.kazmier.com>
Pascal Bourguignon <···@informatimago.com> writes:

> Christian Pohlmann <···········@yahoo.com> writes:
>
>> I am a lisp newbie currently reading Grahams "Ansi Common Lisp".
>> I have some trouble solving exercise 10.3. The reader is supposed
>> to write a macro which takes a number n and some expressions and
>> returns the nth expression evaluated. All other expressions shoud not
>> be evaluated.

[snip]

> Of course, since f-nth-expr does nothing more than nth, we could write
> instead:
> (nth 3 '((+ 1 2) (- 3 4) (* 5 6) (/ 7 8)))
> --> (/ 7 8)
> and simplify the macro:
> (defmacro nth-expr (n &rest args) (nth n args))

When I read Ansi Common Lisp (to learn CL, not for school), I did all
of the problems in the book, and I just went back to look at my answer
to 10.3.  Clearly, I hadn't solved it the way it was intended:

(defmacro nth-expr (n &rest exps)
   `(case ,n
      ,@(let ((i -1))
          (mapcar #'(lambda (exp)
                      `(,(incf i) ,exp))
                  exps))))

I suppose the compiler would have optimized this for me.  Oh well, I'm
still a newbie, but at least now I can say that I would have come up
with the better answer that Pascal provided.
From: Takehiko Abe
Subject: Re: Graham's ACL: solution to ex 10.3
Date: 
Message-ID: <keke-1607051123280001@192.168.1.2>
> (defmacro nth-expr (n &rest args) (nth n args))
> 
> (macroexpand '(nth-expr 2 (+ 1 2) (- 3 4) (* 5 6) (/ 7 8)))
> --> (* 5 6)

But this fails:

  (macroexpand '(nth-expr n (+ 1 2) (- 3 4) (* 5 6) (/ 7 8)))

> 
> (nth-expr 2 (+ 1 2) (- 3 4) (* 5 6) (/ 7 8))
> --> 30
> 
> The macro returns the s-expression (* 5 6), and the interpreter evaluates
> this expression instead of (nth-expr 2 (+ 1 2) (- 3 4) (* 5 6) (/ 7 8))

If you already know that you want (* 5 6), there's little point
to write (nth-expr ....). 

I believe the OP is supposed to write a macro that expands
to CASE or COND or IF or whatever form that select a right
expression at runtime.
From: Pascal Bourguignon
Subject: Re: Graham's ACL: solution to ex 10.3
Date: 
Message-ID: <87pstid9xr.fsf@thalassa.informatimago.com>
····@gol.com (Takehiko Abe) writes:

>> (defmacro nth-expr (n &rest args) (nth n args))
>> 
>> (macroexpand '(nth-expr 2 (+ 1 2) (- 3 4) (* 5 6) (/ 7 8)))
>> --> (* 5 6)
>
> But this fails:
>
>   (macroexpand '(nth-expr n (+ 1 2) (- 3 4) (* 5 6) (/ 7 8)))

Of course.  The OP did not specify that the macro take a symbol or an
expression. He specified it takes a number.  

        (nth-expr (mod n 4) (+ 1 2) (- 3 4) (* 5 6) (/ 7 8)))

will fail too.


>> (nth-expr 2 (+ 1 2) (- 3 4) (* 5 6) (/ 7 8))
>> --> 30
>> 
>> The macro returns the s-expression (* 5 6), and the interpreter evaluates
>> this expression instead of (nth-expr 2 (+ 1 2) (- 3 4) (* 5 6) (/ 7 8))
>
> If you already know that you want (* 5 6), there's little point
> to write (nth-expr ....). 
>
> I believe the OP is supposed to write a macro that expands
> to CASE or COND or IF or whatever form that select a right
> expression at runtime.

Ok.

(defmacro nth-expr (n &body expressions)
  `(case ,n
     ,@(let ((i -1))
          (mapcar (lambda (expr) `((,(incf i)) ,expr)) expressions))
     (otherwise (error "nth-expr: out of bounds."))))

(dotimes (n 4)
  (print (nth-expr n (+ 1 2) (- 3 4) (* 5 6) (/ 7 8))))
3 
-1 
30 
7/8 
--> NIL

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

The world will now reboot.  don't bother saving your artefacts.
From: Takehiko Abe
Subject: Re: Graham's ACL: solution to ex 10.3
Date: 
Message-ID: <keke-1707051128550001@192.168.1.2>
> Of course.  The OP did not specify that the macro take a symbol or an
> expression. He specified it takes a number.  
> 

He said it takes a number n and and did not say that the macro must
take a form that evaluates to an integer. But it is rather obvious
that the latter is what is required.