From: szergling
Subject: Circular structures in macros
Date: 
Message-ID: <1179201353.937930.213770@l77g2000hsb.googlegroups.com>
Hello language lawyers,

I have a few queries regarding circular code (or is that data? (: )
structures.

(loop repeat 10 for x in '#1=(1 2 3 . #1#) collect x)

The code above works fine. The one below the other hand doesn't
(assume I have a good reason to want to use a macro). clisp-2.41 goes
into an infinite loop.

(defmacro test ()
  `(loop
      repeat 10
      for x in '#1=(1 2 3 . #1#)
      collect x))

Is this sort of behaviour specified anywhere? Any pointers? Could it
be a clisp bug? I found this post (read the one after it too)

http://groups.google.com/group/comp.lang.lisp/msg/03057a4f1efd0ad5

but I don't think it's quite the same case here...

-----------------------------
On a side note, just out of whimsy, does anyone know how I can do
this using the #num and #num# notation?

;; Untested at repl
(defclass test () ((self :initarg :self)))

#1=(make-instance 'test :self #1#) ;; infinite code loop.

This is not quite right because #1 gets bound to the list
'(make-instance ...), not the object obtained by evaluating that
list. This one is purely for fun - there's no practical value
whatsoever.

From: Pascal Bourguignon
Subject: Re: Circular structures in macros
Date: 
Message-ID: <87fy5yhai1.fsf@thalassa.lan.informatimago.com>
szergling <···············@gmail.com> writes:

> Hello language lawyers,
>
> I have a few queries regarding circular code (or is that data? (: )
> structures.
>
> (loop repeat 10 for x in '#1=(1 2 3 . #1#) collect x)
>
> The code above works fine. The one below the other hand doesn't
> (assume I have a good reason to want to use a macro). clisp-2.41 goes
> into an infinite loop.
>
> (defmacro test ()
>   `(loop
>       repeat 10
>       for x in '#1=(1 2 3 . #1#)
>       collect x))
>
> Is this sort of behaviour specified anywhere? Any pointers? Could it
> be a clisp bug? I found this post (read the one after it too)

This is not a bug: you elicited undefined behavior when you gave the
compiler a form with cycles.  In particular, the clisp compiler enters
an infinite loop here, because when you have a backquote, it must scan
the whole structure to see where there are commas to splice in.  
The above form worked well only because the compiler didn't need to
scan it.

On the other hand,

(defun test (list)
   (loop :repeat 10
         :for x :in list
         :collect list))

(test '#1=(1 2 3 . #1#))

will work, because when compiling test, there is no circle, in the
source of test.


> http://groups.google.com/group/comp.lang.lisp/msg/03057a4f1efd0ad5
>
> but I don't think it's quite the same case here...



> On a side note, just out of whimsy, does anyone know how I can do
> this using the #num and #num# notation?
>
> ;; Untested at repl
> (defclass test () ((self :initarg :self)))
>
> #1=(make-instance 'test :self #1#) ;; infinite code loop.
>
> This is not quite right because #1 gets bound to the list
> '(make-instance ...), not the object obtained by evaluating that
> list. This one is purely for fun - there's no practical value
> whatsoever.

This is not possible: you cannot pass the result of a function call as
argument to this same function call, unless you have a time machine.

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

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.
From: Greg Buchholz
Subject: Re: Circular structures in macros
Date: 
Message-ID: <1179253409.446195.308610@h2g2000hsg.googlegroups.com>
On May 14, 11:22 pm, Pascal Bourguignon <····@informatimago.com>
wrote:
>
> This is not possible: you cannot pass the result of a function call as
> argument to this same function call, unless you have a time machine.

...or lazy evaluation.

http://www.haskell.org/hawiki/TyingTheKnot
From: Dan Bensen
Subject: Re: Circular structures in macros
Date: 
Message-ID: <f2cvp1$72t$1@wildfire.prairienet.org>
> On May 14, 11:22 pm, Pascal Bourguignon <····@informatimago.com>
> wrote:
>> This is not possible: you cannot pass the result of a function call as
>> argument to this same function call, unless you have a time machine.

Greg Buchholz wrote:
> ...or lazy evaluation.

That depends on whether you want the return value directly (time
travel), or you're willing to settle for the expression (lazy).
In a functionally impure language, it can make a difference.

(defun make-test ()
   (write-line "Press enter to continue.")
   (read-line)
   (make-instance 'test :self (funcall #'make-test)))

-- 
Dan
www.prairienet.org/~dsb/