Nested structs and functions within structs
ballercat opened this issue · comments
Goal
Allow for nested structs and functions within structs.
Overview
Depends on (#28)
Closures are cool, but to be useful you'd want to return an object/struct with a closure or another struct as a field.
Basically, this syntax should be possible
type lambda Closure = () => i32;
type Struct = {
increment: Closure,
decrement: Closure
};
function getActions(): Struct {
let x: i32 = 0;
const result: Struct = 0;
result = {
increment: (): i32 => {
x += 1;
return x;
},
decrement: (): i32 => {
x -= 1;
return x;
},
getX: (): i32 => { return x; }
};
return result;
}
export function test() : i32 {
const actions: Struct = getActions();
actions.increment();
actions.increment();
actions.decrement();
// should be 1
return actions.getX();
}
This should make the syntax much more expressive and allow for a wide range of applications.
Acceptance Criteria
- Allow nested struct types within other structs
- Allow closure types within structs
- Test everything
Why using the lambda
keyword?
In TS & Flow the syntax is:
type Closure = () => i32;
It's easier to compile this way.
I assumed, but I think that introducing a new keyword is problematic. Maybe this can be solved with a special generic?
How would a generic function type work for this? Could you be more specific, what syntax would be an alternative?
For background, I initially did use regular functions types for closures, but the two have fundamentally different representations in the binary. This means that syntax becomes ambiguous, where a function, for example, can return either a closure or a function pointer. By extension, any use of a return value from a function like this is now also ambiguous.
All this means is that types have to be specific to the thing they represent. If there is a way to express a closure being different with existing syntax, I'm all for it though.
It also may be possible to omit the lambda
keyword in the future, but I won't fix this until we are well on our way to a 1.0.0 release. Unless someone puts up an MR to resolve the ambiguity I described above.
You can mark external functions explicitly:
-type Log = (i32) => void;
+type Log = External<(i32) => void>;
Cool, so are you suggesting that we should have a built-in type for Lambda
instead of a keyword? That could work I think with something like this
-type lambda Closure = () => i32;
+type Closure = Lambda<() => i32>;
or
-type lambda Closure = () => i32;
+type FunctionType = () => i32;
+type Closure = Lambda<FunctionType>
I personally have not seen this particular use of generics before, but this could work. Would need a type parser change/PR but I like it 👍
Might I also suggest replacing the 'type' keyword for 'lambda'. For example 'lambda Func = () => i32’
Note: I'm on my phone and I'm unsure how the syntax style formatting works.