From: Paul F. Dietz
Subject: LOOP FOR ... FROM ... and complex numbers
Date: 
Message-ID: <TROdnQ9MjJZVKEmjXTWcoQ@dls.net>
According to section 6.1.2.1.1, the for-as-arithmetic subclause of the LOOP form
has expressions that must have type NUMBER.  Now, the NUMBER type includes
complex numbers.  The BY form, if present, must be a positive number (so
it must be a REAL), and one can argue that if there's an upper or lower
bound to the iteration then one needs to be able to do < or > on the values
(although the wording doesn't actually say this).

But what about indefinite iteration, with no termination test on the
index variable?  As far as I can tell, the following should be legal:

    (loop for i from 1 to 5
          for c from #c(0 1)
          collect c)

    ==> (#c(0 1) #c(1 1) #c(2 1) #c(3 1) #c(4 1))

When I try this form in various lisps I get complaints about #c(0 1) not
being a real, but it evaluates in many of them.

	Paul

From: Nils Goesche
Subject: Re: LOOP FOR ... FROM ... and complex numbers
Date: 
Message-ID: <ly4r3f9ot3.fsf@cartan.de>
"Paul F. Dietz" <·····@dls.net> writes:

> According to section 6.1.2.1.1, the for-as-arithmetic subclause of
> the LOOP form has expressions that must have type NUMBER.  Now, the
> NUMBER type includes complex numbers.

[...]

> But what about indefinite iteration, with no termination test on the
> index variable?  As far as I can tell, the following should be
> legal:
> 
>     (loop for i from 1 to 5
>           for c from #c(0 1)
>           collect c)
> 
>     ==> (#c(0 1) #c(1 1) #c(2 1) #c(3 1) #c(4 1))
> 
> When I try this form in various lisps I get complaints about #c(0 1)
> not being a real, but it evaluates in many of them.

I think the wording is absolutely clear on this one: It should work
(and it does work at least in LW).

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Pascal Bourguignon
Subject: Re: LOOP FOR ... FROM ... and complex numbers
Date: 
Message-ID: <878yspixca.fsf@thalassa.informatimago.com>
Nils Goesche <······@cartan.de> writes:
> "Paul F. Dietz" <·····@dls.net> writes:
> 
> > According to section 6.1.2.1.1, the for-as-arithmetic subclause of
> > the LOOP form has expressions that must have type NUMBER.  Now, the
> > NUMBER type includes complex numbers.
> 
> [...]
> 
> > But what about indefinite iteration, with no termination test on the
> > index variable?  As far as I can tell, the following should be
> > legal:
> > 
> >     (loop for i from 1 to 5
> >           for c from #c(0 1)
> >           collect c)
> > 
> >     ==> (#c(0 1) #c(1 1) #c(2 1) #c(3 1) #c(4 1))
> > 
> > When I try this form in various lisps I get complaints about #c(0 1)
> > not being a real, but it evaluates in many of them.
> 
> I think the wording is absolutely clear on this one: It should work
> (and it does work at least in LW).

There exist total orders on the complex. The only problem is that none
is "standard".


But you should be able to write:

     (loop for c from #c(1 1) upto #c(5 1) collect c)

if you  provide your own complex comparison:

(defmacro replace-by-generic (operator)
  (let ((new  (intern (format nil "original-~A" operator))))
    `(progn
       (setf (symbol-function ,new))  (symbol-function operator))
       (defgeneric operator (a b))
       (defmethod  operator ((a number) (b number)) (,new a b))))
           

(replace-by-generic <)
(replace-by-generic >)
(replace-by-generic <=)
(replace-by-generic >=)

(defmethod  < ((a complex) (b complex))
  (or (original-< (imagpart a) (imagpart b))
      (and (= (imagpart a) (imagpart b))
           (original-< (realpart a) (realpart b)))))

(defmethod >  ((a complex) (b complex))  (< b a))
(defmethod <= ((a complex) (b complex))  (not (< b a)))
(defmethod >= ((a complex) (b complex))  (not (< a b)))



But depending on the application, you may rather want to use:

(defmethod  < ((a complex) (b complex))
  (or (original-< (abs a) (abs b))
      (and (= (abs a) (abs b))
           (original-< (phase a) (phase b)))))

for example, if you have to write:

    (loop for c from #c(1 1) upto #c(5 5) by #c(1 1) collect c)


Or of course, you may prefer:

(defmethod  < ((a complex) (b complex))
  (or (original-< (phase a) (phase b))
      (and (= (phase a) (phase b))
           (original-< (abs a) (abs b)))))

if your job is to iterate over some roots:

    (loop for c from (complex-root x 10) 
          while (< c (expt (complex-root x 10) 5))
          do    (setq c (* c (complex-root x 10))))

but then loop does not provide support for geometric progressions...




-- 
__Pascal_Bourguignon__                   http://www.informatimago.com/
----------------------------------------------------------------------
Do not adjust your mind, there is a fault in reality.
From: Gareth McCaughan
Subject: Re: LOOP FOR ... FROM ... and complex numbers
Date: 
Message-ID: <slrnbdcteb.2eb1.Gareth.McCaughan@g.local>
Pascal Bourguignon wrote:

> But you should be able to write:
> 
>      (loop for c from #c(1 1) upto #c(5 1) collect c)
> 
> if you  provide your own complex comparison:
> 
> (defmacro replace-by-generic (operator)
>   (let ((new  (intern (format nil "original-~A" operator))))
>     `(progn
>        (setf (symbol-function ,new))  (symbol-function operator))
>        (defgeneric operator (a b))
>        (defmethod  operator ((a number) (b number)) (,new a b))))
>            
> 
> (replace-by-generic <)
> (replace-by-generic >)
> (replace-by-generic <=)
> (replace-by-generic >=)
[etc, defining methods on these things for complex numbers]

"Should" in what sense? You certainly aren't allowed to do it
by CL as it presently stands. If you were, and if defining
methods that override the default behaviour for real numbers
were allowed, then nothing in CL would be allowed any more
to make use of the familiar properties of < and its friends.
So, for instance, if you do

    (loop for i from 1 upto 10 do ... something ...)

then the compiler wouldn't be allowed to infer that it's
safe for I always to be a fixnum, or that it never takes
the value 20. (I forget whether you're allowed to alter I
in the loop body; if so, then the compiler can infer those
things at present only if you never do that; but that
can be determined statically, whereas whether you'll
ever do the loop with non-standard definitions of <
in force cannot.)

Nor could it open-code calls to <, lest they be invalidated
by changes.

So you'd better say that you're only ever allowed to
define new methods on < if those methods cannot get
called for arguments that presently aren't erroneous.
Is this really worth it?

-- 
Gareth McCaughan  ················@pobox.com
.sig under construc
From: Pascal Bourguignon
Subject: Re: LOOP FOR ... FROM ... and complex numbers
Date: 
Message-ID: <87smquqkru.fsf@thalassa.informatimago.com>
Gareth McCaughan <················@pobox.com> writes:

> Pascal Bourguignon wrote:
> 
> > But you should be able to write:
> > 
> >      (loop for c from #c(1 1) upto #c(5 1) collect c)
> > 
> > if you  provide your own complex comparison:
> > 
> > (defmacro replace-by-generic (operator)
> >   (let ((new  (intern (format nil "original-~A" operator))))
> >     `(progn
> >        (setf (symbol-function ,new))  (symbol-function operator))
> >        (defgeneric operator (a b))
> >        (defmethod  operator ((a number) (b number)) (,new a b))))
> >            
> > 
> > (replace-by-generic <)
> > (replace-by-generic >)
> > (replace-by-generic <=)
> > (replace-by-generic >=)
> [etc, defining methods on these things for complex numbers]
> 
> "Should" in what sense? You certainly aren't allowed to do it
> by CL as it presently stands. 

Well, it works in clisp... 
The only thing missing is the geometric progression.


> If you were, and if defining
> methods that override the default behaviour for real numbers
> were allowed, then nothing in CL would be allowed any more
> to make use of the familiar properties of < and its friends.
> So, for instance, if you do
> 
>     (loop for i from 1 upto 10 do ... something ...)
> 
> then the compiler wouldn't be allowed to infer that it's
> safe for I always to be a fixnum, or that it never takes
> the value 20. (I forget whether you're allowed to alter I
> in the loop body; if so, then the compiler can infer those
> things at present only if you never do that; but that
> can be determined statically, whereas whether you'll
> ever do the loop with non-standard definitions of <
> in force cannot.)
> 
> Nor could it open-code calls to <, lest they be invalidated
> by changes.
> 
> So you'd better say that you're only ever allowed to
> define new methods on < if those methods cannot get
> called for arguments that presently aren't erroneous.
> Is this really worth it?


The OP noted that loop allowed for any number as variable:
http://www.lisp.org/HyperSpec/Body/sec_6-1-2-2.html

A complex is a number isn't it.

http://www.lisp.org/HyperSpec/Body/sec_6-1-2-1-1.html

In the for-as-arithmetic subclause, the for or as construct iterates
from the value supplied by form1 to the value supplied by form2 in
increments or decrements denoted by form3. Each expression is
evaluated only once and must evaluate to a number. The variable var is
bound to the value of form1 in the first iteration and is stepped[1]
by the value of form3 in each succeeding iteration, or by 1 if form3
is not provided.

So the increment is always 1.

The  only thing  that's missing  in Common-Lisp,  inconsistent  if you
will, is that there is not a predefined order on all the numbers. Only
on the floats and the integers.


So it should  either specify that loop variables  should be integer or
real (and forbid explicitely complex), or it should allow for the user
to provide an order on the complexes. 

The clisp implementation allows the later.


That's my opinion.  It could also  stay as it is, which means that you
can  still use complexes,  but you  can't use  upto, downto,  above or
below  and  you  must use  a  while  or  until clause  comparing  your
complexes without modifying <.

-- 
__Pascal_Bourguignon__                   http://www.informatimago.com/
----------------------------------------------------------------------
Do not adjust your mind, there is a fault in reality.
From: Paul F. Dietz
Subject: Re: LOOP FOR ... FROM ... and complex numbers
Date: 
Message-ID: <he-dnYrjqYlhaUSjXTWcow@dls.net>
Pascal Bourguignon wrote:

>>"Should" in what sense? You certainly aren't allowed to do it
>>by CL as it presently stands. 
> 
> 
> Well, it works in clisp... 

'It works in this implementation' is a very poor way of determining
what is allowed to be in a conforming program.  There are numerous
areas of the standard where behavior is undefined, and a conforming
program may have none of these situations, regardless of what any
particular implementations happen to do with them.

	Paul
From: Gareth McCaughan
Subject: Re: LOOP FOR ... FROM ... and complex numbers
Date: 
Message-ID: <slrnbdspeq.1i9.Gareth.McCaughan@g.local>
Pascal Bourguignon wrote:

> > >   (let ((new  (intern (format nil "original-~A" operator))))
> > >     `(progn
> > >        (setf (symbol-function ,new))  (symbol-function operator))
> > >        (defgeneric operator (a b))
> > >        (defmethod  operator ((a number) (b number)) (,new a b))))
> > > 
> > > (replace-by-generic <)
> > > (replace-by-generic >)
> > > (replace-by-generic <=)
> > > (replace-by-generic >=)
> > [etc, defining methods on these things for complex numbers]
> > 
> > "Should" in what sense? You certainly aren't allowed to do it
> > by CL as it presently stands. 
> 
> Well, it works in clisp... 
> The only thing missing is the geometric progression.

I take it that 11.1.2.1.2 #2 forbids applying
(setf symbol-function) to any external symbol
in the COMMON-LISP package. Including <.

CLISP may well let you get away with it. (The
fact that it doesn't compile to native code
may make this easier for it.) But the instant
you do it your program becomes non-conforming.
If you only ever want to use CLISP then this
is probably fine for you. (Unless you want to
keep up to date with future changes, don't have
an undertaking from its implementors to preserve
this non-required property, and don't want to
spend the necessary time digging in the implementation
yourself to make sure it is preserved even without
their help.)


> > So you'd better say that you're only ever allowed to
> > define new methods on < if those methods cannot get
> > called for arguments that presently aren't erroneous.
> > Is this really worth it?
> 
> 
> The OP noted that loop allowed for any number as variable:
> http://www.lisp.org/HyperSpec/Body/sec_6-1-2-2.html
> 
> A complex is a number isn't it.

I'm not saying that LOOP should stop you using complex
numbers as arithmetic iteration variables. I'm saying
that you can't usefully do that in a conforming program
because you aren't allowed to redefine things like <.
The reasons for this have nothing to do with complexes
being numbers (yes, they are) or with LOOP allowing
any number (yes, it does).

> The  only thing  that's missing  in Common-Lisp,  inconsistent  if you
> will, is that there is not a predefined order on all the numbers. Only
> on the floats and the integers.
> 
> So it should  either specify that loop variables  should be integer or
> real (and forbid explicitely complex), or it should allow for the user
> to provide an order on the complexes. 

Perhaps it should, but it doesn't. It's possible that
making the change you want would produce a better language
than Common Lisp, but it certainly isn't obvious (because
it would inhibit some optimizations).

> That's my opinion.  It could also  stay as it is, which means that you
> can  still use complexes,  but you  can't use  upto, downto,  above or
> below  and  you  must use  a  while  or  until clause  comparing  your
> complexes without modifying <.

That's the way it is in ANSI Common Lisp. Implementors
are free to define different languages, as CLISP does :-).

-- 
Gareth McCaughan  ················@pobox.com
.sig under construc