HaxeFoundation / haxe-evolution

Repository for maintaining proposal for changes to the Haxe programming language
111 stars 58 forks source link

stack based tuples #38

Closed jdonaldson closed 5 years ago

jdonaldson commented 6 years ago

Here's a proposal for stack-based tuples.

var (a,b,c) = (1,2,3);

They could be used for key/value iteration:

for ((k,v) in map){
  trace('$k: $v');
}

Or, as async continuation expressions:

suspend function some_async_function(continuation : Bool->Int->Void){
 [...]
};
var (success : Bool ,value : Int) = some_async_function();

(check @nadako's proposal here : https://github.com/nadako/haxe-coroutines)

Or as multireturns (which have native support on some platforms):

 var (x,y,z) = tupleGenerator();

It should be possible to define a special kind of typedef for them, similar to a complex type:

stacktype StackType = (foo: Int, bar : Float, baz : String);

You could reference parts of the stack by name or index this way.

Rendered version

jdonaldson commented 6 years ago

See also :

  1. https://github.com/HaxeFoundation/haxe/issues/4300
  2. https://github.com/nadako/haxe-coroutines
  3. https://haxe.org/manual/target-lua-multireturns.html
ncannasse commented 6 years ago

I am not sure about it. Having used tuples in OCaml for a long time, I don't think they fit well in Haxe design.

You don't really want to have 4+ elements tuples because they are messy and then would be a lot better with proper field names ( = haxe structures ). 3 is a bit in the middle. 2 might be useful, 1 is... well....

So if the question is should we have tuples for the possibility of returning two values in a function, my conclusion would be no.

jdonaldson commented 6 years ago

I agree, if this proposal is just about handling 2-value multireturns, it's not worth it.

Let's see if @nadako thinks this would work for async scenarios. I think stack based tuples may not get used much for Haxe code that is written from scratch, but if you're writing a lot of async wrappers for pre-existing callback functions, or if you're writing externs for messy multireturns I think it's a good idea.

ncannasse commented 6 years ago

stack based multi return is a bad optimization for us I think, because we have very few platforms that can implement it. So this will lead to some users using them massively and then later noticing they are causing a lot of performance problems on other platforms.

jdonaldson commented 6 years ago

I think there's ways to reduce the overhead on platforms that can't implement natively, but I defer to your experience on that point.

Is the mechanism for async handling clear? I haven't had any feedback on that. The support there will be the same for all platforms.

If necessary I can split the proposal here and/or refactor.

nadako commented 6 years ago

I'm not sure about async stuff atm, but I think Haxe would benefit from tuples a lot. We cannot and we should not make any promises about whether they are stack-allocated or not, but if we say they are non-nullable and read-only, they can be implemented in a native and/or optimized way on many targets, which is not the case with anonymous structures/classes.

As for the usefullness, I think they should have "use-site only" field names, similar to new function type with named argument, so, e.g.:

// these two types unify (same arity and types)
typedef T = (a:Int, b:String);
typedef T2 = (c:Int, d:String);

var t1:T = (10, "hi")
trace(t1.a, t1.b);

var t2:T2 = t1;
trace(t2.c, t2.d);

Unpacking into local vars is a topic that is not strictly related to tuples, and my current opinion is that we should go for a convention-based destructuring, similar to one implemented in Kotlin, basically:

class Pair<T1,T2> {
  public var _1:T1;
  public var _2:T2;
}

// and then
var (a, b) = somePair;

// translated into:
var a = somePair._1;
var b = somePair._2;

This convention would then be simply used by tuples, so any tuple type would have _1/_2/etc. fields.

ncannasse commented 6 years ago

I have designed Haxe to be as simple as possible. Simple to read, simple to learn. This means that only the feature that brings something expressive enough to justify adding them to the syntax/language should be considered for addition. Given the amount of overlap between Tuples and anonymous structures, and the ability to generate these tuples with macro, I'm not in favor of adding them to the official language syntax.

bendmorris commented 6 years ago

To clarify the status of this proposal - is this a veto by @ncannasse, or a no vote? If the latter, it sounds like the vote is currently 1 in favor, 1 opposed?

Justinfront commented 6 years ago

Is there a repo I can try them out where the c++ and js implementations provide both speed and expressive advantages, along with predictable special cases, I think that should be a minimum before you start counting votes. If users like me feel they offer an advantage then your halfway there, I already know Tuples so would be keen to see them as part of the language. Time to demo the implementation, if the theory was enough Nicolas would have agreed? So initially myself - I only care about js and c++... very pragmatic, flash would be nice but like many of the other targets not the main USP. benmorris no disrespect but I have only seen your commits for a short time - so if your not happy with Nicolas vote then rather than talk about votes I think you need to get an implement together so we can try it out, seems it's at that stage?

bendmorris commented 6 years ago

so if your not happy with Nicolas vote...

I'm simply asking for an update on the status of this proposal - please don't read any more intent into that.

Edit: and I'm not volunteering to implement this either :) doesn't seem prudent to work on features that don't have a good chance of being accepted...

Justinfront commented 6 years ago

Well I am happy to try out a branch if you have one.

jdonaldson commented 6 years ago

FWIW this feature would require a lot of buy-in from the rest of the compiler team. The lack of a stack-indexed datastructure is a minor nuisance now, but it seems like a really good idea for certain async features.

Also as a side note, I realize not all platforms would support these datastructures in all cases. They could be emulated with a simple array in most cases I think.

ncannasse commented 6 years ago

We might reconsider this while working on Haxe-in-Haxe (OCaml backend etc) but atm I still don't think it would make a good addition for Haxe "core" language. We will eventually experiment it for the OCaml backend if necessary and see how it plays.

Simn commented 6 years ago

I want destructuring, but I don't think I want tuples. I also don't want to overload the ( ) syntax any further.

jdonaldson commented 6 years ago

I propose we add new bracket symbols in that case:

var 🍺a,b,c 🍺 = 🍺1,2,3 🍺

markknol commented 6 years ago

Fwiw, in typescript they use { } for destructuring

 let {x,y} = point;
RealyUniqueName commented 5 years ago

We discussed it and decided to close this proposal for the reasons mentioned above. However, we should look into providing a way to access platform-specific tuples.