Rationale behind @import at the end of file

You are in control when you update your dependencies and can run tests and tools to make sure that it works. If you want to nail down your application and harden it (while using a language that is still in development btw.), then I expect you to create your own tools to make sure, custom build steps that run tools and tests that verify that it does what you want it to.

One way is that you can create something that enumerates all the available declarations and creates a sort of lock file for them then you review those and commit the lock file to your repository, once new declarations appear you can manually approve or reject those.


The way I see it the language hasn’t even begun to look into anything related to hardening, security, etc., so I find it a bit unfair to criticize the language for something it hasn’t even attempted to provide, currently the language just assumes that you provide your own security, I could imagine that the language eventually gains some features to help with that, but I don’t think it would take an approach where you can be completely negligent about it and have the language do everything for you.

I don’t like this attitude of saying look this language doesn’t do this, look this one neither; so?
And how is that relevant? If you want to make a point than make it. But don’t make it by essentially saying that all languages should basically do everything the same way, otherwise the language is wrong, that is non-sense, languages are useful because they solve things differently.

One thing I like about Zig is that it often doesn’t care about what the popular solution to a problem is and that way it can come up with new, different and in my opinion often better solutions.

1 Like

What?
Are you aware that you only can access declarations that are declared with pub when they are imported from a different file?


I don’t think that imports are necessarily the way to approach security, I think potentially it is a bad way to approach it. I think capability based security (where your code is given something that then allows you to do it) may be a better way.

Overall I would say, unless you are somebody who has vast knowledge about the overlap of security and language design and you want to make a language proposal to add something to make that better, this whole discussion seems to me as if it just isn’t time yet, to have this discussion. First the incremental stuff needs to be done, then when the package build process sandboxing gets implemented, then maybe some of these things become relevant.

2 Likes

Great discussion, I’ve enjoyed reading everyone’s takes. Personally i have been very off put by the idea, as having imports at the top is so ingrained as to seem natural. I’m still not sold on the benefits of moving imports to the bottom, but I’m willing to give it a try at least.

My qualms about it stem from the lack of perceived benefits. Imports at top is an almost universal convention (spanning many programming languages, and communities). The fact that it is popular isn’t an argument for it being good, but it is an argument for it being able to make code “easier” to read, as most people will “expect” to see imports at the top of the file. “readability” is a squishy concept that is often abused. I find it better to talk about readability as a function of the ease of understanding code for a user new to the code. Users new to zig will find imports at the bottom a strange stumbling block. If it becomes convention in zig, then it will not be an issue for users who already understand the convention, but will almost always be an issue for new zig users.

In the end, I don’t see there being any particular benefit to top or bottom, except that for historical reasons top is pretty conventional. I do however think it is useful for imports to always be grouped, as well as top-level declarations, as it provides a well known location for adding and viewing declarations that are scoped to the whole file.

5 Likes

I’m not interested buddy.

That really is the strongest argument for imports at the top.

The strongest argument for imports at the bottom, IMHO, is fields. The “file is a struct” thing is brilliant, but it is itself pretty unusual, and you wouldn’t want to put a bunch of declarations above the fields in a normal struct, right? That would be weird.

It would also be unsatisfactory to put imports at the top, unless the file container has fields, and then put them at the bottom. So that would suggest a consistent policy of bottom imports.

Also worth noting that, while it’s certainly conventional, top imports are a hard requirement in languages where the outer context of a file is evaluated top-to-bottom. So we’re taking something load-bearing and reusing it where it isn’t, because it looks more familiar.

So I’m not about to tuck all my imports at the bottom, but if the compiler and standard library reorganize that way, a) I’d like that because the imports list is never the thing I’m looking for when I open a file in the Zig repo, and b) I’d probably follow suit.

I was not expecting such a long thread to be honest. Thanks a ton for the discussion. IMHO moving them to the bottom, though it’s clearly opinionated, might help with the cognitive overhead. Again - just an opinion.

1 Like

Juat wanted to mention one benefit of using @import directly in functions that need them: it is super easy to move such functions around to other files when you refactor.

For often used things I am ok with @imports at the top or the bottom.

3 Likes

I think this is why I personally prefer imports at the top too and why having the file begin with something else feels “wrong” to me. Because almost every other programming language I’ve used places import/include/using directives at the top (by requirement or convention), I’ve trained myself to consider the first chunk of directives in a file less interesting than the rest, so when I read source code I unconsciously ignore and skip past the first dozen or so lines. I suspect other people also experience something like this, and you could probably draw parallels to the banner blindness phenomenon where people unconsciously ignore banners or sidebar images on websites because they have trained themselves to ignore ads.

3 Likes

I hate to be the party pooper, but this topic has turned into a very long bike shedding.
Put the imports wherever you want.
If you want to see what module a name refers to, just search with grep/crtl+f: “const variable_name”. It’s going to find it wherever it is.
Top imports is going to have minor benefits in some cases, and minor disadvantages in others. Same for bottom imports, same for middle imports, same for imports scoped inside blocks.

4 Likes

The Brainstorming topic could be renamed Bikeshedding without much, if any, loss of specificity.

11 Likes

What’s a brain if not a shed in a different color?

1 Like

I sorta liked the idea of bottom import until @mnemnion brought up the issue of tests. When you do it thoroughly, the space taken up by tests will end up exceeding the space with actual code. The bottom half of the file is really the only sensible place to keep them. That leaves top import as the only option.

4 Likes

there is a secret third option middle import :face_with_open_eyes_and_hand_over_mouth:

8 Likes

When opening a file you are there to lookup for what a module does. Not what it needs. I naturaly switched to Import at bottom.

2 Likes