March 13, 2012
On 3/13/12 2:07 PM, Jose Armando Garcia wrote:
> On Tue, Mar 13, 2012 at 9:07 AM, Andrei Alexandrescu
> <SeeWebsiteForEmail@erdani.org>  wrote:
>> On 3/13/12 10:48 AM, Manu wrote:
>>>
>>> float t;
>>> ...
>>> (myStruct.pos, t, _, int err) = intersectThings();
>>
>
> This can be checked at compile time. The D compiler can check that the
> number of arguments and the types match.

scatter() can also be compile-time checked. I left that to a runtime assert for more flexibility, but probably more checking is better particularly because skip allows skipping some values.

>> I actually find the scatter syntax better than this. Anyway, I hope you'll
>> agree there's not much difference pragmatically.
>>
>
> Correct if I am wrong but the scatter and gather functions cannot
> check that the number of arguments and their type match at compile
> time.

Just replace the two assert()s with static assert or a template constraint.


Andrei
March 13, 2012
On 3/13/12 1:20 PM, Manu wrote:
> What value does it add over Kenji's change? Is this because Kenji's
> change is unable to perform direct to existing variables?

Yes.

> My understanding from early in the thread was that Kenji's change hides
> the returned tuple, and performs a convenient unpack. How can you
> perform a scatter if the tuple instance is no longer visible?

If I understand you correctly, you just say fun().scatter(v1, v2, v3).


Andrei

March 13, 2012
On 13 March 2012 21:40, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org>wrote:

> On 3/13/12 1:20 PM, Manu wrote:
>
>> What value does it add over Kenji's change? Is this because Kenji's change is unable to perform direct to existing variables?
>>
>
> Yes.
>
>
>  My understanding from early in the thread was that Kenji's change hides
>> the returned tuple, and performs a convenient unpack. How can you perform a scatter if the tuple instance is no longer visible?
>>
>
> If I understand you correctly, you just say fun().scatter(v1, v2, v3).


Ah okay, I see.
And you think that's more readable and intuitive than: (v1, v2, v3) =
fun(); ?


March 13, 2012
On 3/13/12 2:57 PM, Manu wrote:
> And you think that's more readable and intuitive than: (v1, v2, v3) =
> fun(); ?

Yes (e.g. when I see the commas my mind starts running in all directions because that's valid code nowadays that ignores v1 and v2 and keeps v3 as an lvalue).

Let me put it another way: I don't see one syntax over another a deal maker or deal breaker. At all.


Andrei
March 13, 2012
Andrei Alexandrescu:

> Let me put it another way: I don't see one syntax over another a deal maker or deal breaker. At all.

I am usually able to follow threads, but this time I am a bit lost (this discussion has mixed very different topics like ABIs, implementation efficiency of tuples and typetuples, a hypothetical not-really-a-tuple third-kind of tuple, built-in syntax, library implementation code, etc). Is someone able and willing to summarize the current situation of this discussion?

From the last weeks (more like months) of intensive usage of functional-style D code I really think D will really enjoy an unpacking syntax for std.typecons.Tuples. Recently I have written a long post about this:

http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=159627

The proposed syntax is quite simple, it's mostly implemented in a patch. The person that has written the patch says he's willing to add the missing part, for foreach looping (see below).

Walter is waiting for something, to find problems. One raw solution for this impasse is to apply the patch as an experiment and then look for problems. Practical usages helps thinking, sometimes.

In this thread I have seen something regarding problems of the patch on code like this, that has one already defined variable:

Tuple!(int,int) foo() { return tuple(1, 2); }
int x;
(x, int y) = foo();


If such code is a problem for the patch, then I am sure the patch author will improve it.

Now I am seeing a scatter()/gather library implementation. In that post of mine there examples like:

alias Tuple!(CTable, string, int, int) Four;
GrowableCircularQueue!Four open;
// ...
while (open.length) {
    immutable item = open.pop();
    immutable CTable cur = item[0];
    immutable string cSol = item[1];
    immutable int x = item[2];
    immutable int y = item[3];


With a tuple unpacking syntax becomes:

while (open.length) {
    immutable (cur, cSol, x, y) = open.pop();


Are those scatter/gather designed to solve this very very simple problem? How do you unpack into immutables? I don't understand.

The missing part in the DMD patch is for something like this (but the exact syntax for this is not yet decided):

foreach (auto (x, y); [tuple(1,2), tuple(3,4)]) {...}

How do you do this with library code?

So I think we should put this thread back on the rails. Library implementations are not enough here. I suggest to start discussing about what's wrong in the proposed D syntax patch, solve the problems Walter has with it.

Bye,
bearophile
March 13, 2012
Maybe

[x, y] = func();

?
March 13, 2012
On Tuesday, 13 March 2012 at 22:26:14 UTC, bearophile wrote:
> Andrei Alexandrescu:
>
>> Let me put it another way: I don't see one syntax over another a deal maker or deal breaker. At all.
>
> I am usually able to follow threads, but this time I am a bit lost (this discussion has mixed very different topics like ABIs, implementation efficiency of tuples and typetuples, a hypothetical not-really-a-tuple third-kind of tuple, built-in syntax, library implementation code, etc). Is someone able and willing to summarize the current situation of this discussion?
>
[snip]
> So I think we should put this thread back on the rails. Library implementations are not enough here. I suggest to start discussing about what's wrong in the proposed D syntax patch, solve the problems Walter has with it.
>
> Bye,
> bearophile

Yeap, I'm confused as well. D's tuple support seems to be completely messed up.
This reminds me - what was the semantic problem with the auto unpacking in a function's parameter list?
Personally, I think D ought to learn from the experts on this. Take a look at how FP languages implement this. E.g take a look at ML or Haskell for pointers.

March 14, 2012
>> Shall we discuss the shortcomings of his implementation? Can someone
>> demonstrate the details of his implementation?
>>  From the little examples up in the thread, it looked like you could
>> only declare new variables inline, but not assign out to existing ones.
>> I'd say this needs to be added too, and perhaps that will throw the
>> whole design into turmoil? ;)
>
We already have very flexible assignments to existing variables.

import std.typecons, std.typetuple, std.stdio;

Tuple!(int, int) foo()
{
    return typeof(return)(1, 2);
}

void main()
{
    int a, b;
    TypeTuple!(a, b) = foo();
    writeln(a, b);

    TypeTuple!(a, b) = tuple(0, 1, 2)[0 .. 2];
    writeln(a, b);

    Tuple!(int, int) t;
    t[] = TypeTuple!(a, b);
    writeln(t);

    TypeTuple!(a, b) = tuple(t[1], t[0]);
    writeln(a, b);
}
March 14, 2012
Kind of unrelated but I think that it is important to have a way to ignore values also.  Leaving them bank would sufice.

(int i,,float f) = intBoringFloat();


March 14, 2012
On Wed, 14 Mar 2012 13:33:18 +1100, Kevin Cox <kevincox.ca@gmail.com> wrote:

> Kind of unrelated but I think that it is important to have a way to ignore
> values also.  Leaving them bank would sufice.
>
> (int i,,float f) = intBoringFloat();

For what its worth, the Euphoria Programming Language uses ? to signify ignored values.

eg.

  integer i
  atom    f
  {i, ?, f} = intBoringFloat()


We felt that leaving a blank could be a source of human error (can be missed when reading code) and also a result of human error (accidentally put in a double comma).  Using an unusual glyph to signify omission was the compromise we came up with.

-- 
Derek Parnell