From: verec
Subject: #0= ... #0#
Date: 
Message-ID: <43fc6d9c$0$1173$5a6aecb4@news.aaisp.net.uk>
I've seen uses of this #n= #n# construct in some posts
here in c.l.l, but I couldn't find anything about it in
the CLHS, though I did find a basic explanation in CLTL2
page 537.

This looks a lot like "C language level" macros, but I'm
wondering what typical uses people have for it.

So far, the only use I have seen, is as a way to avoid
duplicating form#3 from form#2 inside a (do (...

Any other typical use?

Many thanks
--
JFB

From: Tayssir John Gabbour
Subject: Re: #0= ... #0#
Date: 
Message-ID: <1140618485.409026.117680@f14g2000cwb.googlegroups.com>
Hyperspec entry: http://www.lisp.org/HyperSpec/Body/sec_2-4-8-16.html

Dunno, I've seen people create infinite lists full of stuff, though not
using this read syntax...

http://groups.google.com/group/comp.lang.lisp/msg/d77790200cff78ad
  ;; handy tool for MAPCAR...
  (defun infinite-list (&rest items)
    (setf (rest (last items)) items))

  (setf anagrams
        (mapcar #'sort anagrams (infinite-list #'string-lessp)))


I suppose if you represented graphs in sexp notation often, you'd use
this.

Might be an entertaining way to program without conventional looping or
recursive constructs. I wonder whether compilers would survive
confrontations with this technique.


Tayssir
--

Do you like the metaobject protocol?

"The medieval Scholastics distinguished two kinds of logical terms:
first intentions include words that refer to concrete things, and
second intentions refer to linguistic entities like properties and
propositions."
Sowa, _Knowledge Representation_, p. 27
From: Alan Crowe
Subject: Re: #0= ... #0#
Date: 
Message-ID: <86irr71eeh.fsf@cawtech.freeserve.co.uk>
"Tayssir John Gabbour" <···········@yahoo.com> writes:
> Might be an entertaining way to program without conventional looping or
> recursive constructs. I wonder whether compilers would survive
> confrontations with this technique.

It can be quite natural. From my Seal Song code:

(defparameter pitch-circle '#1=(#\A #\B #\C #\D #\E #\F #\G . #1#))

(defun scale-letters (starting-letter)
  (subseq (member starting-letter pitch-circle) 0 7))

(scale-letters #\E) => (#\E #\F #\G #\A #\B #\C #\D)

Alan Crowe
Edinburgh
Scotland
From: Tayssir John Gabbour
Subject: Re: #0= ... #0#
Date: 
Message-ID: <1140631863.998281.23730@z14g2000cwz.googlegroups.com>
Alan Crowe wrote:
> "Tayssir John Gabbour" <···········@yahoo.com> writes:
> > Might be an entertaining way to program without conventional looping or
> > recursive constructs. I wonder whether compilers would survive
> > confrontations with this technique.
>
> It can be quite natural. From my Seal Song code:
>
> (defparameter pitch-circle '#1=(#\A #\B #\C #\D #\E #\F #\G . #1#))
>
> (defun scale-letters (starting-letter)
>   (subseq (member starting-letter pitch-circle) 0 7))
>
> (scale-letters #\E) => (#\E #\F #\G #\A #\B #\C #\D)

Great illustration, but I meant something a bit more evil like:

#1=(if (key-pressed)
       'done!
       #1#)


Tayssir
From: Pascal Bourguignon
Subject: Re: #0= ... #0#
Date: 
Message-ID: <87y803rzlm.fsf@thalassa.informatimago.com>
"Tayssir John Gabbour" <···········@yahoo.com> writes:
> Great illustration, but I meant something a bit more evil like:
>
> #1=(if (key-pressed)
>        'done!
>        #1#)

This will lead to infinite loops in the compilers, most often.


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

Pour moi, la grande question n'a jamais �t�: �Qui suis-je? O� vais-je?� 
comme l'a formul� si adroitement notre ami Pascal, mais plut�t: 
�Comment vais-je m'en tirer?� -- Jean Yanne
From: Alan Crowe
Subject: Re: #0= ... #0#
Date: 
Message-ID: <86fymb117c.fsf@cawtech.freeserve.co.uk>
"Tayssir John Gabbour" <···········@yahoo.com> writes:
> Alan Crowe wrote:
> > It can be quite natural. From my Seal Song code:
> >
> > (defparameter pitch-circle '#1=(#\A #\B #\C #\D #\E #\F #\G . #1#))
> >
> > (defun scale-letters (starting-letter)
> >   (subseq (member starting-letter pitch-circle) 0 7))
> >
> > (scale-letters #\E) => (#\E #\F #\G #\A #\B #\C #\D)
> 
> Great illustration, but I meant something a bit more evil like:
> 
> #1=(if (key-pressed)
>        'done!
>        #1#)

I cannot offer you anything that depraved but there is an
interesting point that I only recently noticed.

Take the issue in another thread about an idiom for reading
lines from a file. LOOP wins over DO because you can say

(loop for line = (read-line stream nil nil) ...

but with DO you have to repeat yourself

(do ((line (read-line stream nil nil)
           (read-line stream nil nil)))
    ...

That gives rise to the idea of writing

(do ((line #1=(read-line stream nil nil)
           #1#))
    ...

And that in turn gives rise to the worry: will the compiler
cope?

It is tempting to answer this worry by writing a macro to do
the duplicating for you

CL-USER> (defmacro relet ((var form) &body code)
           `(do ((,var ,form ,form))
             ((null ,var))
             ,@code))

CL-USER> (defvar form '(relet (x (fetch it))
                        (process x)))

CL-USER> (macroexpand-1 form)
(DO ((X (FETCH IT) (FETCH IT))) ((NULL X)) (PROCESS X))

This looks at first glance as if the macroexander has sat
there typing away at its inner keyboard, typing out 
(fetch it) twice, thus resolving any concerns about whether
the compiler will cope.

However turning on *print-circle* tells a different story:

CL-USER> (write (macroexpand-1 form)
                :circle t)
(DO ((X #1=(FETCH IT) #1#)) ((NULL X)) (PROCESS X))

The macro has built a confluent data structure. I believe
that this is quite typical and gives an unexpected
reassurance: Common Lisp compilers must be able to
cope with confuent data structures or else many macros would fail.

Look for example at #1# and #2# in the way that CMUCL
expands a loop

CL-USER> (macroexpand '(loop for i = (foo) until i do (bar i)))
(BLOCK NIL
  (LET ((I NIL))
    (ANSI-LOOP::LOOP-BODY NIL
                          (NIL (ANSI-LOOP::LOOP-REALLY-DESETQ I #1=(FOO)) NIL
                           NIL #2=(WHEN I (GO ANSI-LOOP::END-LOOP)))
                          ((BAR I))
                          (NIL (ANSI-LOOP::LOOP-REALLY-DESETQ I #1#) NIL NIL
                           #2#)
                          NIL)))
Alan Crowe
Edinburgh
Scotland
      
From: Brian Downing
Subject: Re: #0= ... #0#
Date: 
Message-ID: <o4cLf.573379$084.239251@attbi_s22>
In article <··············@cawtech.freeserve.co.uk>,
Alan Crowe  <····@cawtech.freeserve.co.uk> wrote:
[...]
> but with DO you have to repeat yourself
> 
> (do ((line (read-line stream nil nil)
>            (read-line stream nil nil)))
>     ...
> 
> That gives rise to the idea of writing
> 
> (do ((line #1=(read-line stream nil nil)
>            #1#))
>     ...
> 
> And that in turn gives rise to the worry: will the compiler
> cope?

Any compiler that's not really broken should cope with that.  Only
circularly recursive structures cause problems.  Evaluating circular
code produces possibly infinite execution, but /compiling/ circular code
produces possibly infinite code, which is obviously less useful.

I suppose one could design a compiler to detect some circular structures
and turn them into loops, but why?

It'd be hard work to make a compiler that would generate finite code
for #1=(if (zerop (random 10)) 'done #1#).  It would also be hard work
to make a compiler that would break on (* #1=(+ 2 2) #1#).

-bcd
-- 
*** Brian Downing <bdowning at lavos dot net> 
From: Joe Marshall
Subject: Re: #0= ... #0#
Date: 
Message-ID: <1140714164.868015.186470@g44g2000cwa.googlegroups.com>
Brian Downing wrote:
>
> Any compiler that's not really broken should cope with that.  Only
> circularly recursive structures cause problems.  Evaluating circular
> code produces possibly infinite execution, but /compiling/ circular code
> produces possibly infinite code, which is obviously less useful.
>
> I suppose one could design a compiler to detect some circular structures
> and turn them into loops, but why?
>
> It'd be hard work to make a compiler that would generate finite code
> for #1=(if (zerop (random 10)) 'done #1#).  It would also be hard work
> to make a compiler that would break on (* #1=(+ 2 2) #1#).

I recall reading a paper sometime in the past few years that discussed
the semantics of circular structure in the source code.  If I recall
correctly, they were able to get the compiler to handle the problem by
treating it as syntactic fixed-point operation.  Unfortunately, I've
forgotten the reference and a cursory search via Google isn't turning
it up.
From: Jens Axel Søgaard
Subject: Re: #0= ... #0#
Date: 
Message-ID: <43fdf1cd$0$38668$edfadb0f@dread12.news.tele.dk>
Joe Marshall wrote:

> I recall reading a paper sometime in the past few years that discussed
> the semantics of circular structure in the source code.  If I recall
> correctly, they were able to get the compiler to handle the problem by
> treating it as syntactic fixed-point operation.  Unfortunately, I've
> forgotten the reference and a cursory search via Google isn't turning
> it up.

Christian Queinnec has shown how to compile such programs in
"Compiling Syntactically Recursive Programs":

     <http://youpou.lip6.fr/queinnec/Papers/synrec.ps.gz>

It does so by rewriting into normal Lisp, which incidently show
that you don't gain in expressitivity by allowing recursive
syntax.

-- 
Jens Axel S�gaard
From: Rob Warnock
Subject: Re: #0= ... #0#
Date: 
Message-ID: <_6qdnZhcvOQrBGDe4p2dnA@speakeasy.net>
Alan Crowe  <····@cawtech.freeserve.co.uk> wrote:
+---------------
| It can be quite natural. From my Seal Song code:
| (defparameter pitch-circle '#1=(#\A #\B #\C #\D #\E #\F #\G . #1#))
+---------------

I did something similar in my "CrazyString" HTML hack:

    http://rpw3.org/hacks/lisp/crazystring.html
    http://rpw3.org/hacks/lisp/crazystring.lisp
    ...
    (defconstant +crazy-string-defaults+
		 '#1=(("#0000FF" nil "6")
		      ("#FF0000" sub "6")
		      ("#00FF00" sup "6")
		      ("#c08000" nil "6")
		      ("#0000FF" sub "6")
		      ("#FF0000" sup "6")
		      ("#00FF00" nil "6")
		      ("#c08000" sup "6") . #1#))  ; and so on, forever...
    ...

Here the idea was to simply CDR down the list of character
attributes [color, supescript/subscript/none, size] without
having to worry about the length of the input text to which
the attributes were to be applied.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Thomas A. Russ
Subject: Re: #0= ... #0#
Date: 
Message-ID: <ymihd6pc0ru.fsf@sevak.isi.edu>
Alan Crowe <····@cawtech.freeserve.co.uk> writes:

> 
> It can be quite natural. From my Seal Song code:
> 
> (defparameter pitch-circle '#1=(#\A #\B #\C #\D #\E #\F #\G . #1#))
> 
> (defun scale-letters (starting-letter)
>   (subseq (member starting-letter pitch-circle) 0 7))
> 
> (scale-letters #\E) => (#\E #\F #\G #\A #\B #\C #\D)

Nice.

I would observe that a similar technique can be used for other recurring
patterns such as days of the week or months of the year.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Chris Riesbeck
Subject: Re: #0= ... #0#
Date: 
Message-ID: <463r5cF96439U1@individual.net>
verec wrote:
> I've seen uses of this #n= #n# construct in some posts
> here in c.l.l, but I couldn't find anything about it in
> the CLHS, though I did find a basic explanation in CLTL2
> page 537.
> 
> This looks a lot like "C language level" macros, but I'm
> wondering what typical uses people have for it.
> 
> So far, the only use I have seen, is as a way to avoid
> duplicating form#3 from form#2 inside a (do (...
> 
> Any other typical use?

Most important, IMO, is it gives the printer a way to print circular 
lists re-readably.
From: ········@gmail.com
Subject: Re: #0= ... #0#
Date: 
Message-ID: <1140643730.199231.40220@g43g2000cwa.googlegroups.com>
> This looks a lot like "C language level" macros, but I'm
> wondering what typical uses people have for it.

Some examples:
http://bc.tech.coop/blog/051228.html

--
Bill Clementson
From: verec
Subject: Re: #0= ... #0#
Date: 
Message-ID: <43fe2a96$0$1174$5a6aecb4@news.aaisp.net.uk>
On 2006-02-22 21:28:50 +0000, ········@gmail.com said:

>> This looks a lot like "C language level" macros, but I'm
>> wondering what typical uses people have for it.
> 
> Some examples:
> http://bc.tech.coop/blog/051228.html

Wahoo! Many thanks.
--
JFB
From: Pascal Bourguignon
Subject: Re: #0= ... #0#
Date: 
Message-ID: <87accjtqkj.fsf@thalassa.informatimago.com>
verec <·····@mac.com> writes:

> I've seen uses of this #n= #n# construct in some posts
> here in c.l.l, but I couldn't find anything about it in
> the CLHS, though I did find a basic explanation in CLTL2
> page 537.

http://www.lispworks.com/documentation/HyperSpec/Body/02_dho.htm
http://www.lispworks.com/documentation/HyperSpec/Body/02_dhp.htm


> This looks a lot like "C language level" macros, 

Not really.

> but I'm wondering what typical uses people have for it.
>
> So far, the only use I have seen, is as a way to avoid
> duplicating form#3 from form#2 inside a (do (...
>
> Any other typical use?

In general, to share substructures:

[97]> (defparameter s '(#1=(a b c) #1# (x #1# y)))
s
[98]> (eq (first s) (second s))
t

In particular, to build circular structures:

[100]> (defparameter s '(a b c . #1=(d e f . #1#)))
s
[101]> s
(a b c . #1=(d e f . #1#))
[102]> (loop for i in s repeat 10 do (princ i) (princ " ") finally (terpri))
a b c d e f d e f d 
nil


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

The world will now reboot.  don't bother saving your artefacts.