| |
| Posted by Jonathan M Davis in reply to Salih Dincer | PermalinkReply |
|
Jonathan M Davis
Posted in reply to Salih Dincer
| On Wednesday, October 11, 2023 5:34:50 AM MDT Salih Dincer via Digitalmars-d wrote:
> On Wednesday, 11 October 2023 at 05:31:33 UTC, Jonathan M Davis
>
> wrote:
> > The problem is not using the imports inside of the struct where you have the public import (since whether imports are public or not has no impact on the part of the code where they're imported, just on other modules importing that code). The problem is using them on the struct from within another module.
>
> I see! In this situation there are 2+1 (the first one doesn't count) solutions if I do not remember wrong:
>
> The first thing is not to use "public:" but still be careful. Because the imports may accidentally be in scope, as you mentioned.
>
> Other is "Renamed Imports", a local name for an import can be given. For example:
>
> ```d
> public:
>
> import std.range.primitives : wl = walkLength;
> ```
I wouldn't advise that, since I'm pretty sure that that results in having wl as a public member of the type that it's in (or of the module that it's in if you do it at at the module-level), and you presumably don't want to be creating any extra public symbols like that. In general, simply making sure that the import is before public: solves the issue without having to jump through any hoops - or using public as an attribute rather than as a label also solves the problem.
> Finally, use selective import again and define it inside the member function. For example:
>
> ```d
> public:
>
> size_t length() {
> import std.range.primitives : walkLength;
> return this.walkLength;
> }
> ```
In general, it's advised to scope imports as tightly as possible to avoid what they impact (as well as to make it clearer where they're used so that you know where symbols come from and when you can remove the imports when refactoring), but you do sometimes need them outside of functions (e.g. for the return types), so while local imports help, they don't always solve the problem.
Personally, I ran into this issue, because I just wanted to have the necessary import to get the range primitives for arrays without having to worry about where within the member functions I was using them, and it would have been fine if I'd put the import before the public:, but I didn't, so I ran into issues.
> Thank you very much for this information. There is a huge difference between "import" alone and "public import"!
>
> SDB@79
Ultimately, what it comes down to is that if you use public:, you need to be careful where you place imports in relation to it. You don't want to be creating public imports by accident (and almost never want to create them on purpose; package.d is the primary counter-example). Of course, you can choose to just avoid public: to avoid the problem (in which case, presumably you just use public as an attribute directly on the symbols), but the point is that if you do use public:, you need to be careful where you put it. And it's easy to forget that it impacts imports, since most of us don't do much with public imports.
- Jonathan M Davis
|