5 ms·
`::` simplifies the module vs identifier resolution. In C3 there is something called "path shortening", allowing you to use `foo::bar()` in place of something
by lerno 2y ago
`::` simplifies the module vs identifier resolution.
In C3 there is something called "path shortening", allowing you to use `foo::bar()` in place of something like `std::baz::foo::bar()`. To do something similar with `.` is problematic, because you don't know where the path ends. Is `foo.baz.bar()` referring to `foo::baz::bar()` or `foo::baz.bar()` or `foo.baz.bar()`?
- WhitneyLand 2y agoSure, but in practice I believe most developers would find it intuitive to just type . everywhere. It feels more lightweight and consistent, and collisions aren’t super common once you adopt some conventions. It’s a tradeoff for sure, but this preference comes from having lived in both worlds.
- PartiallyTyped 2y agoN=1; I find :: a lot more obvious.
- steveklabnik 2y agoI’ve lived in both and I prefer ::.
- gpderetta 2y agoI prefer a world where there is no distinction between modules (or namespaces) and object, so '.' it is. (and I'm almost exclusively a C++ programmer).
- lelanthran 2y ago> Sure, but in practice I believe most developers would find it intuitive to just type . everywhere. Yeah, but in practice I try not to produce write-only code. Code is for reading more than for writing, hence make it easier to read. If it becomes easier to write as a side-effect, then so be it.
- IshKebab 2y agoI would just explicit require pulling `foo` into scope, like Rust does. Though in fairness Rust also uses :: for scope anyway and I don't think it's as bad as sfpotter says.
- WalterBright 2y ago> `::` simplifies the module vs identifier resolution The identifier on the right is looked up in the scope of the identifier on the left. If it resolves to a module, then it's a module. If it resolves to a function, then it's a function. If the left side is a pointer (not a symbol with a scope) then the right side resolves to a member. It also makes refactoring much easier - changing a pointer to a reference does not require a global search/replace of -> with .
- lerno 2y agoC3 has "path shortening", so for example given `open(...)` in std::io::file is usually used as `file::open(...)`. If we would to write this as `file.open(...)`. Consider now the case of mistyping `open`: `file.openn(...)`. Is this (A) mistyping the function open in module `std::io::file` or is it (B) the global/local `file` is missing from the current scope? Also, "io", "file", "random" etc are commonly used variables, so the issue with shadowing is real. `File file = file::open(...)` is completely unambiguous and fine. `File file = file.open(...)` on the other hand would be bad. If the language had flat modules, or no path shortening, then it would be possible.
- WalterBright 2y ago> Is this (A) mistyping the function open in module `std::io::file` or is it (B) the global/local `file` is missing from the current scope? D uses a spell checker for undefined identifiers, and the dictionary is all the identifiers in scope. It has about a 50% success rate in guessing which identifier was meant, which is quite good. > Also, "io", "file", "random" etc are commonly used variables, so the issue with shadowing is real. If the same identifier is accessible through multiple lookup paths, an error is issued. If a local variable shadows a variable in an outer scope, and error is issued. We've developed this over several years, and it works quite well. Path shortening can be done with: alias open = file.open; or: import io: open;
- lerno 2y agoIf I would have liked, I could have done something like `import std::io::file as file;` but I noticed that we keep getting this issue that we’re renaming things all of the time, and usually in the same way. This is why path shortening is there. To directly get something like the informal `file_open` namespacing in C programs.
- sfpotter 2y agoThis is the kind of thing I don't want to have to think about as a programmer. The compiler should just make it work.
- lerno 2y agoBut you have to. Ambiguities hint at lack of redundancies that also affects code reading. When you quickly scan something like `file.open` vs `file::open` the former is also more unclear to a reader without more context.