www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - in/inout/out for arrays needs clear defining

reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Using DMD 0.94, Windows 98SE.

I've long noticed a potential cause for confusion.  The passing of 
arrays as (address, length) tuples, while sensible on the whole, leads 
to counter-intuitive behaviour.  While it's logical to this form, it 
isn't what one might expect, and the spec doesn't clearly define the 
semantics of in/inout/out on arrays.

In short: if an array is passed as in, someone might think that the 
contents of the array are in, when in reality only the (address, length) 
tuple is in; the actual array contents are inout.

Of course, it's probably too late to clean up the semantics without 
breaking plenty of existing code.  But I suppose the main point is that 
the semantics we have need to be clearly explained.


Still, a possible idea for the future would be to allow the contents and 
dimensions to have separate in/inout/out settings.  The idea I came up 
with a while back is a notation like

	void qwert(inout int[in] yuiop);

meaning that the length is in, and the contents are inout.  There would 
be six possibilities:


in int[in]
	"Give me an array to look at"
	Pass in (address, length); either disallow changes to data in the 
function body, or copy on entry if any changes can occur

inout int[in]
	"Give me the size and some starting data, and I'll play around with the 
data"
	Pass in (address, length); allow the contents to be modified in-place 
(current treatment of in int[], except that changing the length should 
be disallowed)

out int[in]
	"Give me the size, and I'll give you the data"
	Pass in (address, length); initialise the array elements on entry; 
allow the contents to be modified in-place

inout int[inout]
	"Give me an array, and I'll do what I like with it"
	Pass in reference to (address, length); anything goes (current 
treatment of inout int[])

out int[inout]
	"Give me a starting size, and I'll give you the data, changing the size 
if I want"
	Pass in reference to (address, length); initialise the array elements 
on entry; anything goes

out int[out]
	"I'll give you an array"
	Pass in reference to (address, length), which is initialised to null


Of course, the other combinations in[inout], in[out], inout[out] make 
little or no sense.

I guess the extension to arrays of arrays would be straightforward, but 
I'm not sure.

And combined with the existing system, while the syntax of my idea 
doesn't clash with it, it would cause confusion.  And it would probalby 
clash if we tried to extend it to static array parameters.  Maybe 
there's a better notation....

Stewart.

-- 
My e-mail is valid but not my primary mailbox, aside from its being the 
unfortunate victim of intensive mail-bombing at the moment.  Please keep 
replies on the 'group where everyone may benefit.
Jul 06 2004
parent Norbert Nemec <Norbert.Nemec gmx.de> writes:
What you say is very true: we have a problem there that needs to be solved.
Anyhow, I fear, documenting the current behavior is all we can do:

Regulating what the routine is allowed to do with the referenced data would
be equal to going for const references, which you should not even mention
if you want to live in peace with Walter....

In any case, one should be aware that the behavior of static arrays is
defined even less. In some cases they have plain value semantics, in others
they mimic the behavior of dynamic arrays being handled by reference. My
preference would be to make a clear cut here and say: static arrays have
value semantics throughout, dynamic arrays have reference semantics (unless
you are using the magic of array/vector expressions, but that's a different
topic)

There is some fundamental asymmetry between the two kinds of arrays anyway,
so why not make it complete instead of trying to cover it up?




Stewart Gordon wrote:

 Using DMD 0.94, Windows 98SE.
 
 I've long noticed a potential cause for confusion.  The passing of
 arrays as (address, length) tuples, while sensible on the whole, leads
 to counter-intuitive behaviour.  While it's logical to this form, it
 isn't what one might expect, and the spec doesn't clearly define the
 semantics of in/inout/out on arrays.
 
 In short: if an array is passed as in, someone might think that the
 contents of the array are in, when in reality only the (address, length)
 tuple is in; the actual array contents are inout.
 
 Of course, it's probably too late to clean up the semantics without
 breaking plenty of existing code.  But I suppose the main point is that
 the semantics we have need to be clearly explained.
 
 
 Still, a possible idea for the future would be to allow the contents and
 dimensions to have separate in/inout/out settings.  The idea I came up
 with a while back is a notation like
 
 void qwert(inout int[in] yuiop);
 
 meaning that the length is in, and the contents are inout.  There would
 be six possibilities:
 
 
 in int[in]
 "Give me an array to look at"
 Pass in (address, length); either disallow changes to data in the
 function body, or copy on entry if any changes can occur
 
 inout int[in]
 "Give me the size and some starting data, and I'll play around with the
 data"
 Pass in (address, length); allow the contents to be modified in-place
 (current treatment of in int[], except that changing the length should
 be disallowed)
 
 out int[in]
 "Give me the size, and I'll give you the data"
 Pass in (address, length); initialise the array elements on entry;
 allow the contents to be modified in-place
 
 inout int[inout]
 "Give me an array, and I'll do what I like with it"
 Pass in reference to (address, length); anything goes (current
 treatment of inout int[])
 
 out int[inout]
 "Give me a starting size, and I'll give you the data, changing the size
 if I want"
 Pass in reference to (address, length); initialise the array elements
 on entry; anything goes
 
 out int[out]
 "I'll give you an array"
 Pass in reference to (address, length), which is initialised to null
 
 
 Of course, the other combinations in[inout], in[out], inout[out] make
 little or no sense.
 
 I guess the extension to arrays of arrays would be straightforward, but
 I'm not sure.
 
 And combined with the existing system, while the syntax of my idea
 doesn't clash with it, it would cause confusion.  And it would probalby
 clash if we tried to extend it to static array parameters.  Maybe
 there's a better notation....
 
 Stewart.
 
Jul 06 2004