-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
named return values and reference-assignment operators #286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Proposal: a reference assignment statement I think this idea is syntactically sound, but "set" is not be the best word. It doesn't really describe what the statement is doing, the block after it is where things are actually set. It does essentially what the reference-assignment operator proposed above does.
Other names to consider:
|
See #287 for my copy eliding proposal. With that proposal the following is fine (in the context of this issue's OP): fn foo() -> (result: %Value) {
result = Value.One { Vec2 { .x = 1, .y = 2, }};
}
// or even without a named return value:
fn foo() -> %Value {
Value.One { Vec2 { .x = 1, .y = 2, }}
} So here's my proposal to throw into the bucket of ideas for this issue's reference-assignment usecase: Introduce named return values for blocks. I'm not super excited about this idea, but here it is. fn foo() -> (result: %Value) {
// where a Vec2 value is expected, we provide a block that returns a Vec2.
// the block's return value is named vec.
result = Value.One { -> (vec: Vec2) {
vec.x = 1;
vec.y = 2;
}};
} This syntax doesn't introduce any new keywords. I'm not sure if this would introduce ambiguity with the inline assembly syntax, but it doesn't introduce any ambiguity elsewhere. |
@thejoshwolfe - I like where you're going, and think the sweet spot is actually somewhere between our suggestions... How about this?
Which with your copy eliding rules makes it just like a regular assignment. It's still sort of a named return value for a block or a named assignment address, equivalent to something like
I like the |...| syntax for this because of how it appears in the rest of zig:
Basically, the |...| creates a view into something created by the statement it's in. The same syntax, for a %Vec2
In this proposal, the statement the |...| is drawing from is equivalent to an assignment, "unsugared": The I'm about to comment on the null/error unwrapping vs try/test blocks and some exploration of the |...| concept that dips into closures. Would doing something like this make sense?
|
i like where you're going @raulgrell. Consider the comment I just added in #287, which could allow this syntax: fn foo() -> %Value {
Value.One {
var vec: Vec2 = undefined;
vec.x = 1;
vec.y = 2;
vec
}
} This is a very small departure from existing Zig constructs, and solves this issue entirely with copy eliding rules. That being said, I'm not sure we want the copy eliding rules to be this sophisticated. See #287. |
fn baz() -> (result: %Func ) {
// Should this work?
result = selfFn; // <---- no. you need to reference Func.A
// Or this ?
result = Func.A { selfFn } // <---- that should work already
} |
Closing in favor of well defined copy eliding semantics (#287) which accomplishes all the goals of named return values. |
Proposal:
Covers part of #83.
The syntax looks pretty scary and is certainly not intuitive.
But the semantics make sense. The point of this is so that the same init code can work at compile time and at runtime. Consider an init method. Here's status quo
std.rand.Rand
:This is problematic because you cannot initialize Rand at compile time. Also the usage looks like this:
Better usage would look like:
And this would work the same at run-time or compile-time.
Although I guess technically you can still get it to work at compile-time status quo:
This is still less than ideal. We could have the better syntax with this definition:
The text was updated successfully, but these errors were encountered: