If you enforce a code style or, if you don't but you would convene that someFunction and some_function should mean the same thing in your codebase. Then nim's approach should be transparent to you.
So don't bring up nimgrep like it's a necessity when it's more of a last resort tool nowadays. You will be just attracting flaming.
Such a mistakes is easy for a linter to pick up on so that the code would never be merged in the first place.
> It's so external dependencies don't have to infect your codebase. So you can actually apply a consistent code style within your project.
Say an external dependency has a declaration called 'getFileSystem', and in my Nim codebase I refer to it as 'get_file_system', but last year someone accidentally committed 'get_filesystem'. In this case neither usage matches the declaration. Does the linter flag both spellings because they don't match 'getFileSystem'?
EDIT: And what about reflection? If someone wrote `newCall("get_filesystem")`, will the linter fix that too?
I suspect, in practice, almost everyone follows the sane approach of enforcing a code style in your codebase. I think what usually gets lost when this is brought up is that the point of this code style insensitivity is not to encourage you go to crazy and mix and match it in your projects. It's so external dependencies don't have to infect your codebase. So you can actually apply a consistent code style within your project.
test.nim(2, 8) Hint: 'myvar' should be: 'myVar' [var declared in test.nim(1, 7)] [Name]
edit --styleCheck:error perhaps?
- hand tvättas (wash your hands) != handtvättas (wash by hand)
- sjuk gymnast (sick gymnast) != sjukgymnast (physical therapist)
- sjuk sköterska (sick nurse) != sjuksköterska (hospital nurse)
- lång hårig (tall and hairy) != långhårig (long-haired)
- sjö nära tomt (lake near a house) != sjönära tomt (house near a lake)
Here's one illustration: https://github.com/nim-lang/RFCs/issues/456#issuecomment-111...
We have partial case-insensitivity in PHP. Can't say I'm very fond of it, but I'm ambivalent as long as it's not abused.
And "C names are usually very cryptic" is plain false, unless you talk about APIs coming from the ages and compilers where all identifiers had to be 8 characters or fewer in length.
This is literally idiomatic Python style! Classes are TitleCase and everything else is snake_case.
I have also used a mix of camelCase and snake_case for different purposes, eg in Haskell where conventions are mixed (and I am far from an expert), I've written names like "fooBar_prev"
And Nim does distinguish between those.
> I've written names like "fooBar_prev"
That's disgusting.
Also, John Carmack: https://mobile.twitter.com/id_aa_carmack/status/159256093820...
E.g. The Python Selenium library used to be in CamelCase, while almost all code in Python is snake_case. By using Selenium you ended up with code like:
my_button = browser.getElementById("Button")
They rewrote the whole library to be in snake_case, a change that forced a lot of code rewrite downstream. Even the Python builtin library has case inconsistencies (logging module is camelCase, sys has both alllowercase and snake_case) that weren't fixed even in 2to3.Nim would have handle this efortlessly, allowing you to use get_element_by_id or getElementById in the old library, and avoiding you the effort to rewrite your code if the Selenium mantainers decided for a case change. You can refactor your case without fear of making life worse for your users.
The downside is that for each library you want to do this to, _once_ you have to spend a few minutes writing the renamings.
The upside is that if you now want to find everything that uses the external function getElementById, you can search for _that_, and you will find the "rename getElementById as get_element_by_id"[1] declaration, and then you know to search your project for get_element_by_id to find all the places where it's used.
[1] I am not suggesting that particular syntax; I just picked something at random.
The other upside is that if you want to find uses of the getFoobar function that's defined in your project, you just have to search for getFoobar rather than doing a case-insensitive regex search for "_*g_*e_*t_*f_*o_*o_*b_*a_*r_*". (Or, if your answer to that is to use language-specific tooling, that you aren't forced to use language-specific tooling when it might be more convenient to do searches on the GitHub website, or in the text editor / IDE that everyone else on your team uses, or in the text editor / IDE that you'd been using for years before starting to use Nim.)
To me, this seems like an obviously better design. I don't want people who have spent years becoming productive in Emacs, or Vim, or Visual Studio, or whatever, to have to choose between using some different set of tools they aren't used to and having the searching operations they're used to using silently do the wrong thing.
Am I missing something? Because, rightly or wrongly, this one weird design decision is enough to keep Nim off my list of languages that are worth the time to investigate: not because this single thing makes that much difference on its own (though it does feel as if it would make my life substantially worse, if I were writing a lot of code in Nim) but because I feel like the language is designed by someone who makes weirdly terrible design decisions sometimes, and if that's what I want then I already have C++ and Javascript :-).
Are you seriously expecting that someone will put an underscore in the middle of a word?
I don't have a plausible example of #2 in mind. Maybe there aren't any. (There are definitely lots of things that break into words in multiple ways, of course, but maybe there aren't any that make plausible identifier names more than one way. Though for what it's worth I bet there are.) And in any given case you can check, given a few seconds' thought, that there aren't other possibilities. But that little extra cognitive load is a bigger deal than it sounds like -- it's a distraction from other things -- and if you don't do the check then you'll never know whether your search operation actually found everything it should have.
So you can check by eye every time. Or you can write the ugly regexp every time. Or you can just accept that what ought to be a perfectly simple operation isn't quite right and might invisibly go wrong some time.
That's not a set of options I like.
As far as renaming external libraries goes, if the original name is get_foobar, and the project uses snakeCase, I would be very surprised if it's renamed to anything other than getFoobar. There are slightly more tricky stuff like get_ID, but even then there are only a couple of reasonable forms to search for. And it's rare to be searching for things you haven't seen used, and if you saw it used you know how it's spelled in that library.
I've been programming for years in Nim and never had any problem grepping or searching for things because the style insensitivity.
I don't think it's reasonable to force every developer to spend a few minutes writing renamings if virtually all of them are obvious mechanical transformations, just because a paranoia not substantiated by experience.
Third party Nim libraries? Because if the all used the same style this would never be needed in the first place.
Rust never has this issue because everyone uses the same style.
If I'm looking for some example code that uses my_testfunction(), I can't just search for "my_testfunction nim". Instead I have to add MyTestFunction, my_test_function, MYTESTFUNCTION, etc. The case-insensitivity isn't really a big deal, but the underscore-insensitivity is.
If I'm honest, I think this is a big problem for adoption of the language. It's incompatible with a lot of search-engines, and weird to anybody coming from any other programming language. Nim should take advantage of the 2.0 release to do a compatibility break in this area, maybe with a compiler flag to enable the legacy behavior.
Can confirm, it single-handedly kept me away from the language.
> Nim should take advantage of the 2.0 release to do a compatibility break in this area, maybe with a compiler flag to enable the legacy behavior.
No thanks, I don't want inconsistent naming conventions in my code.
Style insensitivity lets you automate your local code (and/or through CI) to consistency for easy searching, even when external libraries YOLO their own style.
> It's incompatible with a lot of search-engines
Google and search engines are case insensitive, and mostly ignore underscores too. Let's be honest, how often would you just search for 'testfunction libraryname' on the web and get the signature you need?
My experience from using the language in production for years is that case insensitive searches will find what I want in Nim code specifically because no one can use case/underscores to make things make unique. Instead, the language uses overloading through the type system to distinguish things. This is a far more succinct, safe, and expressive way of writing code from my perspective.
It's worth noting that the first letter of an identifier is case sensitive, with the convention for types to start with a capital letter. So, you can write 'type Test = object' and 'proc test(t: Test)', then use them with 'var test: Test; test(test)' without any ambiguity, and with code completion/jump to source in VSCode (and others).
If you then add 'proc test()' with no arguments, it's still unambiguous because the functions have different signatures, so you can then write 'test()' and your second function is called.
If something is ambiguous, it's a compile time error. If you want, you can prefix modules like Python, but there's never any need. If you have two libraries with the API, same types, and function signatures (such as using two async libraries in the same program), you can just slap a generic '[T]' so it's lazily instantiated at the call site and move on.
IMHO relying on casing/underscore to distinguish identifiers is objectively worse than using the type system to statically and unambiguously prove your intent, and normalising names removes a class of identifier confusion bugs to boot. Even style guides in case sensitive languages beg us not to use case and underscores to disambiguate symbols for the confusing code it creates, and to be honest, I've yet to see a compelling argument in favour of case sensitivity beyond simply being what people are used to.
I see it as a mandated style checker built into the language.
The issues are:
1. Difficult to search code. Even just case insensitivity makes this worse because often you do have names that only differ in case (but in an acceptable way, e.g. they're different kinds of thing, or namespaces). But ignoring underscores makes it much much harder - now every search needs to be a regex.
You can say "use an IDE!" and you absolutely should but you still sometimes need to search with dumb grep style tools.
2. Case insensitive rules are always more complex and difficult to remember. Where do they apply? All identifiers or just variables? What about keywords. Nim's rule is especially complex. It adds cognitive load.
3. Extra bike shedding. I imagine they added it to avoid bike shedding? But it will have the opposite effect. They should have just made a language wide convention like Rust. Nobody debates case style in Rust or indentation style in Go because the tooling and community pretty much force one style.
I fully anticipate a Nim linter that bans style variation from the canonical one. If that doesn't exist already.
I don't know about Rust, but Python has a language-wide convention – and programs still violate it, including the standard library.
import logging
import sys
sys.breakpointhook()
sys.exc_info()
logging.getLogger(__name__)
And both `sys` and `logging` are not obscure builtins, they are used everywhere. And just for that, case is not fixable.2 - Negligible cognitive load in my experience. You can just ignore that part of the language and treat it as case sensitive and everything will work. Inside projects it's effectively case sensitive too. And the rules just make sense, they are just there to allow you to be consistent in your casing, nothing less nothing more. It applies everywhere they are need for that, and nowhere else.
3. Gofmt wasn't a thing when Nim(rod) started and now is too late to force all projects to a single style. But projects are internally consistent, and you can always use your preferred style, so I consider Nim's a superior solution.
> I fully anticipate a Nim linter that bans style variation from the canonical one. If that doesn't exist already.
The compiler already warns you by default if you are not consistent on the spelling of identifiers inside your code, and you can make that an error too. See `--styleCheck:usages` and `--styleCheck:off|hint|error`. There is a nim linter that can make your code conform to NEP-1, but last time I saw it was a bit too buggy in that style transformation, so people don't usually use it.
I've been programming for years in Nim and never had any problem grepping or searching for things because the style insensitivity. In pratice it's a non-problem.
I think I remember reading early remarks from the Nim team that you can opt-in to the symbol sensitivity but it's a marker comment per-file, or some kind of DIY preprocessor which does the same. I'd be happy if it was a CLI switch.
All that said, and in practice, clearly a lot of people are fine with this and even like it. I'd much rather Nim exist with this (IMO) oddity than not at all.
Nim developers are as smart as any other, and they like and write clean codebases adhering to the convention in NEP1. The ability to mix cases is used to fix libraries without having to disrupt their users.
I've seen this kind of complains over and over: a new language emerges (e.g. Python 20-30 years ago), and what people finds the absolute showstopper is the indents instead or braces, a minimal part of the language that should not bother a competent programmer at all. The same people that were writting old PHP or old Perl, go figure, complainig that Python whitespace is ugly.