6 ms·
One thing I just can't understand is proactively using the :: syntax. It's sooo ugly with so much unnecessary line noise. Just use a single period! I think one
by sfpotter 2y ago
One thing I just can't understand is proactively using the :: syntax. It's sooo ugly with so much unnecessary line noise. Just use a single period! I think one of the best decisions D made was to get of -> and :: and just use . for everything.
- 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.
- foul 2y agoI can understand it, I just hate it. I would prefer confusing dots, a module builtin namespace, rebol backslashes, confusing slashes, anything else.
- melon_tusk 2y agoI can live with "this::that", but what drives me bonkers is "this :: that", which is what Odin does. Other than that, Odin is an incredible language.
- deagle50 2y agothat's a constant assignment, completely different. And you're not going to see it 100s of times in a project.
- Asooka 2y agoI like it. It disambiguates when you're referring to a member of an object -- myobj.member vs referring to a global object by its full name -- module::function. I guess you could say the IDE can colour the two differently, but after spending a lot of time working with various code review tools of varying quality, I have come to really appreciate having the program text be as explicit as possible. If you find it so disagreeable, can't you configure your IDE to visually replace that syntax with a single dot and also automatically convert a single dot to two colons when typing a namespace?
- mort96 2y agoI like to quickly at a glance be able to distinguish between "this is a member access on an object" and "this is referencing something in a module". I like that the compiler can distinguish those two things too, so that I can refer to things within modules even if I happen to also have a local variable with the same name. Go sometimes annoys me because I need to rename a module or a variable just because the syntax doesn't distinguish between the two things.
- throwawaymaths 2y ago> distinguish between "this is a member access on an object" and "this is referencing something in a module". zig: what's the difference?
- mort96 2y agoSurely Zig differentiates between, say, a function in a module, and a member on an object? Or are "modules" literally just instances of classes or something?
- lerno 2y agoNo, they are the same.
- throwawaymaths 2y agoall structs are namespaces (there no classes). namespaces may contain declarations (consts and functions) or fields ("fields" are slightly different for unions or certain builtins like arrays and slices) unions and enums also create namespaces. any @import creates a namespace that is a struct. If a function's first argument is the type of the function's namespace or a pointer to the type of the namespace, you may (and by convention are encouraged to) use dot dereferencing (like python firso parameter self) as a lexical sugar to call the function with the "implicitly rearranged" first parameter ("oop style caling, but not really oop") modules are somewhat different, in zig these are collections of code you can map to a non-filepath import string using the command line or build tool (in particular you may map something out of code root path), but these too ultimately become a namespace struct
- inkyoto 2y agoI concur RE: «::». For deep levels of nesting, the level of noise that «::» causes becomes excessive. When Rust was in its infancy, I maintained a local fork for a while where I modified the parser to use the Ada syntax («'», a single apostrophe) for the same purpose. So std::collections::hash_map::HashMap::entry became std'collections'hash_map'HashMap'entry But I am not convinced that using «.» for two distinct purposes – 1) as a name qualifier, and 2) as a method/data element accessor – is a good idea, for maintaining the semantic clarity is important, i.e. is «e» in «a.b.c.d.e» 1) A method call; or 2) An accessor for a deeply nested data structure. It is not easy to say whilst just glancing upon the code.