I’m working on a template language that compiles down to Zig, and it would help me a LOT if I could have unused function parameters without explicitly discarding them. I assume there is no way to do that, but I thought I’d ask anyway and maybe I’ll be surprised.
I’d let the others answer directly, but I can suggest to use anytype and pass void, or an optional with null as a workaround.
No, this is not possible.
However if you want to transpile and don’t care about whether the result is readable, you could always discard all function parameters with _ = ¶m_name;, it is ugly, but at least you could compile the code until you figure out a better solution.
If you use the ZLS VSCode extension, it has an option that automatically adds and removes the discards based on usage. Would be nice to have equivalent functionality in other code editors as well.
Thanks, it didn’t occur to me I could fool the compiler like this to accept “useless” discards. The thing is, for a proper fix, I need to do liveness analysis on the Zig code inside the template that I currently treat as opaque. I really wanted to avoid having to understand the Zig code, so discarding all params like this helps me a lot.
You have to discard them. A Few tips you can use:
-
you can discard in the function declaration:
fn foo(_: i32) {} // discards the integer. -
you can discard many things with a tuple
fn foo(a: i32, b: i32, c: i32) void { _ = .{a, b, c}; }
As someone who regularly watch videos about air crash investigations, I found this arrangement completely insane. Imagine if the ground proximity warning system of a passenger jet works in manner. It’d go off whenever the radar return indicates the plane is near the ground. During landing, pilots would be greeted by continual warnings of “TERRAN AHEAD! PULL UP!”. And the same when their plane is just standing in line waiting for take-off. How would pilots react to such an asinine system? Now imagine that they’re offered, as a solution, a voice-activated robot arm that automatically pushes the mute button.
You just described why zig has this error and why you can get around it explicitly.
The zls feature is off by default, and I don’t think anyone who understands the utility of this language design would ever turn it on.
But not everyone is writing high stakes software, I don’t see why they shouldn’t be allowed this convenience.
And I would expect anyone who is writing high stakes software to know better than to use such a feature.
It doesn’t really “mute” it does it? Since the discards are either added or removed from your diff. That’s the whole point, that the source code doesn’t lie.
That’s the nice thing about the solution being editor based. It’s out of scope of the language. So you and I can both have our shared preference, other people can have their preference of ignoring these errors, but we all enjoy reading uniform, standardized code that lists all discards explicitly.
I was recently reminded that there is still missing tooling for one aspect of this situation, and is, I think, the primary reason complaints about this are this persistent:
There is currently no difference between telling Zig, ZLS, etc:
a) “I’ll add a use for it later, I’m working on it. Please let me test what I have so far”
b) “No, I do not intend to (ever) use it, I have this in here so I can ex: share an API with something else that does need it”
The former should ring alarm bells if it makes it to a certain stage of the development/release cycle, the latter should not.
Then you might be happy to know that in the future the zig compiler will still emit artifacts after a compile error that will trip a panic once it gets to the point of the compile error.
I imagine unused variables will panic at the end of the scope/function.
This lets you test if your logic is correct without having to appease the compiler first.
I believe the roc language already does this, they are at least planing to do it.
It is interesting how Andrew and (forgive me for forgetting his name, I’ll just call him “the roc” for fun) independently came to the same solution
Do you mean Richard Feldman? rtfeldman (Richard Feldman) · GitHub
Adding placeholder to code is a nice feature of ZLS, it can be enabled in the zls config file.
Source code might not lie but our brains do. Years ago I was working as a tutor as my university. During a particular training exercise, we were asked to circle all occurrences of “the” in an article. Supposed to be easy, but none of us managed to get over 50%. As the head tutor explained, because we were all engineering majors, our brains were conditioned to filter out low-value information–in this case occurrences of “the”. Even though they were in front of our eyes we couldn’t perceived them.
Another example. From your profile picture I see that you wear glasses. I bet that you don’t see the frame or the nose pads.
When something is ever present, after a while we stop seeing it altogether. That’ why we need to be careful when it comes to warning messages. They need to be relevant and actionable. Otherwise people would become desensitized.
And that’s what has happened with the issue at hand. A function accepting a parameter that it does nothing with is extraordinary if you think about. It defers our normal expectation. Different inputs should produce different outputs. It’s a situation that demands an explanation. We don’t get that now because the unused variable warning pops up all the time.
This can be reduced significantly by just not adding variables/parameters until you need them.
There is also the practice of putting discards near their definition instead of buried somewhere else.
Emphasis on my first point, I find that I really don’t have unused variables/parameters often. When I do, it’s because the function needs a specific signature to be passed/used by something else.
Outside that most of my discards are the return of a function that I really don’t need.
It has never been an issue for me in zig, even in languages that don’t have explicit discards it hasn’t been an issue. What has been an issue is not knowing if a variable has been used, in zig if I follow my own advice I can see immediately the lack of a discard after its definition.
It’s not a warning though, is it. It’s a compile error. So it gets dealt with, or you don’t run the program. In fact that’s rather the point.
I actually agree with you about the “normalization of deviance”, and consider it one of the strongest, if not the strongest, argument for Zig’s liveness rule.
This is exactly why Zig has ‘compile errors’ instead of ‘warnings’; they must be addressed, and no one can ignore them. Even low-priority compile errors cannot be ignored by anyone.
For these situations, I have a simple personal pre-commit hook in Git that will prevent me from committing anything containing the word nocheckin. So, to temporarily discard a value during development, I would do this:
_ = discarded_value; //nocheckin
Of course, this won’t apply if you intend to do this across commits, but then you could have something similar in CI that would e.g. prevent you from merging a branch if it has a certain word in it.
Here's the hook if you're interested
#!/usr/bin/env bash
set -e
exit_code=0
if [[ "$(git config user.nocheckin)" != 'false' && "$IGNORE_NOCHECKIN" != '1' ]]; then
# get the staged files
s_files=$(git diff --name-only --cached --diff-filter=d)
# if a staged file contains the keyword, cancel this commit
for s_file in ${s_files}; do
if git grep -q -iF nocheckin :"$s_file"; then
echo "ERROR: ${s_file} contains the keyword nocheckin"
exit_code=1
fi
done
fi
exit $exit_code
Well, it’s an error by choice. And there’s nothing wrong with that. It just needs to fire at appropriate moments. Going back to aviation safety, GPWS alerts are not advisory in nature. Pilots are trained to always obey the system. If it says “PULL UP!” you pull up. And they would only do that when they have full trust in the system. It cannot cry wolf all the times.
On many occasions already I’ve pushed for disabling the check for unused/unmutated variables when optimize is Debug. That setting is used when a programmer is still working on a piece of code. You cannot know if he has forgotten to use or change a variable because that’s an event that still lies in the future–or not. These checks are looking for conditions that logically cannot exist. That’s why the false positive rate is so absurdly high. At least 90% of the times when you get the unused/unmutated variable error it’s bogus.
There are no false positives. 100% of the time, if you get this error, your source code is missing a line of code to discard the variable.