AliasTuples, rather than Records, to return multiple values

deadalnix deadalnix at gmail.com
Thu May 17 10:20:38 PDT 2012


Le 17/05/2012 16:20, Dario Schiavon a écrit :
> Hi everybody!
>
> I've been lurking this forum for quite some time, attracted by the power
> and elegance of D. Although I'm not a programmer by profession, I often
> happen to develop programs for scientific data evaluation at work and
> I've always being intrigued with programming languages since I was a
> teenager. A lot of time has passed since the last time I looked at D,
> and now I'm really impressed with the amount of progress that has been
> done.
>
> However, I don't understand why some feature that would be so desirable
> are still not implemented and, although there are already a lot of posts
> about them, little to no progress is done at implementing them. One of
> these is using tuples to return multiple values from functions. I'd like
> to share with you my thoughts and opinions about how tuples might work
> and be useful in D. I hope you find this contribution useful, and you
> will let me understand where the problems are otherwise. I also
> apologize for the length of my post if it doesn't really contain
> anything new.
>
> At the time being we have two kinds of tuples in D and a lot of
> confusion about them. The first one is the Tuple object in Phobos
> (std.typecons.Tuple), which I'm going to call "Record" for the rest of
> the post to avoid confusion. They are pretty similar to Python's tuples,
> except that they are not immutable and have named items (admittedly a
> useful addition).
>
> By introducing Records, you were probably trying to achieve the
> following two points:
>
> 1) Provide a way to group values together, as if they were anonymous
> struct's. Unfortunately, Records are not compatible with ordinary
> struct's despite all their similarities. And I'm also not totally
> convinced they are that useful, except when dealing with point 2. They
> just confuse novices about whether they should be using Records or
> struct's, just like they can't choose between tuples and lists in Python.
>
> 2) Provide a mechanism for functions to return multiple values. It may
> be noted that functions in D can already return multiple values through
> out/ref arguments, but most people agree that returning multiple values
> would be a neater solution (I also do). This mechanism doesn't work yet
> because of the lack of compiler support. I don't understand, however,
> why Records should be a better candidate to implement this feature than
> TypeTuples (more about that later).
>
> Before going on, let me open a parenthesis about how returning multiple
> values works in Python. Suppose that the function "func" returns two
> values. The following saves the two values in the variables a and b.
>
> (a, b) = func()
>
> The parentheses around the tuple are not necessary, but I include them
> anyway for clarity. I'd like you to notice that this syntax is treated
> specially in Python. Python's tuples are immutable so you can't assign
> values to them.
>
> c = (0, 1)
> c[0] = 2 # error: tuple object does not support item assignment
> c = (2, 3) # this changes the reference c so that it points to a
> different tuple
>
> d = (a, b)
> d = func() # this doesn't assign the return values to a and b!
> (a, b) = func() # this does, but it's obviously a special case
>
> Ok, enough for Python, let's go on with D.
>
> The second kind of tuple is the in-built construct used in templates to
> group template arguments (std.typetuple.TypeTuple). Let's call it
> AliasTuple for the rest of the post, since TypeTuple is really a
> misnomer (as others before me have already pointed out: they can contain
> more than just types).
>
> It must be noted that AliasTuples are not containers. They may be
> considered a kind of compile-time container, but definitely not a
> run-time container. With this, I mean that they don't copy their content
> in a structured form in a determined region of memory at runtime, like
> arrays, linked-lists and Records do. This implies, for example, that we
> can't take their address or make an array of them. AliasTuples are just
> collections of aliases, they don't contain actual data. So they are not
> "just another struct-like container in the language", like Records are.
>
> We may debate about how many defects AliasTuples have but, I guess, we
> all agree that they are an extremely useful construct for D's templates.
> Without them, templates in D would certainly be much more difficult to
> use and they would lose much of their power. Therefore, I hope nobody
> really intends to scrap them. If they have deficiencies (for instance,
> they can't actually be used to return multiple values from functions), I
> think we should improve them so that they cover all the useful use cases.
>
> It is my opinion that AliasTuples are much more appropriate to manage
> multiple return values than Records. However, for that to be possible,
> we must solve some of their weaknesses. One of them is that there isn't
> a concise literal expression yet. Let's suppose that we can create a
> tuple like this:
>
> @(1, 2, float) // equivalent to TypeTuple!(1, 2, float)
>
> Of course it would be preferable to have just the parentheses without
> the @. Unfortunately, it would clash with the normal parentheses and the
> comma expression. In Python it works that way, but single-valued tuples
> are awkwardly defined as (1,). Bearophile suggested for syntax (|1, 2|)
> (although that was for Records), which I happen to like even less than
> @(1, 2). Maybe someone will come out with a better syntax later on.
>
> Since an AliasTuple contains just aliases, assigning a value to an item
> of the AliasTuple is actually equivalent to assign the value to the
> "thing" the alias points to. The following would be valid D code (it
> already works if you replace @() with TypeTuple!()).
>
> int a;
> alias @(1, 2, float, a) b; // defines b to be the given tuple
> b[3] = 3; // assigns 3 to the variable a
>
> The following snipped, instead, doesn't work yet but I think it should
> be made to work:
>
> int a=1, b=2;
> @(a, b) = @(b, a); // should swap values between a and b
> writeln(a, b); // outputs "22" but should output "21"
>
> Let's suppose it is possible to define a function that returns an
> AliasTuple. The following might be a possible syntax. If the return type
> of a function is an AliasTuple of only types, then the function should
> returns an AliasTuple of values with those types.
>
> @(int, int) func() {
> return @(4, 5);
> }
> int x, y;
> @(x, y) = func();
>
> Note that the last line is not a special case as it is in Python. It
> naturally works that way because an AliasTuple is a collection of
> aliases and not a container. There should not be any implementation
> problem in this feature, because it would be just syntax sugar for:
>
> int func(out int z) {
> z = 5;
> return 4;
> }
> int x, y;
> x = func(y);
>
> What do you think of it?

I think you show a real need here, but I don't really like your 
proposal. I'd advocate for recycling the comma operator for tuple building.

This would be very similar to your proposal as a result, but no need to 
introduce a new syntax.


More information about the Digitalmars-d mailing list