Re: Wider tuple design discussion

2011-08-02 Thread Alex Rønne Petersen

On 02-08-2011 16:28, bearophile wrote:

Michel Fortin:


We need a way to make those two concepts work together, I think that's
the hard part.


I think they are incompatible.

Bye,
bearophile


I'm not sure it would make much sense to actually allow low-level 
operations on tuples. They're meant to be a language abstraction, and 
freely taking the address of them seems useless in practice and really 
just smells like array pointers (or similar) to me.


- Alex


Re: Wider tuple design discussion

2011-08-02 Thread Don

Michel Fortin wrote:

On 2011-08-02 13:15:52 +, bearophile  said:

A tuple isn't an object, it's more like a record, it's almost like a 
more handy POD. So tuples are data structures that you use with code 
(functions) that they don't contain.


Actually, that's up to debate in my opinion. Andrei's Tuple in phobos is 
a struct, so it's a POD like you say. Walter's tuples in the language 
are just collections of variables.


In fact they're collections of symbols, which can be types, variables, 
or values...





A language tuple does not have an address in itself, it essentially has 
one address per field. This actually makes tuple packing/unpacking very 
efficient across function calls (because there's no real 
packing/unpacking taking place), but it makes it impossible to take the 
address of a tuple.


We need a way to make those two concepts work together, I think that's 
the hard part.



Tuples do have some disadvantages. Their fields often are anonymous, 
this goes against the typical well defined style of D/Java/Ada 
programs, where you know the name of what you are using. So tuples are 
better if you use them locally, or if they have only few items. Long 
tuples become hard to use because you risk forgetting what each field 
is, so the most common tuples have between 2 and 5 items.


Named tuple elements in a language tuple will be implemented when/if 
someone implement named arguments, something I might do eventually.




Re: Wider tuple design discussion

2011-08-02 Thread bearophile
Michel Fortin:

> We need a way to make those two concepts work together, I think that's 
> the hard part.

I think they are incompatible.

Bye,
bearophile


Re: Wider tuple design discussion

2011-08-02 Thread Pelle
On Tue, 02 Aug 2011 15:15:52 +0200, bearophile   
wrote:



5.1) The most basic one is unpacking a tuple locally, inside a function.
5.2) Another common situation is unpacking a small tuple inside a  
foreach statement, when you iterate on a collection of tuples.


I would argue these two are the most important ones.

5.3) Another usage (quite common in Haskell and similar languages) is to  
unpack a tuple in the signature of a function. Haskell even allows to  
give names at the same time to both fields and to the whole tuple.


This is less important, I think.


Other operations are:
6) Slice a tuple like a Python/D array: tup[1..3]. (This is already  
supported in D, but you can't use the normal slice syntax, you need to  
use tup.slice!(1, 3) ).

7) Concat two or more tuples (using ~ and ~= operators).


Note that ~= cannot work, as the result of the concatenation has a  
different type than the left hand side. (Unless, of course, the right hand  
side is the empty tuple :-)


5.3) This is already possible in D using the typetuple coming from a  
tuple using the (undocumented?) .tupleof. But this has the problem of  
losing some safety, this compiles with no errors:


import std.typecons;
void bar(int i, string s) {}
void main() {
auto t1 = tuple(1, "foo");
bar(t1.tupleof);
auto t2 = tuple(1);
auto t3 = tuple("foo");
bar(t2.tupleof, t3.tupleof);
}


This is because of the conflation of TypeTuple (the compiler thing) and  
Tuple (the sane type thing). That code works because .tupleof is a  
TypeTuple.


We need this functionality because of things like  
std.traits.ParameterTypeTuple (or indeed Tuple itself uses a TypeTuple  
internally).


The built in compiler tuple could use a new name, badly, to disperse the  
confused situation with sane tuples. AliasSequence or something :-)


In Python there are more features similar to the point (5). Yo are  
allowed to unpack a dynamic array too into variables, and even a lazy  
generator. This is so handy and useful that I have suggested to allow  
the same thing in D too:

http://d.puremagic.com/issues/show_bug.cgi?id=6383


I think that as well as tuples, any range should be unpackable, and I  
think it should be implemented via syntactic rewrite.


Translate this:

auto (a, rest...) = myRange;

into

static assert (isInputRange!myRange);
assert (!myRange.empty);
auto a = myRange.front;
myRange.popFront;
rest = myRange;

Equivalently with bidirectional ranges, and any number of unpacked  
elements.



I wonder how the auto(...) syntax works with existing variables. For  
example, in python:



a, b = b, a # swap!


Re: Wider tuple design discussion

2011-08-02 Thread Michel Fortin

On 2011-08-02 13:15:52 +, bearophile  said:

A tuple isn't an object, it's more like a record, it's almost like a 
more handy POD. So tuples are data structures that you use with code 
(functions) that they don't contain.


Actually, that's up to debate in my opinion. Andrei's Tuple in phobos 
is a struct, so it's a POD like you say. Walter's tuples in the 
language are just collections of variables.


A language tuple does not have an address in itself, it essentially has 
one address per field. This actually makes tuple packing/unpacking very 
efficient across function calls (because there's no real 
packing/unpacking taking place), but it makes it impossible to take the 
address of a tuple.


We need a way to make those two concepts work together, I think that's 
the hard part.



Tuples do have some disadvantages. Their fields often are anonymous, 
this goes against the typical well defined style of D/Java/Ada 
programs, where you know the name of what you are using. So tuples are 
better if you use them locally, or if they have only few items. Long 
tuples become hard to use because you risk forgetting what each field 
is, so the most common tuples have between 2 and 5 items.


Named tuple elements in a language tuple will be implemented when/if 
someone implement named arguments, something I might do eventually.



--
Michel Fortin
michel.for...@michelf.com
http://michelf.com/



Wider tuple design discussion

2011-08-02 Thread bearophile
Walter has asked for a more global vision on tuples before implementing their 
unpacking, so need to show the discussion here again:
http://d.puremagic.com/issues/show_bug.cgi?id=6365#c26

Walter:
> My main reservation about this is not that I can see anything obviously wrong
> about it, but I am nervous we are building a special case for tuples. I think
> any expansion of tuple support should be part of a more comprehensive design
> for tuples.
> 
> If we grow tuple support by adding piecemeal special cases for this and that,
> without thinking about them more globally, we are liable to build ourselves
> into a box we can't get out of.
> 
> I can give examples in other languages that did this - the most infamous being
> the great C idea of conflating arrays and pointers. It seems to be a great 
> idea
> in the small, but only much larger experience showed what a disastrous mistake
> it was.
> 
> We should step back and figure out what we want to do with tuples in the much
> more general case.


More stuff I've written:
http://d.puremagic.com/issues/show_bug.cgi?id=6367
http://d.puremagic.com/issues/show_bug.cgi?id=6383


A global design for tuples in D was right what I have tried to avoid, because I 
have thought that Andrei was against a full tuple built-in design and that 
generally there was not so much desire for large changes in D2 now. With that 
syntax sugar suggestion I have tried to find the simpler and more essential D 
change that allows me to use tuples in a more handy way. Now I'm back to the 
start. And I still fear that a better and more comprehensive tuple design will 
be refused in D. So I fear there is no way out: if you design a minimal change 
Walter fears of corner cases and myopic design, and if you design a 
comprehensive tuple, it risks being a too much big change for this stage of D 
evolution. In both cases the end result is of not having good enough tuples in 
D.

In the end Walter is right. Better to not have built-in support for tuples than 
having some wrongly designed built-in syntax sugar for tuples. So let's think 
about the only viable alternative, a wider design, and hope.

When you design something you need first of all to think about what your tool 
will be used for.

Tuples are used all the time in functional-style languages, usually once every 
line of code or so. In Python and Haskell I use them all the time. In D I 
already use tuples, but they are not so handy.

Tuples are not essential in D. You are able to write large programs without 
tuples. But they are sometimes handy, especially if you use a more 
functional-style programming.

Tuples do have some disadvantages. Their fields often are anonymous, this goes 
against the typical well defined style of D/Java/Ada programs, where you know 
the name of what you are using. So tuples are better if you use them locally, 
or if they have only few items. Long tuples become hard to use because you risk 
forgetting what each field is, so the most common tuples have between 2 and 5 
items. In Python you are also allowed to define a tuple with zero items, and a 
tuple with one item, but in my experience they are not so useful (in Python you 
sometimes use longer tuples made of items of the same type, because you are 
using them essentially as immutable arrays. This is considered not pythonic). D 
tuples allow a name for the fields, this is useful at usage point, because 
instead of a "[2]" you use (example) ".isOpen", that's more descriptive.

A tuple isn't an object, it's more like a record, it's almost like a more handy 
POD. So tuples are data structures that you use with code (functions) that they 
don't contain. OOP design is against this. But I am not fond of pure OO design. 
There are many situations where you want something more handy, more functional 
style, or more in "abstract data structure"-style. Python, D, Scala and other 
languages recognize this.

In some languages (like Python) tuples are immutable, while in D they are the 
opposite, you currently can't give them immutable fields. In D tuples are 
values, while in Python they are used by kind of reference (by name). In 
functional languages you can't how they managed, because there is referential 
transparency (so even if there is a reference, it's invisible. So the compiler 
is free to implement them as it wants, and optimize as much as it can).

In some languages tuples are managed with a nominal type system, while in most 
other situations they are managed by a structural type system (that means that 
two tuples are seen of different type only if the types of their fields 
differ). (Time ago I have even suggested a @structural attribute to be used in 
the Phobos code that defines D tuples).

There are many operations you want to perform on tuples, the most basic ones 
are:
0) define the type of a tuple
1) create a tuple
2) copy a tuple
3) Read a tuple field
4) Write a tuple field
5) Unpack tuple fields into variables, this is useful in 3 or more differ