ENIGMA Forums

Contributing to ENIGMA => Proposals => Topic started by: Josh @ Dreamland on September 13, 2012, 02:11:37 pm

Title: Arrays
Post by: Josh @ Dreamland on September 13, 2012, 02:11:37 pm
I doubt anyone would disagree that ENIGMA needs arrays. What I'm proposing is that rather than inherit array syntax from C++, we take a page out of the JavaScript playbook and denote them with [].

I want to use [] for a couple reasons. First, of course, is that [1, 2, 3][1] looks neater than {1,2,3}[1]. That was a joke; I don't give a shit about that. What I want to allow is this sort of syntax:

Code: (EDL) [Select]
[x, y] = [y, x] // Switches the values of x and y
[x, y] = get_some_coordinates(); // Fetches a length-2 array of coordinates, assign

Using {} for arrays, {x,y} would be ambiguous; it could be a new scope which uses x and y, or it could be our assignment array. There would be next to no way to distinguish the two, so it's out of the question if we want the assignment array.

As for the dynamics, when compiling to C, this is what it would look like:
In the [a,b,c]=array_func() case:
Code: (cpp) [Select]
{
  Array tmp = array_func(); // This is copied verbatim
  switch (tmp.length) { default: // Array size is size_t; must be >= 0
    case 3: c = tmp[3]; // Waterfall
    case 2: b = tmp[2];
    case 1: a = tmp[1];
    case 0: ;
  }
}

In the [a,b,c] = scalar_func() special case:
Code: (cpp) [Select]
  c = b = a = scalar_func();

As for building an array, that's easy. Old ENIGMA can do that. [expression1, expression2, expression3] simply becomes this:
[snip=cpp](Array(3).put(0,expression1).put(1,expression2).put(2,expression3))[/snip]

Where [snip]Array(int N)[/snip] reserves N variants, and [snip]Array& Array::put(int, variant)[/snip] is the same as [snip]Array::operator[](int)::operator=(variant)[/snip].
Title: Re: Arrays
Post by: polygone on September 13, 2012, 02:16:13 pm
What about this though

Code: (edl) [Select]
a = b
[x, y] = get_some_coordinates();
Title: Re: Arrays
Post by: Josh @ Dreamland on September 13, 2012, 02:19:11 pm
This is an EDL feature; the expectation is that the user will distinguish those two with the use of a semicolon. However, if you have an idea to eliminate that, let's hear it.
Title: Re: Arrays
Post by: luiscubal on September 13, 2012, 02:43:34 pm
Agree with
Code: (edl) [Select]
[x, y] = array_func();

Disagree with
Code: (edl) [Select]
[x, y] = scalar_func();
Title: Re: Arrays
Post by: Josh @ Dreamland on September 13, 2012, 03:11:02 pm
What would you have [] = scalar do?
Title: Re: Arrays
Post by: IsmAvatar on September 13, 2012, 03:47:01 pm
Error/warn :-p
Seriously, though, what would the user expect [a,b] = 3; to do when a = b = 3 is just as easy to write.
Also, what happens with:
[a,b,c] = [1,2];
Title: Re: Arrays
Post by: TheExDeus on September 13, 2012, 03:48:48 pm
This is also cool, but what if I only want to set one of the variables? Like have:
Code: [Select]
[0, y] = get_some_coordinates();That wouldn't work would it?
Title: Re: Arrays
Post by: Josh @ Dreamland on September 13, 2012, 03:55:20 pm
No, that would throw a syntax error to the tune of "Assignment array elements must be variables."
Title: Re: Arrays
Post by: TheExDeus on September 13, 2012, 04:01:06 pm
So would there be a possibility to return only N'th result? From your previous example I see that this would probably work:
Code: [Select]
[x] = get_some_coordinates();As that would just return the first variable to x, but if I wanted the second one?
Title: Re: Arrays
Post by: Josh @ Dreamland on September 13, 2012, 04:04:34 pm
[snip=edl]y = get_some_coordinates()[2][/snip].
But I see the point you're trying to make. I guess we can allow using zero or maybe the null keyword to indicate that you don't want the field; otherwise, you'd do something like this:
Code: (edl) [Select]
int discard;
[discard,y] = get_some_coordinates();
Title: Re: Arrays
Post by: TheExDeus on September 13, 2012, 04:17:14 pm
Code: [Select]
y = get_some_coordinates()[2]Also works. I just didn't think of that for some reason (though I do it all the time in C++ with OpenCV).
Title: Re: Arrays
Post by: luiscubal on September 13, 2012, 04:59:20 pm
Here's my proposal.

1. If function returns a scalar, forbid [] syntax. Completely. It's worthless anyway.
2. If function returns Array, allow [] syntax but force the number of parameters to match.
3. If function returns Array but you don't want to use all parameters, use
Code: (edl) [Select]
[a, b, c, ...] = func();
Still, the array would be forced to have at least 3 elements.
4. If this is *still* not acceptable, you could have this:
Code: (edl) [Select]
[a, b?] = func();
or
Code: (edl) [Select]
[a, b=2]=func();
That code would work for func() returning both 1 or 2 parameters. It'd still be an error for 0 or more than 2 parameters (for 0, use a?. For more than 2, add the "...")
Code: (edl) [Select]
[a?, b?, ...] = func();
This is inspired by function arguments syntax.

As a final note, after an optional variable, all following variables must be optional. So this would still be an error:
Code: (edl) [Select]
[a?, b] = func(); //ERROR!

As an extra note, __unused could be used for worthless variables:
Code: (edl) [Select]
[__unused, x, __unused, __unused?, y?] = func();
cout << __unused << endl; //ERROR: __unused is not defined

If you dislike this syntax, this could also be used (although it might be more error-prone):
Code: (edl) [Select]
[, x, , ?, y?] = func();
Title: Re: Arrays
Post by: Josh @ Dreamland on September 13, 2012, 11:38:06 pm
I don't want to use ?, since ? is ternary. [snip=EDL](boolean_expression ? x : y) = 10;[/snip] is already valid EDL. It will remain so in the arrays, I imagine. I do like your [snip]...[/snip] to denote that the array may be larger. However, I like HaRRi's 0 idea better than __unused.

Perhaps as a prefix, ? could denote optionality.
[snip=EDL][0, x, y, ?z] = get_wxyz();[/snip]
Title: Re: Arrays
Post by: luiscubal on September 14, 2012, 07:21:16 am
Prefix, postfix. I really don't care. It was just a proposal.

For further headaches:
Code: (edl) [Select]
int& x = ...;
int& y = ...;
[ x > 2 ? x : y] = func();

(Basically, what if instead of just variables it actually allowed any reference? Non-references would still be forbidden)
Title: Re: Arrays
Post by: Josh @ Dreamland on September 14, 2012, 09:02:06 am
I was just going on about how that'd be fine. All I really need is to make sure JDI includes the & in variable types it coerces, then I can ask JDI for the type of ENIGMA's AST.
Title: Re: Arrays
Post by: luiscubal on September 14, 2012, 04:48:12 pm
Code: (edl) [Select]
[0, x] = func();

Seems to imply that the first element should be 0. Just like this:

Code: (edl) [Select]
Array res = func();
assert(res[0] == 0);
x = res[1];
Title: Re: Arrays
Post by: TheExDeus on September 15, 2012, 07:18:37 am
Then your code would also assert that the second element should be x, but it doesn't. You implying it should be 0 is just illogical. So I do like the 0 way to do this.
Title: Re: Arrays
Post by: polygone on September 15, 2012, 10:49:04 am
These things look like a mess to me.
Title: Re: Arrays
Post by: TheExDeus on September 15, 2012, 11:14:37 am
I am fine with just it being: x = func()[2]
Title: Re: Arrays
Post by: Josh @ Dreamland on September 15, 2012, 11:34:44 am
Agreed with HaRRi, again. Zero seems like an elegant solution.

I'd just make them use array subscripts, except it may not always be the case that the function returns an array of only two elements. It may return five, and the user needs only four.
Title: Re: Arrays
Post by: TheExDeus on September 15, 2012, 11:59:28 am
Then maybe this would also work:
Code: [Select]
[y, z]=func()[1,2]That would also allow changing the order of the return like:
Code: [Select]
[y, z]=func()[2,1]This would set the second param to z and third to y while leaving the first unused.

But that I think is unneeded. So using [] for a specific value and 0 for an array of values seems the best way.
Title: Re: Arrays
Post by: Josh @ Dreamland on September 15, 2012, 02:45:55 pm
Unfortunately, GML ambiguates [1,2]. It means the same as [1][2]. Otherwise we could do all sorts of neat array tricks.

Perhaps array[[1,2]] could work.
Title: Re: Arrays
Post by: luiscubal on September 16, 2012, 07:26:44 am
Hmmm...

Code: (edl) [Select]
[x,y,z] = func()[1..3]
Title: Re: Arrays
Post by: Josh @ Dreamland on September 16, 2012, 09:08:58 am
If we allow arbitrary element access by using an array as an array subscript, and we let 1..5 be the same as [1, 2, 3, 4, 5] (and maybe let 1..2..9 be [1,3,5,7,9]), then that will work.