-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Proposal/discussion: Decide on a preference for generic functions #522
Comments
I like proposal 1, although it's a tough sell. One big issue here is Just to emphasize that there's two ways to do it, here's an excerpt from the math module: I agree that this is a violation of the zen of zig. The issue where the type system doesn't tell you that a |
What about being explicit and using We should always pass some types as parameters if we use generics, but we should be able to compute types by using comptime functions returning types. I think this should be allowed if it already isn't possible.
Now we would be able to always be explicit in some way. The use of
The example might be a bit bad given we can easily determinate that a is T, but there are situations where you would just want to get the type of a field, but it might be dependant on many comptime type arguments which also might be computed. |
I agree math.max is better as I think status quo is (3) compromise. 2 examples where var seems right:
/// Renders fmt string with args, calling output with slices of bytes.
/// Return false from output function and output will not be called again.
/// Returns false if output ever returned false, true otherwise.
pub fn format(context: var, output: fn(@typeOf(context), []const u8)->bool,
comptime fmt: []const u8, args: ...) -> bool Here, Edit: I realized you can still accomplish the same thing by taking the type explicitly as the first argument. My mistake. |
So basically one could say that So basically we should just make it clear how they are different and always use comptime T: type where the semantics of ´var´ aren't required. Perhaps it shouldn't be just var but instead comptime T: value or something? |
AFAICT, I think the varargs syntax could work like it does today. That is, with I agree with @thejoshwolfe that there’s a lot of unfortunate magic attached to |
It seems to me that if you're going to pass I think I can come up with a flow chart of when to use
As for magic, let's list the magic attached to
That's all I can think of. Anything else? |
@andrewrk does something trivial like I don’t know anything about the internal magic of |
I'd say yes. |
Backing up a step here. Where is "..." used? Just printf-like things? Are there other more "Zig-like" ways to do the same thing keeping "be explicit" in mind? It seems like "..." is itself a bit of departure from one of the key Zig points: be explicit. Taking the case of the format function, what if I pass a mutex as one of the arguments? Shouldn't that be a compile time error? You should not be able to copy a mutex. A mutex reference, sure. |
I strongly prefer to have the type explicit. While this makes for a bit of boilerplate, it serves a dual purpose: 1) it tells the compiler exact what is required and so it can check the inputs, 2) it forces the programmer to think about it and make sure that it makes sense. No hidden magic. If the whole purpose of var is to support the things that @andrewrk mentioned, but ... in particular, are there better ways of doing those things? |
|
@thejoshwolfe, your filter/sort/map example is interesting. I had not thought of that. That is something that is covered in the tuple idea (or []var slice option of it) in #533. Can you assign to a
If so, how is type checking done? |
This discussion seems to be more about |
just ran into the same issue #1205 (comment) not sure what is better though, I think the vom-time thing is a bit too verbose but the var thing (without interfaces hehe) feels a bit generic as well. |
Another idiosyncrasy with |
Functions taking generic arguments can be implicitly or duckly typed, taking
var
and maybe making use of@typeOf
:Or they can be explicitly typed, taking the type as an argument:
That there are these two different ways to do this seems to go against the Zen of Zig, in particular “Only one obvious way to do things”.
Proposal 1: Ban/disfavor
var
For the callee, a
var
is essentially just a type and a value bundled together, so changing a function to take each separately is usually trivial (there might be an issue with passing integer literals, but I don't believe it would be a big problem to reify them to a concrete integer type instead).For the caller, things are different: we introduce an entire new argument! This is a loss of ergonomics, but maybe a win in clarity?
Some pain points would be functions generic over multiple types that usually, but not always, are the same, e.g.:
I’m not sure this is sufficiently better than using
and having the arguments be cast to a parent/wrapper type, though.
Functions taking
...
arguments would also need to pass the type on to its called functions, but I don't think this would be much of a problem in practice.Proposal 2: Embrace
var
Use
var
everywhere. This would mean rewriting the above functions to:This will certainly make the functions more ergonomic to call, but there are two major problems:
Using
var
essentially bypasses the explicit type system. In particular, it's now impossible to declaremem.max
'sslice
to be a slice; you'll have to rely on duckly typing or casts/assertions in the function body itself.The error messages will generally be less helpful, since it's impossible to type-check arguments up front.
As a very minor point, this is equally unergonomic as Proposal 1 when passing integer literals to functions:
In addition, some functions will still require an explicit type to be passed:
Proposal 3: Compromise, somehow
Embrace that some kinds of functions should take explicit types, while others should take implicit types, essentially separating function-like functions from macro-like functions. I can't think of a good metric for what functions would fit in which categories.
I’m partial towards Proposal 1, but am aware it might be the most extreme of the three.
I think it’s important to decide on a policy; not necessarily one of these three. If I’m misunderstanding something, or I seem confusing/confused, please let me know!
I’m very curious to see how the language will evolve. :)
The text was updated successfully, but these errors were encountered: