From: Wade Humeniuk
Subject: Re: ····@
Date: 
Message-ID: <z0TA9.2512$3J1.278536@news1.telusplanet.net>
It might be easier just to do away with a special character
altogether and put a special function to return within the macro.

(defmacro prog-anywhere (&body body)
  (let ((return-value (gensym)))
    `(let ((,return-value nil))
       (flet ((prog-return (value)
                           (setf ,return-value value)))
         ,@body)
       ,return-value)))

CL-USER 11 > (prog-anywhere
              (if t
                  (1+ (prog-return 10))
                (1- (prog-return 0))))
10

CL-USER 12 > (prog-anywhere
              (if nil
                  (1+ (prog-return 10))
                (1- (prog-return 0))))
0

CL-USER 13 > 

The prog-anywhere can be renamed to anything one wants.  I am
not sure how a VALUES return could be made to work.  Also the
flet could be replaced with a macrolet if one is concerned
with generating anonymous functions all over the place.

Wade

From: Wade Humeniuk
Subject: Re: ····@
Date: 
Message-ID: <7iTA9.2731$3J1.284176@news1.telusplanet.net>
This can be even simpler and work in calls down the stack.

(defvar *prog-anywhere-return* nil)

(defun prog-return (value) (setf *prog-anywhere-return* value))

(defmacro prog-anywhere (&body body)
  `(progn
     ,@body
     *prog-anywhere-return*))

Wade
From: Barry Margolin
Subject: Re: ····@
Date: 
Message-ID: <HrTA9.29$Xq1.1482@paloalto-snr1.gtei.net>
In article <·····················@news1.telusplanet.net>,
Wade Humeniuk <····@nospam.nowhere> wrote:
>
>This can be even simpler and work in calls down the stack.
>
>(defvar *prog-anywhere-return* nil)
>
>(defun prog-return (value) (setf *prog-anywhere-return* value))
>
>(defmacro prog-anywhere (&body body)
>  `(progn
>     ,@body
>     *prog-anywhere-return*))

Your previous version, with the FLET, addressed my issue of nesting these
things.

Using a global variable like this is actually worse than the OP's version.
Not only can't they nest lexically, they also can't nest dynamically.
E.g. the following won't work right:

(defun fun1 ()
  (prog-anywhere
    @ 'fun1
    (fun2)))

(defun fun2 ()
  (prog-anywhere
    @ 'fun2))

(fun1) should return FUN1, but it will return FUN2.  This is the type of
referential transparency problem that lexical scoping was designed to
solve.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Wade Humeniuk
Subject: Re: ····@
Date: 
Message-ID: <xYTA9.3038$3J1.292495@news1.telusplanet.net>
"Barry Margolin" <······@genuity.net> wrote in message
······················@paloalto-snr1.gtei.net...
> Your previous version, with the FLET, addressed my issue of nesting these
> things.
>
> Using a global variable like this is actually worse than the OP's version.
> Not only can't they nest lexically, they also can't nest dynamically.
> E.g. the following won't work right:
>
> (defun fun1 ()
>   (prog-anywhere
>     @ 'fun1
>     (fun2)))
>
> (defun fun2 ()
>   (prog-anywhere
>     @ 'fun2))
>
> (fun1) should return FUN1, but it will return FUN2.  This is the type of
> referential transparency problem that lexical scoping was designed to
> solve.

Oops, I guess that should be

(defvar *prog-anywhere-return* nil)

(defun prog-return (value) (setf *prog-anywhere-return* value))

(defmacro prog-anywhere (&body body)
  `(let (*prog-anywhere-return*)
     ,@body
     *prog-anywhere-return*))

CL-USER 3 > (defun fun2 ()
  (prog-anywhere
    (prog-return 'fun2)))

FUN2

CL-USER 4 > (defun fun1 ()
  (prog-anywhere
    (prog-return 'fun1)
    (fun2)))
FUN1

CL-USER 5 > (fun1)
FUN1

CL-USER 6 >

Wade
From: Erik Naggum
Subject: Re: ····@
Date: 
Message-ID: <3246296121410326@naggum.no>
* "Wade Humeniuk" <····@nospam.nowhere>
| This can be even simpler and work in calls down the stack.
| 
| (defvar *prog-anywhere-return* nil)
| 
| (defun prog-return (value) (setf *prog-anywhere-return* value))
| 
| (defmacro prog-anywhere (&body body)
|   `(progn
|      ,@body
|      *prog-anywhere-return*))

  Make that

(defmacro prog-anywhere (&body body)
  `(let (*prog-anywhere-return*)
     ,@body
     *prog-anywhere-return*))

-- 
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.
From: Gabe Garza
Subject: Re: ····@
Date: 
Message-ID: <87d6p7h79d.fsf@ix.netcom.com>
"Wade Humeniuk" <····@nospam.nowhere> writes:

> The prog-anywhere can be renamed to anything one wants.  I am
> not sure how a VALUES return could be made to work.  Also the
> flet could be replaced with a macrolet if one is concerned
> with generating anonymous functions all over the place.

Here's something along these lines that would allow multiple
values:

(defmacro prog-anywhere (returner-name &body body)
  (let ((return-values-list (gensym "RETURN-VALUES-LIST")))
    `(let (,return-values-list)
       (flet ((,returner-name (&rest values)
		(setf ,return-values-list values)))
	 ,@body
	 (values-list ,return-values-list)))))

* (prog-anywhere return-outer
    (multiple-value-bind (a b)
      (prog-anywhere return-inner
        1
        (return-inner 2 3)
        4
        (return-outer 5 6)
        7)
      (print (cons a b))))
(2 . 3) 
5
6
* 

Gabe Garza
From: Wade Humeniuk
Subject: Re: ····@
Date: 
Message-ID: <z2%A9.946$bh1.66205@news1.telusplanet.net>
"Gabe Garza" <·······@ix.netcom.com> wrote in message ···················@ix.netcom.com...
> (defmacro prog-anywhere (returner-name &body body)
>   (let ((return-values-list (gensym "RETURN-VALUES-LIST")))
>     `(let (,return-values-list)
>        (flet ((,returner-name (&rest values)
> (setf ,return-values-list values)))
> ,@body
> (values-list ,return-values-list)))))
> 
> * (prog-anywhere return-outer
>     (multiple-value-bind (a b)
>       (prog-anywhere return-inner
>         1
>         (return-inner 2 3)
>         4
>         (return-outer 5 6)
>         7)
>       (print (cons a b))))
> (2 . 3) 
> 5
> 6
> * 

Nice touch with the returner-name.  I get that mind altered feeling
with the example.  It feels like it would be useful in real life (a kind of 
a space connected with a whole bunch of wormholes), though I am 
don't know where.  Adds a new take on the idea of spaghetti code.


Wade
From: Pascal Costanza
Subject: Re: ····@
Date: 
Message-ID: <ar26io$gpq$1@newsreader2.netcologne.de>
Gabe Garza wrote:
> "Wade Humeniuk" <····@nospam.nowhere> writes:
> 
> 
>>The prog-anywhere can be renamed to anything one wants.  I am
>>not sure how a VALUES return could be made to work.  Also the
>>flet could be replaced with a macrolet if one is concerned
>>with generating anonymous functions all over the place.
> 
> 
> Here's something along these lines that would allow multiple
> values:
> 
> (defmacro prog-anywhere (returner-name &body body)
>   (let ((return-values-list (gensym "RETURN-VALUES-LIST")))
>     `(let (,return-values-list)
>        (flet ((,returner-name (&rest values)
> 		(setf ,return-values-list values)))
> 	 ,@body
> 	 (values-list ,return-values-list)))))

Yes, but the following still doesn't work.

 > (prog-anywhere !
      5 6 7
      (! (values 42 43 44))
      8 9 10)
42

To be able to deal with multiple values is especially important when you 
want to call a (predefined) function that returns multiple values.

Another question: I have seen (gensym "SOME-NAME") every now and then. 
My understanding of this usage of gensym is that the generated symbols 
aren't strictly unique anymore, right? Why do people still use this idiom?


Pascal

-- 
Given any rule, however �fundamental� or �necessary� for science, there 
are always circumstances when it is advisable not only to ignore the 
rule, but to adopt its opposite. - Paul Feyerabend
From: Gabe Garza
Subject: Re: ····@
Date: 
Message-ID: <878yzvgubs.fsf@ix.netcom.com>
Pascal Costanza <········@web.de> writes:
> Yes, but the following still doesn't work.
> 
>  > (prog-anywhere !
>       5 6 7
>       (! (values 42 43 44))
>       8 9 10)
> 42
> 
> To be able to deal with multiple values is especially important when
> you want to call a (predefined) function that returns multiple values.

If that's the semantics you want you could always use:

(defmacro multiple-value-prog-anywhere (returner-name &body body)
   (let ((return-values-list (gensym "RETURN-VALUES-LIST")))
     `(let (,return-values-list)
        (macrolet ((,returner-name (&body body)
   	             `(setf ,',return-values-list
			    (multiple-value-list ,@body))))
 	 ,@body
        (values-list ,return-values-list)))))

* (multiple-value-prog-anywhere !
       5 6 7
       (! (values 42 43 44))
       8 9 10)
42
43
44
* 

> Another question: I have seen (gensym "SOME-NAME") every now and
> then. My understanding of this usage of gensym is that the generated
> symbols aren't strictly unique anymore, right? Why do people still use
> this idiom?

The generated symbols are unique--that's the whole point of gensym.  I
assume you're confused over giving it a name...

In this case, I used it for ease of debugging.  Any worthy Common Lisp
environment will have a facility for macroexpanding a form so you can
see what your macros are expanding to.  For example, in ilisp if I put
the cursor before the previous example and type M-x macroexpand-lisp
the following output is displayed:

(LET (#:RETURN-VALUES-LIST2158)
  (MACROLET ((! (&BODY BODY)
               `(SETF #:RETURN-VALUES-LIST2158 (MULTIPLE-VALUE-LIST ,@BODY))))
    5 
    6
    7
    (! (VALUES 42 43 44))
    8
    9
    10
    (VALUES-LIST #:RETURN-VALUES-LIST2158)))

In this case, it's not that necessary.  But in more complicated
macros, or nested macros, etc., it can be.

Gabe Garza
From: Gabe Garza
Subject: Re: ····@
Date: 
Message-ID: <871y5ngu5t.fsf@ix.netcom.com>
Pascal Costanza <········@web.de> writes:
> Yes, but the following still doesn't work.
> 
>  > (prog-anywhere !
>       5 6 7
>       (! (values 42 43 44))
>       8 9 10)
> 42
> 
> To be able to deal with multiple values is especially important when
> you want to call a (predefined) function that returns multiple values.

If that's the semantics you want you could always use:

(defmacro multiple-value-prog-anywhere (returner-name &body body)
   (let ((return-values-list (gensym "RETURN-VALUES-LIST")))
     `(let (,return-values-list)
        (macrolet ((,returner-name (form)
                    `(setf ,',return-values-list
			    (multiple-value-list ,form))))
 	 ,@body
        (values-list ,return-values-list)))))

* (multiple-value-prog-anywhere !
       5 6 7
       (! (values 42 43 44))
       8 9 10)
42
43
44
* 

> Another question: I have seen (gensym "SOME-NAME") every now and
> then. My understanding of this usage of gensym is that the generated
> symbols aren't strictly unique anymore, right? Why do people still use
> this idiom?

The generated symbols are unique--that's the whole point of gensym.  I
assume you're confused over giving it a name...

In this case, I used it for ease of debugging.  Any worthy Common Lisp
environment will have a facility for macroexpanding a form so you can
see what your macros are expanding to.  For example, in ilisp if I put
the cursor before the previous example and type M-x macroexpand-lisp
the following output is displayed:

(LET (#:RETURN-VALUES-LIST2158)
  (MACROLET ((! (&BODY BODY)
               `(SETF #:RETURN-VALUES-LIST2158 (MULTIPLE-VALUE-LIST ,@BODY))))
    5 
    6
    7
    (! (VALUES 42 43 44))
    8
    9
    10
    (VALUES-LIST #:RETURN-VALUES-LIST2158)))

In this case, it's not that necessary.  But in more complicated
macros, or nested macros, etc., it can be.

Gabe Garza
From: Pascal Costanza
Subject: Re: ····@
Date: 
Message-ID: <ar2aos$p16$1@newsreader2.netcologne.de>
Gabe Garza wrote:
> Pascal Costanza <········@web.de> writes:
> 

>>Another question: I have seen (gensym "SOME-NAME") every now and
>>then. My understanding of this usage of gensym is that the generated
>>symbols aren't strictly unique anymore, right? Why do people still use
>>this idiom?
> 
> 
> The generated symbols are unique--that's the whole point of gensym.  I
> assume you're confused over giving it a name...
> 

No, it's about the uniqueness. In the example you have given, it may be 
the case that RETURN-VALUES-LIST2158 has already existed before. As far 
as I understand the HyperSpec a Common Lisp implementation is not 
required to take the necessary precautions against this case (whereas 
(gensym) without a string argument is always guaranteed to be unique). 
Right?

> (LET (#:RETURN-VALUES-LIST2158)
>   (MACROLET ((! (&BODY BODY)
>                `(SETF #:RETURN-VALUES-LIST2158 (MULTIPLE-VALUE-LIST ,@BODY))))
>     5 
>     6
>     7
>     (! (VALUES 42 43 44))
>     8
>     9
>     10
>     (VALUES-LIST #:RETURN-VALUES-LIST2158)))

Pascal

-- 
Given any rule, however �fundamental� or �necessary� for science, there 
are always circumstances when it is advisable not only to ignore the 
rule, but to adopt its opposite. - Paul Feyerabend
From: Christophe Rhodes
Subject: Re: ····@
Date: 
Message-ID: <sqznsbci8x.fsf@lambda.jcn.srcf.net>
Pascal Costanza <········@web.de> writes:

> Gabe Garza wrote:
> > Pascal Costanza <········@web.de> writes:
> >
> 
> >>Another question: I have seen (gensym "SOME-NAME") every now and
> >>then. My understanding of this usage of gensym is that the generated
> >>symbols aren't strictly unique anymore, right? Why do people still use
> >>this idiom?
> > The generated symbols are unique--that's the whole point of gensym.
> > I
> > assume you're confused over giving it a name...
> >
> 
> No, it's about the uniqueness. In the example you have given, it may
> be the case that RETURN-VALUES-LIST2158 has already existed before. As
> far as I understand the HyperSpec a Common Lisp implementation is not
> required to take the necessary precautions against this case (whereas
> (gensym) without a string argument is always guaranteed to be
> unique). Right?

Wrong.

A symbol with the name RETURN-VALUES-LIST2158 may already have
existed; however, it is a different symbol from the one returned by
gensym.  The CLHS page on gensym makes this clear, when it says that
the return value is a "fresh, uninterned symbol".

  * '#:foo-1                  -> #:FOO-1
  * (setf *gensym-counter* 1) -> 1
  * (gensym "FOO-")           -> #:FOO-1
  * (eq * ***)                -> NIL

Cheers,

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)
From: Pascal Costanza
Subject: Re: ····@
Date: 
Message-ID: <3DD4C733.1060500@web.de>
Christophe Rhodes wrote:
> Pascal Costanza <········@web.de> writes:
> 
> 
>>Gabe Garza wrote:
>>
>>>Pascal Costanza <········@web.de> writes:
>>>
>>
>>>>Another question: I have seen (gensym "SOME-NAME") every now and
>>>>then. My understanding of this usage of gensym is that the generated
>>>>symbols aren't strictly unique anymore, right? Why do people still use
>>>>this idiom?
>>>
>>>The generated symbols are unique--that's the whole point of gensym.
>>>I
>>>assume you're confused over giving it a name...
>>>
>>
>>No, it's about the uniqueness. In the example you have given, it may
>>be the case that RETURN-VALUES-LIST2158 has already existed before. As
>>far as I understand the HyperSpec a Common Lisp implementation is not
>>required to take the necessary precautions against this case (whereas
>>(gensym) without a string argument is always guaranteed to be
>>unique). Right?
> 
> 
> Wrong.
> 
> A symbol with the name RETURN-VALUES-LIST2158 may already have
> existed; however, it is a different symbol from the one returned by
> gensym.  The CLHS page on gensym makes this clear, when it says that
> the return value is a "fresh, uninterned symbol".
> 
>   * '#:foo-1                  -> #:FOO-1
>   * (setf *gensym-counter* 1) -> 1
>   * (gensym "FOO-")           -> #:FOO-1
>   * (eq * ***)                -> NIL

Now I am really confused. How does a macro treat uninterned symbols, how 
are they evaluated.

I have tried the following.

(defmacro test ()
   (let ((bla #:bla))
     `(let ((,bla '(1 2 3))
        (pprint ,bla))))

 > (test)
(1 2 3)

 > (macroexpand +)
(LET ((#:BLA (QUOTE (1 2 3)))) (PPRINT #:BLA))

 > (LET ((#:BLA (QUOTE (1 2 3)))) (PPRINT #:BLA))
Error: The variable #:BLA is unbound.

Huh?!? Of course, #:BLA is an uninterned symbol, but why does the macro 
'test work in the first place?

Then again:

(defmacro test ()
   `(let ((#:BLA '(1 2 3)))
      (pprint #:BLA)))

 > (test)
Error: The variable #:BLA is unbound.

?!?

I have tried to find a clue in the HyperSpec sections about macros, 
symbols, evaluation, backquote and even packages, but I haven't found an 
explanation. So basically I am stuck. What's going on here?


Pascal

-- 
Pascal Costanza               University of Bonn
···············@web.de        Institute of Computer Science III
http://www.pascalcostanza.de  R�merstr. 164, D-53117 Bonn (Germany)
From: Christophe Rhodes
Subject: Re: ····@
Date: 
Message-ID: <sqvg2zcf4v.fsf@lambda.jcn.srcf.net>
Pascal Costanza <········@web.de> writes:

> Christophe Rhodes wrote:
> > Pascal Costanza <········@web.de> writes:
> >>No, it's about the uniqueness. In the example you have given, it may
> >>be the case that RETURN-VALUES-LIST2158 has already existed before. As
> >>far as I understand the HyperSpec a Common Lisp implementation is not
> >>required to take the necessary precautions against this case (whereas
> >>(gensym) without a string argument is always guaranteed to be
> >>unique). Right?
> > Wrong.
> > A symbol with the name RETURN-VALUES-LIST2158 may already have
> > existed; however, it is a different symbol from the one returned by
> > gensym.  The CLHS page on gensym makes this clear, when it says that
> > the return value is a "fresh, uninterned symbol".
> >   * '#:foo-1                  -> #:FOO-1
> >   * (setf *gensym-counter* 1) -> 1
> >   * (gensym "FOO-")           -> #:FOO-1
> >   * (eq * ***)                -> NIL
> 
> Now I am really confused. How does a macro treat uninterned symbols,
> how are they evaluated.
> 
> I have tried the following.
> 
> (defmacro test ()
>    (let ((bla #:bla))
>      `(let ((,bla '(1 2 3))
>         (pprint ,bla))))
> 
>  > (test)
> (1 2 3)
> 
>  > (macroexpand +)
> (LET ((#:BLA (QUOTE (1 2 3)))) (PPRINT #:BLA))

Hmm.  Rewriting for the sake of posterity:
  (defmacro test ()
    (let ((bla '#:bla))
      `(let ((,bla '(1 2 3)))
         (pprint ,bla))))
Then
  (macroexpand '(test))
gives
  (LET ((#:BLA '(1 2 3)))
    (PPRINT #:BLA))
So, why does this not work when typed in?  Well, think about object
identity.  In the macroexpansion, the two things that have printed as
#:BLA are the same symbol; if you type this in, you get two different
uninterned symbols with the name "BLA".  To see this:
  (setf *print-circle* t)
  (macroexpand '(test))
gives
  (LET ((#1=#:BLA '(1 2 3)))
    (PPRINT #1#))

Two different symbols can have the same name, and can print the same.

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)
From: Pascal Costanza
Subject: Re: ····@
Date: 
Message-ID: <3DD4CC15.5000401@web.de>
Christophe Rhodes wrote:
> Pascal Costanza <········@web.de> writes:

>>Now I am really confused. How does a macro treat uninterned symbols,
>>how are they evaluated.
>>
> 
> 
> Hmm.  Rewriting for the sake of posterity:
>   (defmacro test ()
>     (let ((bla '#:bla))
>       `(let ((,bla '(1 2 3)))
>          (pprint ,bla))))

Er, yes, that's what I meant.

> Then
>   (macroexpand '(test))
> gives
>   (LET ((#:BLA '(1 2 3)))
>     (PPRINT #:BLA))
> So, why does this not work when typed in?  Well, think about object
> identity.  In the macroexpansion, the two things that have printed as
> #:BLA are the same symbol; if you type this in, you get two different
> uninterned symbols with the name "BLA".

Oh dear - yes, that's clear as daylight! Now I also understand why 
(gensym "SOME-NAME") is safe.

Thanks a lot indeed!

Pascal

-- 
Pascal Costanza               University of Bonn
···············@web.de        Institute of Computer Science III
http://www.pascalcostanza.de  R�merstr. 164, D-53117 Bonn (Germany)
From: Frode Vatvedt Fjeld
Subject: Re: ····@
Date: 
Message-ID: <2hisyz9la3.fsf@vserver.cs.uit.no>
Pascal Costanza <········@web.de> writes:

> Now I am really confused. How does a macro treat uninterned symbols,
> how are they evaluated.

Just like any other symbols. It is mostly the reader and printer that
deals specially with uninterned symbols:

  (eq '#:foo '#:foo) => NIL

-- 
Frode Vatvedt Fjeld