From: Thom Goodsell
Subject: Arrays in functional position
Date: 
Message-ID: <7velkjy1ah.fsf@shalott.cra.com>
Erann Gat (and others) have proposed that arrays should functionally
resolve to accessors, such that

> (defvar *temp* (make-array '(10 10) :initial-element 1))
#2A((1 1 1 . . .) . . .)
> (*temp* 2 2)
1
> (setf (*temp* 2 2) 2)
2
> (*temp* 2 2)
2

I'm sure that implementing this is much more complicated than I've
imagined it. So, to help me get a grip on the issues involved, could
someone please explain to me what is conceptually missing from the
following macros?

(defmacro defarray (name dimensions &rest keywords)
  (let* ((num-dimensions (if (atom dimensions)
                             1
                             (length dimensions)))
         (indices (loop for i from 1 to num-dimensions
                        collect (gensym))))
    `(prog1
      (defvar ,name (make-array (quote ,dimensions) ,@keywords))
      (defun ,name (,@indices) (aref ,name ,@indices))
      (defun (setf ,name) (value ,@indices) ; BUG? variable capture of 'value
        (setf (aref ,name ,@indices) value)))))

(defmacro with-array ((name dimensions &rest keywords) &rest body)
  (let* ((num-dimensions (if (atom dimensions)
                             1
                             (length dimensions)))
         (indices (loop for i from 1 to num-dimensions
                        collect (gensym))))
    `(let ((,name (make-array (quote ,dimensions) ,@keywords)))
      (flet ((,name (,@indices) (aref ,name ,@indices))
             ((setf ,name) (value ,@indices)
               (setf (aref ,name ,@indices) value)))
        (progn ,@body)))))

Thanks,
Thom

-- 
(let ((e-mail-address ····@IXG.IUS")) (loop with new-string =
(make-string (length e-mail-address)) for count from 0 to (1- (length
e-mail-address)) for char-code = (char-code (aref e-mail-address
count)) for new-char-code = (if (and (> char-code 64) (< char-code
123)) (+ (mod (+ 13 char-code) 52) 65) char-code) do (setf (aref
new-string count) (code-char new-char-code)) finally (return
new-string)))

From: Christopher Stacy
Subject: Re: Arrays in functional position
Date: 
Message-ID: <upu435wfj.fsf@swingandcircle.com>
Array references in MACLISP looked like function calls:
  (A J)  == (AREF A J)
and you could even FUNCALL/APPLY arrays as if they were functions.

When the Lisp Machine came along (ca. 1977), this language feature was 
deprecated: "This kind of array referencing is considered to be obsolete,
and is slower than the usual kind.  It should not be used in new programs."

Experience had led to the conclusion that conflating function calling
with array references was a mistake, because the resulting programs
were not as clearly understandable.

Why all this sudden interest in turning the clock back 25 years?
From: Thom Goodsell
Subject: Re: Arrays in functional position
Date: 
Message-ID: <7vadv7xyps.fsf@shalott.cra.com>
Christopher Stacy <······@swingandcircle.com> writes:
> When the Lisp Machine came along (ca. 1977), this language feature was 
> deprecated: "This kind of array referencing is considered to be obsolete,
> and is slower than the usual kind.  It should not be used in new programs."
> 
> Experience had led to the conclusion that conflating function calling
> with array references was a mistake, because the resulting programs
> were not as clearly understandable.

This is different than what you quoted above. Is there some reference
for the "not clearly understandable" argument?
 
> Why all this sudden interest in turning the clock back 25 years?

I can't speak for Erann Gat or Paul Graham. My interest was simply
that this appeared to be something that could be easily addressed with
a few macros, and I was wondering what I was missing that prevented
this from being an acceptable solution.

Thom

-- 
(let ((e-mail-address ····@IXG.IUS")) (loop with new-string =
(make-string (length e-mail-address)) for count from 0 to (1- (length
e-mail-address)) for char-code = (char-code (aref e-mail-address
count)) for new-char-code = (if (and (> char-code 64) (< char-code
123)) (+ (mod (+ 13 char-code) 52) 65) char-code) do (setf (aref
new-string count) (code-char new-char-code)) finally (return
new-string)))
From: Christopher Stacy
Subject: Re: Arrays in functional position
Date: 
Message-ID: <un0z75r3h.fsf@swingandcircle.com>
>>>>> On 21 Jan 2002 14:58:55 -0500, Thom Goodsell ("Thom") writes:

 Thom> Christopher Stacy <······@swingandcircle.com> writes:
 >> When the Lisp Machine came along (ca. 1977), this language feature was 
 >> deprecated: "This kind of array referencing is considered to be obsolete,
 >> and is slower than the usual kind.  It should not be used in new programs."
 >> 
 >> Experience had led to the conclusion that conflating function calling
 >> with array references was a mistake, because the resulting programs
 >> were not as clearly understandable.

 Thom> This is different than what you quoted above. Is there some
 Thom> reference for the "not clearly understandable" argument?

You mistook the admonition that it was slower to be the justification
for deprecating the feature.  That is not the causation.  The same
people implemented the feature in both compilers, and could have made
it operate at least as fast on the Lisp Machine as they did on the PDP-10.
They chose not to do that, but rather to deprecate the feature, and to
document that it was a MACLISP compatability hack which they were not
going to bother optimizing and that it's future use should be avoided.
The only reference I could give for the reasoning I cited would be personal
communication with the other hackers when I was at that laboratory.
From: Thomas F. Burdick
Subject: Re: Arrays in functional position
Date: 
Message-ID: <xcvadv6kew6.fsf@famine.OCF.Berkeley.EDU>
Christopher Stacy <······@swingandcircle.com> writes:

> Array references in MACLISP looked like function calls:
>   (A J)  == (AREF A J)
> and you could even FUNCALL/APPLY arrays as if they were functions.
> 
> When the Lisp Machine came along (ca. 1977), this language feature was 
> deprecated: "This kind of array referencing is considered to be obsolete,
> and is slower than the usual kind.  It should not be used in new programs."
> 
> Experience had led to the conclusion that conflating function calling
> with array references was a mistake, because the resulting programs
> were not as clearly understandable.
> 
> Why all this sudden interest in turning the clock back 25 years?

I don't think that's the interest, but rather it's the same abstract
deisre that led to the array/function conflation back then.  I thought
this was a great feature until I thought about it specifically for a
while.  I realized that what I wanted was a very general, simple
syntax similar to:

  x[31, 14]

Similar as in simple, and similar as in parallel to function calling.
I got this with my generic function REF, and haven't felt the need for
funcall-able arrays since.  Functions and arrays/sparse-arrays/trees/etc
are similar to functions.  It's nice to have a construct that reflects
this similarity.  It's also nice to not be forced to use it, though.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Barry Margolin
Subject: Re: Arrays in functional position
Date: 
Message-ID: <_e_28.9$hI5.272282@burlma1-snr2>
In article <··············@shalott.cra.com>,
Thom Goodsell  <·········@DESPAM.cra.com> wrote:
>Erann Gat (and others) have proposed that arrays should functionally
>resolve to accessors, such that
>
>> (defvar *temp* (make-array '(10 10) :initial-element 1))
>#2A((1 1 1 . . .) . . .)
>> (*temp* 2 2)
>1
>> (setf (*temp* 2 2) 2)
>2
>> (*temp* 2 2)
>2
>
>I'm sure that implementing this is much more complicated than I've
>imagined it. So, to help me get a grip on the issues involved, could
>someone please explain to me what is conceptually missing from the
>following macros?

The main thing is that you have to use these declarations in order to do
it.  You can't do:

(defun my-fun (array-arg ...)
  (array-arg ...))

Before I looked carefully at your WITH-ARRAY macro I assumed it would allow
something like:

(defun my-fun (array-arg ...)
  (with-array (array-arg)
    (array-arg ...)))

But then I looked closer and saw that WITH-ARRAY not only makes the name
into a function, but it also allocates a new array, rather than just using
the array that's already in the variable.

>(defmacro defarray (name dimensions &rest keywords)
>  (let* ((num-dimensions (if (atom dimensions)
>                             1
>                             (length dimensions)))
>         (indices (loop for i from 1 to num-dimensions
>                        collect (gensym))))
>    `(prog1
>      (defvar ,name (make-array (quote ,dimensions) ,@keywords))
>      (defun ,name (,@indices) (aref ,name ,@indices))
>      (defun (setf ,name) (value ,@indices) ; BUG? variable capture of 'value
>        (setf (aref ,name ,@indices) value)))))

No bug.  Since (SETF ,name) is a function, not a macro, it doesn't suffer
from variable capture problems.

>(defmacro with-array ((name dimensions &rest keywords) &rest body)
>  (let* ((num-dimensions (if (atom dimensions)
>                             1
>                             (length dimensions)))
>         (indices (loop for i from 1 to num-dimensions
>                        collect (gensym))))
>    `(let ((,name (make-array (quote ,dimensions) ,@keywords)))
>      (flet ((,name (,@indices) (aref ,name ,@indices))
>             ((setf ,name) (value ,@indices)
>               (setf (aref ,name ,@indices) value)))
>        (progn ,@body)))))

BTW, you don't need the lists of gensyms, use &REST arguments and APPLY:

(defmacro with-array ((name dimensions &rest keywords) &rest body)
  (let ((indices (gensym)))
    `(let ((,name (make-array ,dimensions ,@keywords)))
       (flet ((,name (&rest ,indices) (apply #'aref ,name ,indices))
	      ((setf ,name) (value &rest ,indices)
		 (setf (apply #'aref ,name ,indices) value)))
	 ,@body))))

And now that you're not consing a list whose length is based on DIMENSIONS,
you don't require it to be a constant, and can allow it to be evaluated in
the dynamic environment.

-- 
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.