-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Make assignment operations expressions #11805
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
Am I interpreting correctly that this proposal would similarly disallow function calls resulting in fn wrapper(target_fn: anytype) @typeInfo(target_fn).Fn.return_type.? {
return target_fn();
} would now only be valid for a |
Yes that's correct, this would disallow all expressions that evaluate to a void type including calls to functions with return type void. You're right that this will require some more special casing of void in generic code than the status quo requires. I think this is an acceptable tradeoff in your example but this brings more problematic cases to mind such as In implementing such a generic data structure, there might be a function like this: fn put(self: *Self, key: K, value: V) void {
self.items[i].key = key;
self.items[i].value = value; // if V is void then the expression `value` has type void.
} Adding another exception alongside |
I wounder if it is really worth the effort preventing people from using assignments in expressions. Currently, we allow function that return void everywhere, and you don't really see people using that for anything spicy, because it does not have much use. |
Just an observation, all motivating examples listed here make use of if expressions (grammar element I assume you found some downside with this, compared to the proposed solution? |
This is a good point. We already allow I may have gotten too hung up on trying to keep the language as strict or stricter than status quo at the cost of significantly increasing complexity. I think that the examples in #9059 show that there are some weird edge cases with the status quo of void expressions, but that is perhaps orthogonal to allowing usage of assignments as expressions. I think I'll move the "disallow void expressions in most contexts" part of this proposal over to #9059 and reduce the scope of this to allowing assignment operations in expressions. |
Hey, Has there been any work done on this proposal ? As of zig 0.13.0, you still cannot do this:
You have to make the assignment an expression:
Are there any plans to make assignments the same as normal expressions ? |
I think it's interesting to note that the main benefit of making assignments act as statements rather than as expressions is avoiding the pitfall seen in C where However in zig this is already avoided/avoidable in two ways:
In effect, status quo assignments-as-statements acts as a redundant protection against a solved problem, and incur an extra unnecessary cost in complexity in the grammar, and adds special cases to remember in general usage, ie |
@InKryption While I generally agree with your point, the single exception I'll nitpick is generic contexts that allow both |
I'm still a student, so I might be ignorant on the topic. However, I cannot think of a function that is evaluated at compile time doing something that will not result in an error if passed a At least, from my understanding, |
@abvee I mostly expect usage of You could also write a function to handle a function result, f.e. repackage an error union |
I'm relatively new to the language, but would this not cause some potential confusion when creating structs? This would be allowed: var x = 0;
var y = 0;
var z = 0;
const my_struct = .{x = 1, y = 2, z = 3}; and |
@Aldlevine The original post states "Assignment expressions would be defined to always evaluate to type/value void." |
Currently the following code snippets which look valid do not parse:
Some of these examples are mentioned in #5731 and #3749.
This is because the grammar does not treat assignment operations such as
x = 1
ory += 5
as expressions and only allows them in specific contexts.I propose changing the grammar to make assignment operations normal expressions, example patch here. I think this may unlock some further cleanups to the grammar as well not included in that example patch.
Assignment expressions would be defined to always evaluate to type/value void. In effect, we already allow expressions with exactly these semantics such as
{ x = 1; }
. This proposal merely makes the grammar a bit more consistent and allows writing more intuitive code as the examples above demonstrate.Original additional proposal to disallow void expressions in most contexts
That change alone would however bring some downsides. For example code like this would become valid: ```zig test { var y: u32 = 0; var x = (y = 1); // declares variable x with type/value void, assigns 1 to y } ``` This is obviously undesirable, therefore I propose disallowing expressions of type void in all contexts except: 1. As a statement in a block. 2. As the operand of `defer`/`errdefer`/`suspend`. 4. In the continue expression of a while loop. 5. In the body and else branch of `if`/`while`/`for` if the expression as a whole evaluates to type void. 6. In `switch` cases if the switch as a whole evaluates to type void. 7. As the operand of `comptime`/`nosuspend` if the expression as a whole evaluates to type void.Note that rules 4, 5, and 6 are transitive, the outer
if
/while
/for
/switch
/comptime
/nosuspend
must also appear in a context where void expressions are permitted.I also propose that an exception be made for the empty block
{}
which is permitted as an expression in all contexts as the canonical void value.These proposed rules would make the
var x = (y = 1);
snippet a compile error while allowing the motivating examples above.These rules would also effectively implement #9059. As discussed there, there are already cases in the language where allowing void expressions causes confusion and this proposal would help eliminate those.
The text was updated successfully, but these errors were encountered: