October 20, 2009
== Quote from Steven Schveighoffer (schveiguy@yahoo.com)'s article
> On Mon, 19 Oct 2009 21:50:46 -0400, Walter Bright <newshound1@digitalmars.com> wrote:
> > 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)
> What happens for IFTI?
> void foo(T)(T t)
> {
>     return t[2];
> }
> void main()
> {
>     int[3] x;
>     x[] = 5;
>     printf(foo(x));
> }
> I would think T would resolve to int[3], which means pass by value.  You'd
> need a specialization for static arrays to get the current behavior.
> Don't get me wrong, I would love to see static arrays become real types,
> but I wonder if there are any ways we can "optimize out" the staticness of
> an array argument for templates.  In particular, I hate how IFTI likes to
> assume static array for literals...
> In the absence of such an optimization, I'd still prefer static arrays
> become value types like you say.
> -Steve

To me, static arrays are an optimization that you don't use unless you really need it.  Dynamic arrays should be most programmers' "default" array type.  If you insist on using static arrays, then the onus should be on you to make sure nothing like this happens by doing something like:

print(foo(x[]));  // Slice operator converts x into an int[], passed
                  //the way dynamic arrays are.

The what type are literals question, though, is a legit issue.
October 20, 2009
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@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.
October 20, 2009
On Tue, 20 Oct 2009 15:19:15 -0400, language_fan <foo@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@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))
October 21, 2009
language_fan, el 20 de octubre a las 19:19 me escribiste:
> >> 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?

Yes, thanks for the clarification.

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

Yes, D support for tuples is way far from ideal.

-- 
Leandro Lucarella (AKA luca)                     http://llucax.com.ar/
----------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------
If you want to be alone, just be alone
If you want to watch the sea, just watch the sea
But do it now, timing is the answer, do it now
Timing is the answer to success
October 21, 2009
On Tue, 20 Oct 2009 20:38:33 -0400, Leandro Lucarella <llucax@gmail.com> wrote:
> language_fan, el 20 de octubre a las 19:19 me escribiste:
>> >> 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?
>
> Yes, thanks for the clarification.
>
>> 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.
>
> Yes, D support for tuples is way far from ideal.

How so? I think this is merely the difference between a library type in a flexible language and a built-in type in an inflexible language. I mean the example was essentially:
In D:
 Apple a
 Apple b
 Orange c

 assert(a != c); // Error: incompatible types Apple and Orange

In SOL:
 Apple a
 Apple b
 Apple c

 assert(a != c); // ok, both a and c are apples.

Now, if SOL allowed tuples to do things you can't do today in D, like assign a tuple to a struct with the same signature, then this might be a point. But that wasn't the example given.

Now, the example was a good argument for making it easier and more natural to use the built-in tuple type. Adding syntaxtic sugar for tuples has been recommended before. I prefer using the slice syntax '..', as it would allow clean multi-dimensional slicing and mixed indexing and slicing, both of which are important to supporting arrays.
October 21, 2009
Robert Jacques wrote:
> On Tue, 20 Oct 2009 20:38:33 -0400, Leandro Lucarella <llucax@gmail.com> wrote:
>> Yes, D support for tuples is way far from ideal.
> 
> How so? I think this is merely the difference between a library type in a flexible language and a built-in type in an inflexible language. I mean the example was essentially:
> In D:
>  Apple a
>  Apple b
>  Orange c
> 
>  assert(a != c); // Error: incompatible types Apple and Orange
> 
> In SOL:
>  Apple a
>  Apple b
>  Apple c
> 
>  assert(a != c); // ok, both a and c are apples.
> 
> Now, if SOL allowed tuples to do things you can't do today in D, like assign a tuple to a struct with the same signature, then this might be a point. But that wasn't the example given.

I also don't understand all the argument about structural vs. name equivalence.

Andrei
October 21, 2009
Robert Jacques, el 20 de octubre a las 21:06 me escribiste:
> >>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.
> >
> >Yes, D support for tuples is way far from ideal.
> 
> How so? I think this is merely the difference between a library type
> in a flexible language and a built-in type in an inflexible
> language. I mean the example was essentially:
> In D:
>  Apple a
>  Apple b
>  Orange c
> 
>  assert(a != c); // Error: incompatible types Apple and Orange
> 
> In SOL:
>  Apple a
>  Apple b
>  Apple c
> 
>  assert(a != c); // ok, both a and c are apples.

I wasn't referring to this particular example, even when I agree this is not a big issue, is much more difficult to end up comparing Apples to Oranges if the language have support for tuple literals (like in the example). In D I think you might find yourself in this situation more often, but still rarely.

I think tuple literals is an important thing to encourage people using tuples, specially when you want to support functional programming style.

> Now, if SOL allowed tuples to do things you can't do today in D, like assign a tuple to a struct with the same signature, then this might be a point. But that wasn't the example given.

Yes, that's another thing that can be done without real tuple support in the language. Anyway, I guess I was a little exaggerated with '*way far* from ideal', but I'm convinced there is plenty of room for improvements. =)

-- 
Leandro Lucarella (AKA luca)                     http://llucax.com.ar/
----------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------
FINALMENTE EL CABALLITO FABIAN VA A PASAR UNA BUENA NAVIDAD
	-- Crónica TV
October 21, 2009
On Tue, 20 Oct 2009 22:45:53 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> Robert Jacques wrote:
>> On Tue, 20 Oct 2009 20:38:33 -0400, Leandro Lucarella <llucax@gmail.com> wrote:
>>> Yes, D support for tuples is way far from ideal.
>>  How so? I think this is merely the difference between a library type in a flexible language and a built-in type in an inflexible language. I mean the example was essentially:
>> In D:
>>  Apple a
>>  Apple b
>>  Orange c
>>   assert(a != c); // Error: incompatible types Apple and Orange
>>  In SOL:
>>  Apple a
>>  Apple b
>>  Apple c
>>   assert(a != c); // ok, both a and c are apples.
>>  Now, if SOL allowed tuples to do things you can't do today in D, like assign a tuple to a struct with the same signature, then this might be a point. But that wasn't the example given.
>
> I also don't understand all the argument about structural vs. name equivalence.
>
> Andrei

The original thread stated that D's value tuples (as opposed to type tuples) were far from ideal, because it's not a built-in type. So two people could make value tuple structs types that were incompatible with each other. (One counter to this is it's simple to define a templated opAssgin method that works correctly. Another counter is to relate this problem to typedefs).
My issue was with the example comparing D to some-other-language (SOL). The issue was that only the built-in value-tuple type in SOL was shown, and not a value-tuple interfacing with something else that wasn't the built-in value-tuple. This indicates that SOL isn't flexible/expressive enough to have library value-tuple-types, or the problems with D's value-tuple type solution.
October 21, 2009
On Tue, 20 Oct 2009 23:30:48 -0400, Leandro Lucarella <llucax@gmail.com> wrote:
> Robert Jacques, el 20 de octubre a las 21:06 me escribiste:
>> Now, if SOL allowed tuples to do things you can't do today in D,
>> like assign a tuple to a struct with the same signature, then this
>> might be a point. But that wasn't the example given.
>
> Yes, that's another thing that can be done without real tuple support in
> the language. Anyway, I guess I was a little exaggerated with '*way far*
> from ideal', but I'm convinced there is plenty of room for improvements.
> =)
>

Would you happen to know of a language which does tuples well already?
October 21, 2009
On 21/10/2009 05:48, Robert Jacques wrote:
> On Tue, 20 Oct 2009 23:30:48 -0400, Leandro Lucarella <llucax@gmail.com>
> wrote:
>> Robert Jacques, el 20 de octubre a las 21:06 me escribiste:
>>> Now, if SOL allowed tuples to do things you can't do today in D,
>>> like assign a tuple to a struct with the same signature, then this
>>> might be a point. But that wasn't the example given.
>>
>> Yes, that's another thing that can be done without real tuple support in
>> the language. Anyway, I guess I was a little exaggerated with '*way far*
>> from ideal', but I'm convinced there is plenty of room for improvements.
>> =)
>>
>
> Would you happen to know of a language which does tuples well already?

pick any functional language.. my favorite is ML