I’ll keep my thoughts brief here. I could go either way on usingnamespace but I am leaning towards removing it.
usingnamespace is a handy utility - it does a lot of work very quickly and it’s one of the most “intheritance-styled” things that we have in Zig. However, it’s more restrictive than inheritance in a good way. We can’t traffic in state with it in the form of injecting instance-level member variables.
The more time I’ve spent around implementation-injection facilities, the less I’ve come to like them. They are very useful from the perspective of an author, but as a reader I’ve often found them to make otherwise trivial refactors more annoying than they should be. They’re also a common source of sneaky bugs (probably less in the case of usingnamespace than in the case of full-fledged inheritance).
Recording my perspective as a beginner here(I voted I don’t know), before I forget what it’s like to a beginner.
My first and only experience with usingnamespace has been in reading about it in the documentation. I have not felt the need to use it after writing ~7000 lines of zig. But I also haven’t gotten to interfaces yet (and still don’t know what I am doing there yet after consuming a few hours of content).
My first impression of it was that it was not immediately clear to me what it was. But i come from python so I didn’t really know what namespaces were for.
My second impression of it was that it severely destroys the readability of my code (in a similar manner to inheritance in python). Adding a single little line can drastically change the behavior / expectations of my program in an easily hidable way.
I have zero experience with usingnamespace but voted to remove it because it makes incremental compilation easier.
What Zig-pilled me is the fact that I serve the compiler so I can get better tooling, performance, and control. I’d like Zig to continue moving forward in that direction with this change.
It can be added back if it’s that much of a dealbreaker. And the factors surrounding that decision would be apparent once the much more complex language/toolchain features are fleshed out - i.e. when incremental compilation, async, and safe recursion are all combined.
I have quite a bit of work to do because of this removal, but I’m not changing my stance. I’d rather work with a language where maintainers are willing to break things because they have a clear vision of the future, than a conservative language designed by committee that avoids breaking change, even when necessary out of fear that software engineers would have to work and actually fix their code. If they believe something should be removed, then so be it
A poll was a bad choice here. People who are saying “I think it should be removed because other people think it should be removed” are not expressing an opinion, they’re engaging in a Keynesian Beauty Contest.
A poll removes the obligation to provide an informed opinion, and makes this thread noise, not signal. Polls are for languages designed by committee.
// program.zig
const foo = @import("fancy-lib.zig");
const log = foo.debug.print;
pub fn main() void {
log("I'm fooling you - actually I came from 'std', not from 'fancy-lib'...\n", .{});
}
and after this I am thinking I do not need such a “re-exporting”,
I’d better use const properName = @import("some")in every file
where I need that “some”.
So I voted for removing.
P.S.
Also I looked into my /usr/share/mc/syntax/zig.syntax and…
there is no usingnamespace in there, I just did not put this word into it.
I don’t think that’s the case - if you look at the github, you’ll see that there are similar metrics showing up on the opening post (unless we’re going to count both results as a social phenomenon).
On the contrary, I think we’re seeing more involvement because most people probably don’t have a strong enough opinion on the subject to motivate a writeup.
Also, I think people who are motivated will express an opinion regardless of a poll.
i’m still a relative newcomer to zig, so i’m not necessarily aware of some of “deep” implementation issues as well as all of the design alternatives…
having had a favorable experience with namespaces back in C++, i immediately knew the situations where this feature would be helpful…
based on the description in the docs (plus examples at this forum), it initially struck me as a very convenient way to merge disjunct source files with lots of top-level declarations… the alternative would have me explicitly creating a top-level file whose declarations are basically “renames” of internally imported declarations…
but as i progressed further in my design of Zig•EM i relied on usingnamespace in a rather novel manner… to illustrate, here’s an example from a recent article of mine…
long story short, but each .em.zig source file is compiled TWICE in the Zig•EM framework: first with the file’s top-level declarations merged with the EM__META namespace; and then with the file’s top-level declarations merged with the EM__TARG namespace…
[[ read on in this article to understand the motivation ]]
lacking usingnamespace, i could very easily generate TWO derivative source-files that respectively merge in the EM__META and EM__TARG declarations… i’m not sure whether there is an alternative solution using other language constructs…
i’m not sure that the Mixin alternative described by @AndrewCodeDev would apply here… a recent topic talking about “source code rewrite transformations” had @mnemnion suggesting a solution with usingnamespace
in summary, it’s essential in my current framework design… but if i start doing some upstream source-code transformation anyway (for situations for which there is my only alternative), then i can easily subsume my current use-cases for usingnamespace…
Yes, my suggestion is not a direct replacement. usingnamespace is it’s own beast entirely and there are some cases that it won’t cover. For basic code deduplication it can serve much the same purpose.
To be clear, I’m not hard-line convinced it’s a bad thing, but I’m leaning away from it given my experience with implementation injection.
I should have read through the issue and the comments on it before voting. I voted for “I don’t have a preference”. Before this, i have never used usingnamespace nor really understood why it would be used.
After reading the issue, I lean more towards “remove”, for the possible benefits that it can provide for incremental compilation, and recognizing that I have had the problem of dealing with trying to find code that is re-exported in this way. However I also agree with the commenters that “readability” is not really a strong argument for removing it. Many of the examples of replacements are (in my opinon) less readable. However, I do understand that the code is more discoverable in the new form.
My soapbox about readability
“Readability” of code is proportional to a person’s experience reading the kind of code in question. As more and more of the mixin pattern is proliferated, those with experience with zig code will find it more readable. So the main question with readabilty is “How obvious is the code”/“How easy is it to grok” for someone uninitiated.
As an example the use of goto in C for error handling and releasing resources is completely foreign to someone coming from python, and would be deemed “bad” code for readability. But someone who has seen the pattern 1000 times immediately understands what is going on.
I think usingnamespace can fall under a tool/syntax/semantic that makes some of these patterns more readable, but comes at a cost of complexity and discoverability.
It would be nice if after it is removed (if it is removed), we were able to bring in some of the functionality back, with less complexity.
Check out the linked issue under the section hading “Use Cases”. There are examples of alternative code for the most common usingnamespace use cases including implementation switching and mixins.
I’v toyed around with making mixins both usingnamespace and @fieldParentPtr. The latter is more powerful, because it can contain context, it’s easy to pass the mixin interface as an argument, and it’s also more clear because of the possibility of conflicting declaration in multiple namespaces.
I don’t think anymore that usingnamespace is that good for making mixins.
I’m not sure there was ever this obligation? I know this obligation exists on the GitHub issue tracker, because I recall Andrew K saying so on one of the long issues, but this is a forum.
Forums are noisy, forums are messy. We have some things to help cut through noise (like count, marking solutions) but this is a brainstorming post (no solution marking).
Beginners like myself come to the forum for the noise, we learn from the noise, we are born in it, molded by it (batman!). We are all fleshy LLMs anyway. Often learning is accelerated by doing it wrong first (making noise), and going back to fix it up (refactoring).
TLDR: the forum is attractive to beginners because it is messy and low-obligation. Nobody has to read the forum if they don’t want to. On the other end of the spectrum is the GitHub issue tracker, where we are requiring someone else to read something, and make a decision.