From: Pierre R. Mai
Subject: adjustable-array-p, adjust-array and array-destruction
Date: 
Message-ID: <87itdoe9mh.fsf@orion.bln.pmsf.de>
Hi!

If I interpret the HyperSpec entry for adjust-array and the glossary
entry for "actually adjustable" correctly, then the following
implications hold:

expressly adjustable     -> actually adjustable
(adjustable-array-p foo) -> actually adjustable

actually adjustable      -> (eq (adjust-array foo ...) foo)

(not (eq (adjust-array foo ...) foo)) -> foo is _not_ modified

And hence by deduction:

(eq (adjust-array foo ...) foo) -> foo may be destructively modified

It would now seem allowable for an implementation to destructively
modify an array foo on adjust-array, even if it is not expressly
adjustable and (adjustable-array-p foo) returns nil, since the
definition of actually adjustable only contains implications, and not
equivalences, as seen from the point of view of the programmer.

This is relevant, because CMU CL can destructively reduce (but not
increase) the length of a simple-vector (and other one-dimensional
simple-arrays), and adjust-array would in that case[1] return a
destructively modified, eq array, even though adjustable-array-p would
return nil for such an array (since this can only work for certain
calls to adjust-array, of course).  From my interpretation of the
HyperSpec, this would seem legal behaviour.

Relevant quotes:

- From the entry on ADJUST-ARRAY:

  If adjust-array is applied to an array that is actually adjustable,
  the array returned is identical to array. If the array returned by 
  adjust-array is distinct from array, then the argument array is
  unchanged.

- From the glossary entry for actually adjustable:

  actually adjustable adj. (of an array) such that adjust-array can
  adjust its characteristics by direct modification. A conforming
  program may depend on an array being actually adjustable only if
  either that array is known to have been expressly adjustable or if
  that array has been explicitly tested by adjustable-array-p.

OTOH I feel that my (or CMU CL's) interpretation of the standard is
quite agressive.  The writeup for issue ADJUST-ARRAY-NOT-ADJUSTABLE,
which introduced the current behaviour into the standard, contradicts
my interpretation (yes, I know, issues are not part of the standard):

  5. The predicate ADJUSTABLE-ARRAY-P is true if and only if ADJUST-ARRAY
  will return a value EQ to this array when given this array as its first
  argument.

So what I'm really asking is:  Do people feel that such an
interpretation is both justifiable and acceptable from the user POV,
or is this way overboard and runs contrary to user expectations?
Do users expect adjustable-array-p and actually adjustable to be
equivalent?  Or do they even expect the equivalence from the writeup?

Regs, Pierre.

Footnotes: 
[1]  If it consistently used that feature, which it currently doesn't,
     because of an unrelated bug in adjust-array, which I was fixing
     when I stumbled across this whole problem.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: Kent M Pitman
Subject: Re: adjustable-array-p, adjust-array and array-destruction
Date: 
Message-ID: <sfwvghowcei.fsf@world.std.com>
"Pierre R. Mai" <····@acm.org> writes:

> So what I'm really asking is:  Do people feel that such an
> interpretation is both justifiable and acceptable from the user POV,
> or is this way overboard and runs contrary to user expectations?

I'd begin by asking myself not just the implications but how a program
could get confused by these things.  The most likely thing I can see is
a program that does

                              Yes--> code that expects to observe copying
                             /
  array in ----- adjustable? 
                             \
                              No---> code that expects not to observe copying

I could imagine there could be some obscure program that didn't check to see
if the result was going to be copied and just dropped one or the other 
arrays based on its belief about what would happen.  So probably it's possible
to lose.

However, I think the case is remarkably rare, and I think reasonable
defensive programming basically does (as with the standard "delete
bug" workaround)
 (setq foo (adjust-array foo ...))
thus not really getting into this problem in 99% of the cases.

Were I you, I might document this as a "possible deviation" from the
standard and leave it to customers to complain if they disagree with
your exercise of discretion.  Especially you might put it on a switch,
either a compile time switch or (and I think the speed hit in adjust-array
could be tolerated), a special variable check at adjust-array time.

I do think it wouldn't have been unreasonable to say that sometimes
reducing array size can be accomodated even in non-adjustable arrays,
and it's too bad we didn't.  If I recall correctly, the whole
actually/expressly thing had to do with an accomodation to the lisp
machine, in which most arrays were adjustable even if you didn't ask
for them to be, due to the cost-free hardware assist available of
forwarding pointers that could be inserted if an adjustment needed a
larger backing store. (I think there were some exceptions.)  I think
the overall intent is to allow users to express "the minimum
preparation for array adjustability that they'll need" and then to
allow implementations to respond in a way that is maximally
accomodating to the operators called, and I think that's what you're
doing...