-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
make implicit cast syntax different than function call syntax #1757
Comments
This also removes the choice of |
How so? The choice becomes |
I meant, that we currently have these two, very similar, choices when there should really only be one way to do this. At least with this new |
This is tangential, but is "implicit" the right word for this? |
I don't think we would do that because the decision to put a type or to allow inference has implications for maintenance of the software. For example, if you want your code to be generic friendly you could purposefully omit a type; however if some code was brittle and you wanted to get a compile error if anything changed, you could put the type there.
Feel free to suggest alternative names. It's called "implicit" because it's the same cast semantically as what happens when you do this: fn foo(x: i32) void {}
test "a" {
foo(1); // 1 is implicitly casted to i32
} This is exactly equivalent to (in status quo zig) |
I would say:
|
These are semantically the same as each other
These are not semantically the same as the items in the previous list
So what we need is names for each category. How about the first category is called "casting", and the second category is called "conversion"? |
I don't really want to call the third example ( Also, this would be a user (programmer) experience downgrade:
|
Let's say we eliminated the |
I don’t really see the issue to begin with. |
This kind of cast is always preferable to any of the others, because it's always safe (will never emit a safety check), never mangles information, and always works at compile time. It's the first kind of cast that coders should reach for, before resorting to the others. If we didn't have expression syntax for it, one would have to create a variable in order to get the behavior, but this has different semantics. When it's in an expression, the result location (this is a copy elision concept) is propagated. With a separate variable, there is separate memory allocated. Some particularly useful expressions that use this construct:
|
If this type of cast is will only ever be available/possible with built in types (numeric coercions, etc.) and not usable for user-types[1], then I think it would be more consistent to use the @-prefix syntax. This would seem to agree with the "Favour reading code over writing code" and "Communicate intent precisely" insofar as the source of behaviour (compiler defined vs. user/std lib defined) goes. Unambiguous function call syntax would also make tooling easier to write, albeit marginally. [1] That is, this will never be valid: |
I'm pretty sure that I want this - make implicit cast syntax different than function call syntax - but I'm not satisfied with any of the syntax ideas so far. I want to press "accept" but I want a satisfying syntax proposal first. I suppose one option is how Rust does it: |
A slight alternative to
|
What about reusing the type declaration syntax?
Might need some playing with the whitespace placement. Pro: Concept has only one syntax, less to learn. |
…unc), with safety checks. Finishing this depends on ziglang#1757. I'd rather not re-work ir_gen_node_raw for explicit casts (signed to unsigned, and safe narrowing casts) when that is upcoming.
…unc), with safety checks. Finishing this depends on ziglang#1757. I'd rather not re-work ir_gen_node_raw for explicit casts (signed to unsigned, and safe narrowing casts) when that is upcoming.
…unc), with safety checks. Finishing this depends on ziglang#1757. I'd rather not re-work ir_gen_node_raw for explicit casts (signed to unsigned, and safe narrowing casts) when that is upcoming.
This is now accepted with |
…unc), with safety checks. Finishing this depends on ziglang#1757. I'd rather not re-work ir_gen_node_raw for explicit casts (signed to unsigned, and safe narrowing casts) when that is upcoming. v2: @truncate can now take a scalar type
Landed in 6d5abf8 |
…unc), with safety checks. Finishing this depends on ziglang#1757. I'd rather not re-work ir_gen_node_raw for explicit casts (signed to unsigned, and safe narrowing casts) when that is upcoming. v2: @truncate can now take a scalar type
The implicit cast syntax was changed in <ziglang/zig#1757> in a breaking way.
The implicit cast syntax was changed in <ziglang/zig#1757> in a breaking way.
The implicit cast syntax was changed in <ziglang/zig#1757> in a breaking way.
Accepted Proposal
Given:
A(B)
and no other information it is impossible to tell if this is a function call or an implicit cast.Instead
@cast(A, B)
would be implicit cast syntax, andA(B)
would then be unambiguously function call syntax.This is arguably a readability improvement for this example:
const a = ([*]const u32)((*const [1]u32)(&foo[20]));
becomesconst a = @cast([*]const u32, @cast(*const [1]u32, &foo[20]));
And makes this example worse:
i32(1234)
becomes@cast(i32, 1234)
The text was updated successfully, but these errors were encountered: