static arrays becoming value types

Robert Jacques sandford at jhu.edu
Tue Oct 20 13:25:05 PDT 2009


On Tue, 20 Oct 2009 15:19:15 -0400, language_fan <foo at bar.com.invalid>  
wrote:

> Tue, 20 Oct 2009 12:39:47 -0300, Leandro Lucarella thusly wrote:
>
>> language_fan, el 20 de octubre a las 13:52 me escribiste:
>>> Tue, 20 Oct 2009 10:34:35 -0300, Leandro Lucarella thusly wrote:
>>>
>>> > dsimcha, el 20 de octubre a las 02:44 me escribiste:
>>> >> == Quote from Walter Bright (newshound1 at digitalmars.com)'s article
>>> >> > Currently, static arrays are (as in C) half-value types and
>>> >> > half-reference types. This tends to cause a series of weird
>>> >> > problems and special cases in the language semantics, such as
>>> >> > functions not being able to return static arrays, and out
>>> >> > parameters not being possible to be static arrays.
>>> >> > Andrei and I agonized over this for some time, and eventually came
>>> >> > to the conclusion that static arrays should become value types.
>>> >> > I.e.,
>>> >> >    T[3]
>>> >> > should behave much as if it were:
>>> >> >    struct ??
>>> >> >    {
>>> >> >       T[3];
>>> >> >    }
>>> >> > Then it can be returned from a function. In particular,
>>> >> >    void foo(T[3] a)
>>> >> > is currently done (as in C) by passing a pointer to the array, and
>>> >> > then with a bit of compiler magic 'a' is rewritten as (*a)[3].
>>> >> > Making this change would mean that the entire array would be
>>> >> > pushed onto the parameter stack, i.e. a copy of the array, rather
>>> >> > than a reference to it. Making this change would clean up the
>>> >> > internal behavior of types. They'll be more orthogonal and
>>> >> > consistent, and templates will work better. The previous behavior
>>> >> > for function parameters can be retained by making it a ref
>>> >> > parameter:
>>> >> >     void foo(ref T[3] a)
>>> >>
>>> >> Vote++.  It's funny, I use static arrays so little that I never
>>> >> realized that they weren't passed by value to functions.  I'd
>>> >> absolutely love to be able to just return static arrays from
>>> >> functions, and often use structs to do that now, but using structs
>>> >> feels like a really ugly hack.
>>> >
>>> > It would be the poor men tuple for returning (homogeneous) stuff =P
>>>
>>> It depends on how you define things. Traditionally tuples are seen as a
>>> generalization of pairs (2 elements -> n elements). Records, on the
>>> other
>>
>> In what tradition? C++ maybe. I never saw a pair type outside C++, but
>> saw tuples everywhere (even in other structured languages like SQL).
>
> Pairs are pretty common actually. You might have applications that have
> mappings, functions, or zip (list operation) etc. I admit these are more
> common in functional languages but the main reason for this is that most
> mainstream languages do not support the Pair or Tuple types in any way.
> Even D has broken support (from this point of view).
>
>>> One nasty thing about D's structs is that they don't have structural
>>> equivalence relation unlike tuples. So you need to use the same
>>> container struct type to get the same semantics. To achieve that you
>>> would need some kind of STuple on standard library level or other kinds
>>> of hacks.
>>>
>>> What I find unfortunate in D is that your abstractions come in two
>>> sizes - either you use the modest tiny construct that does not scale
>>> elegantly or the enormous hammer to crush things down theatretically.
>>
>> I don't understand very well what are you saying anyways...
>
> Because of the unnecessary nominal typing in D's tuple emulation,
> redefinitions of Tuples do not have implicit equivalence relation:
>
>   struct Tuple(T...) {
>     T t;
>   }
>   struct Tuple2(T...) {
>     T t;
>   }
>
>   void main() {
>     Tuple!(int,int) a;
>     Tuple!(int,int) b;
>     Tuple2!(int,int) c;
>
>     assert(a == b); // ok
>     assert(a != c); // Error: incompatible types for ((a) != (b))
>   }
>
> In some other language:
>
>   val a = (1,2) : [Int,Int]
>   val b = (1,2) : [Int,Int]
>   val c = (2,3) : [Int,Int]
>
>   assert(a == b); // ok
>   assert(a != c); // ok
>
> Did you get it now?
>
> Real tuple types do not have a special type tag which gets injected
> implicitly with structs. So every time you try to do something
> lightweight by emulating tuples, you need to refer to the global Tuple
> type or bang your head to the wall.

Or use a templated opAssign mixin to allow two desperate types to be  
assigned to each other.
Besides, I think you're comparing apples to oranges. In the SOL example,  
you use the same declaration for all types. Shouldn't the SOL example be:

   val a = (1,2) : [Int,Int]
   val b = (1,2) : [Int,Int]
   val c = (2,3) : MyCustomTupleType[Int,Int]

which would probably generate:
      assert(a == b); // ok
      assert(a != c); // Error: incompatible types for ((a) != (b))



More information about the Digitalmars-d mailing list