1. 18
    1. 23

      For the uninitiated: Style insensitivity is a unique feature of the Nim programming language that allows a code base to follow a consistent naming style, even if its dependencies use a different style. It works by comparing identifiers in a case-insensitive way, except for the first character, and ignoring underscores.

      Another advantage of style insensitivity is that identifiers such as itemId, itemID or item_ID can never refer to different things, which prevents certain kinds of bad code. An exception is made for the first letter to allow the common convention of having a value foo of type Foo.

      There’s a common misconception that this feature causes Nim programmers to mix different styles in a single codebase (which, as mentioned, is precisely the opposite of what it does), and it gets brought up every time Nim is mentioned on Lobsters/HackerNews/etc, diverting the discussion from more valuable topics.

      1. 3

        There’s a common misconception that this feature causes Nim programmers to mix different styles in a single codebase (which, as mentioned, is precisely the opposite of what it does)

        But… isn’t it exactly what the feature does? If my coding habits would make me write itemId and a coworker’s code habits would make them write item_id, style insensitivity makes it likely that I would accidentally use a different style than my coworker for the same variable in the same codebase, right? While most languages would make this impossible by making item_id be a different name than itemId, right?

        How is this a misconception?

        To be clear, I’m not saying it’s a huge deal or that it warrants all the attention it’s getting (that’s a different discussion), but since you brought it up…

      2. 3

        Thanks for providing some context. Is this a thing that gets applied by default any time you use any library, or a feature you can specifically invoke at the point during which the library is imported?

        The former seems … real bad. The latter seems … kinda neat? but a bit silly.

        1. 6

          Currently it’s always on, and there’s an opt-in compile flag --styleCheck:error that makes it impossible to use an identifier inconsistently within the same file. The linked issue discusses if and how this behavior should be changed in Nim 2.

          Personally, I wouldn’t mind if it was removed, as long as:

          • --styleCheck:error was on by default
          • there was a mechanism to restyle identifiers when importing a library.
          1. 2

            I agree. People outside the Nim community can add real value to this discussion, since it is just speculation what they really think based on a few loud complainers.

            1. 5

              I’m someone who looked at Nim, really liked it, then saw the “style insensitivity” and thought “this isn’t for me”. (Not co-incidentally, I’ve been involved in a major, CEOs-gettting-involved, fiasco that was ultimately due to SQL case-insensitivity.)

              Nim occupies a nice space - compiled but relatively “high level” - with only really Go as a competitor (zig/rust/c++ all seem a little too low level.) I personally recoil at the idea of “style insensitivity”, but hopefully in a friendly, lobste.rs manner.

              1. 5

                I’ve been involved in a major, CEOs-gettting-involved, fiasco that was ultimately due to SQL case-insensitivity.

                You can’t just say this and leave us hanging 😆 tell us the story! How did that cause a fiasco?

                1. 5

                  Our software wouldn’t start for one customer (a large bank). The problem was unreproducible and had been going on for weeks. The customer was understandably very unhappy.

                  The ultimate cause was a “does the database version match the code” check. The database had a typical version table that looked like:

                  CREATE TABLE DB_STATE (VERSION INT, ...);
                  

                  Which was checked at startup using something like select version from db_state. This was failing for the customer because in Turkish, the upper case of “version” is “VERSİON” (look closely). Case-insensitivity is language-specific and the customer had installed the Turkish version of SQL Server.

                  Some java to demonstrate:

                  public class Turkish {
                    public static void main(String[] args) {
                      System.out.println("version".toUpperCase(java.util.Locale.forLanguageTag("tr")));
                    }
                  }
                  

                  If you look at the java documentation for toUpper, they specifically mention Turkish - others have been bit by this same issue, I’m sure.

                  Which makes me wonder - how does Nim behave if compiled on a machine in Turkey, or Germany.

                  1. 6

                    This is making me wonder if anyone has ever used this as a stack-smashing attack. Find some C code that uppercases the input in place and send a bunch of “ß”s. Did the programmer ensure the buffer is big enough?

                  2. 3

                    I’m pretty sure Nim’s style insensitivity is not locale-specific. That would be very dumb.

              2. 3

                There’s also crystal, but ii is failing to reach critical mass in my opinion.

                I think crystal did a great job providing things people usually want upfront. I want a quick and direct way to make an HTTP request. I want to extract na value from a JSON string with no fuss. I want to expose functionality via CLI or a web interface with minimal effort. Crystal got these right.

                I agree that above-mentioned languages are too low level.

                1. 1

                  Not sure about the others, but I think exposing functionality via CLI is pretty easy in Nim. cligen is not in the Nim stdlib, though.

                  1. 1

                    I was not comparing to Nim directly. Just giving examples of the kind of thing I believe are the strongest drives to success of a language.

                    But for an example of one thing that I found lacking in Nim was concurrency primitives. Crystal makes it relatively simple and direct with fairly simple and familiar fibre API.

                    A quick way to spin up an HTTP service was another one. It even had support for websockets.

              3. 2

                Seems plenty friendly to me. Programmers can get awfully passionate about style guides/identifier conventions.

                I think it tracks individual, personal history a lot - what confusions someone had, what editor/tool support they had for what sort of “what meta-kind of token is this?” questions and so on. In extreme cases it can lead to, e.g. Hungarian notation like moves. It can even be influenced by font choices.

                Vaguely related to case insensitivity, early on, Nim only used '\l' to denote a newline character..Not sure why it was not '\n' from the start, but because lower case “l” (elle) and the numeral “1” often look so similar, '\L' was the dominant suggestion and all special character literals were case insensitive. (Well, one could argue it was just tracking general insensitivity that made them insensitive…).

                1. 2

                  Personally I’d say this compares unfavorably to go, where style arguments are solved by the language shipping a single blessed formatting style.

                  Confusions/disagreements over formatting style are - imo - a waste of the teams engineering time, so I see the go approach as inherently better.

                  1. 2

                    Go doesn’t enforce a style for identifiers. Try it online!

                    1. 3

                      Thanks, I hate it.

                      Fair point to nim though!

        2. 4

          It is always on - even for keywords like f_Or in a loop. I was trying to perhaps help guide the group towards a usage like you articulate.

          EDIT: The main use case cited is always “use a library with an alien convention according to your own convention”. So, being more precise and explicit about this as an import-time construct would seem to be less feather ruffling (IMO).

      3. 3

        Just for the record - the Z shell (Zsh) had style insensitivity for its setopt builtin waaay back in the very early 90s. They did not make the first letter sensitive, though. :-)

        As this seems to be a very divisive issue and part of what is divisive is knowing how those outside the community (who do not love/have not made peace with the feature) feel, it might be helpful if Lobster people could weigh in.

        1. 2

          As this seems to be a very divisive issue and part of what is divisive is knowing how those outside the community (who do not love/have not made peace with the feature) feel, it might be helpful if Lobster people could weigh in.

          I looked into Nim and was at least partially dissuaded by style insensitivity. I don’t think it’s fatal persay, but it did hit me very early in my evaluation. I would liken it to the dot calls in Elixir: Something that feels wrong and makes you question other decisions in the language. That said, Elixir is a fabulous language and I powered through. I imagine others feel similarly.

          1. 2

            What specifically do you not like about style insensitivity?

            1. 1

              Here’s the thing: I haven’t used style insensitivity so I can’t really say I dislike it. However, it struck me as unnecessarily inconsistent. I don’t care about snake case or camel case. I just want code to be consistent. Of course, code I write can be consistent with style insensitivity, but code I read probably won’t be.

              Additionally, I imagined that working in a team could have issues: repos use the original author’s preferred styling. Of course, having a clear style guide helps, but in small teams sometimes people are intractable and resistant to change. In a way, it triggers a feeling of exasperation: a memory of all the stupid little arguments you have with other developers.

              So here I am kicking the tires on a new exciting language and I am already thinking about arguing with people. Kind of takes the wind out of your sails. It may be a great feature, but I imagine it’s a barrier to adoption for some neurotic types like myself. (Maybe that’s a blessing?)

              1. 1

                You have it the other way around. With style insensitivity, code is much more likely to follow a consistent style — because it can’t be forced into inconsistency by using libraries from different authors.

                1. 1

                  I can see how code I write is consistent, but code I read is going to be more inconsistent. If it wasn’t then why would we need style insensitivity in the first place?

                  1. 1

                    I can see how code I write is consistent, but code I read is going to be more inconsistent.

                    Can you show me a serious Nim project that uses an inconsistent style?

                    If it wasn’t then why would we need style insensitivity in the first place?

                    Because libraries you’re using may be written in different styles.

                    1. 1

                      I’m saying it’s inconsistent across projects. Not within projects. Sometimes you have to read other people’s code. Style insensitivity allows/encourages people to pick the nondefault style.

                      Ultimately, I’m not in the nim ecosystem. I posted my comment about why style insensitivity made me less interested in nim. I can tell you that this is the exact sort of argument I was looking to avoid so you have proven my initial concerns correct.

                      1. 1

                        I don’t see what the problem is with reading code written in a different style, as long as it’s consistent. And in practice, most Nim projects follow NEP1.

      4. 2

        Doesn’t JRuby have something similar around Java native methods?

        1. 2

          I think it’s an interesting comparison, but it’s important to keep in mind that a language based around message passing is fundamentally different from what’s going on here where the compiler itself is collapsing a bunch of different identifiers during compile-time. When you call a method in Ruby, you’re not really supposed to care how it’s resolved, but when you make a call in a language like Nim, you expect it to be resolved at compile-time.

          1. 3

            I’d disagree there. The mechanism in JRuby is that the method is made available under multiple names to the application after it’s loaded. That’s not extremely different from what Nim does, except if we go down to the level to say we can’t compare languages with different runtime and module loading models.

            https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby

            1. 2

              I guess what I meant was that even if the implementation works the same way, Rubyists fundamentally have different expectations around what happens when you call foo.bar(); they’ve already given up on greppability for other reasons.

    2. 16

      This feature renders text search tools ambiguous. You can no longer count occurrences of a symbol with a search tool. Nor use it to jump to the next or previous occurrence in a file. This criticism has been met with “you can use our custom made search tool instead of grep”.

      That someone stands by such statement believing it is a good alternative, boggles my mind. Breaking the tools that are the bread and butter of millions of programmers for the gain of allowing style consistence when importing third party libraries.

      No one ever refrained from using a library because of symbol styles. Style is ultimately an irrelevant detail. It har lower precedence than any other criteria.

      This also signals insistence on initial choices for little reason beyond being stuck in an idea. Outsiders are described as misunderstanding a feature. Dude, you guys broke friggin grep… Have just a tiny bit self awareness.

      1. 4

        You can no longer count occurrences of a symbol with a search tool. Nor use it to jump to the next or previous occurrence in a file.

        You can, as long as you use a consistent style within your code, which you should.

        No one ever refrained from using a library because of symbol styles.

        I have personally refrained from using Python’s unittest module because it violates PEP8. Style insensitivity could’ve prevented that.

        Outsiders are described as misunderstanding a feature.

        Because they criticize it without even checking whether it’s a problem in practice (which it isn’t).

        1. 5

          You can, as long as you use a consistent style within your code, which you should.

          No. You can as long as you do that and if you search only in your code. Which noone does. Personally, searches in code I wrote account for a 1-5% of the code searches I make, if not less.

          I see things are quickly going down the path of claiming that it was never intended to be used within a code base. You’re not very far from getting to the point of not using it at all.

          Because they criticize it without even checking whether it’s a problem in practice (which it isn’t).

          It is already a problem for anyone inspecting code using text search. I read the source of code I import and resource to grep and the like extensively. That feature breaks the unambiguity of an exact match search. Thus, as soon as I make a search, I know that I cannot be sure that I am catching all the references. Which renders my search pointless. It is a real problem in practice.

          1. 3

            I see things are quickly going down the path of claiming that it was never intended to be used within a code base. You’re not very far from getting to the point of not using it at all.

            It is, indeed, not intended to be used within a single codebase, as I explained in my top-level comment. The entire point is to avoid having to use multiple different naming styles.

            I see things are quickly going down the path of claiming that it was never intended to be used within a code base. You’re not very far from getting to the point of not using it at all.

            Just take a second to look what naming style the project is using (which is camelCase for like 99% of Nim projects), then you know exactly what to search for.

            1. 2

              Then what you would want is an easy way to map symbol names at the top of the code somehow, then use them thoughout their entire scope and remove the ambiguous symbol equivalence.

              Achieving that by such hacky symbol namming rules is a very bad idea at best.

              Just take a second to look what naming style

              What for if it doesn’t give me any guarantees anyway? How can I be sure the author didn’t change the style somewhere in the source? I can’t.

              The use case you describe is valid. It’s just the solution that is a huge mismatch.

            2. 2

              Just take a second to look what naming style the project is using (which is camelCase for like 99% of Nim projects), then you know exactly what to search for

              Projects include libraries which code I want to inspect. Furthermore what you suggest relies on making assumptions on the code which I cannot verify. How do you know that one styles is followed accross all code? You have to read the whole code.

    3. 12

      It’s a bikeshed trap.

    4. 6

      I’ve probably spent a few hundred hours coding in Nim, although not for a year or so. I barely recall even noticing style insensitivity. I might have had one or two brief instances of confusion looking at code where a method was spelled differently than usual. I do remember having some issues with C bindings where Nim either didn’t like a C function ending in underscore, or collapsed two C symbols into one.

      I do like the idea of being insulated from other library developers’ unfortunate use of snake_case, but it’s not worth the other headaches it causes, especially if it’s something that repels people from trying Nim.

    5. 4

      A lot of the comments upstream are conflating “preventing two similar identifiers with different names” and “resolving two similar identifiers to the same keyword/variable/type,” which is unfortunate. Most of the pro-insensitivity comments boil down to “it keeps me from making mistakes by having two variables/properties/whatever with similar but not identical names and getting confused” (is that really such a problem?) but that benefit can be easily kept without also forcibly coalescing all similar identifiers.

      1. 3

        that benefit can be easily kept without also forcibly coalescing all similar identifiers

        And? In what situation could you possibly want fooBar and foo_bar to be different things?

        1. 9

          Not arguing for either side here, but your question made me think of words like in_box, is_land, turn_table, high_light, or take_out.

        2. 4

          To expand on the point @mqudsi seems to be making and @jibsen’s interesting examples, I think there are just many kinds of identifier. How much fooBar and fOO_BAR “look the same” is subjective. It depends upon fonts (how big ‘_’ looks). How much to leverage looking different to denote kind is also subjective. One does not always have an IDE on hand when interpreting code. How often that happens is also subjective. Even with an IDE, redundant visual cues can often lessen confusion - how much so, also subjective. What kinds confuse the most is also subjective.

          Type is one important aspect. FORTRAN’s old starts with “[I-N] => integer type” is the original Hungarian notation alluded to earlier. There are many aspects, though, and Nim has maybe more than most (at least packages, modules, const, let, var, func, proc, iterator, generics, template, macros). Is global search/replace change of such a redundant cue a pain? It can be. Is the trade off worth it? Also hard to know.

          Nim itself recommends leading capitals for type names. LOUD_CASE for constants is all over the stdlib. Caps used to be like radio operator alphabets. Low-res devices did not select LOUD_CASE randomly. It was viewed by many as CLEAR_CASE. (I’d agree it might be “clarity wasted on constant-hood” whose origins may be tied to the hackiness of the C preprocessor.) Probably before it had good IDE tools, Nim used to put a ‘T’ prefix in front of type names and a ‘P’ in front of pointers.

          In the Ada case, it was viewed as not possible to render lowercase on some US DoD devices. So, HW limits took away case sensitivity as a choice. Many I know think of case insensitivity, even that of CP/M|DOS heir Windows file systems, as a throw back to ancient technology. There is usually a just so story to support the choice in the modern age when the “real” reason may simply be backward compatibility to the 1970s.

          Various studies try to assess all this subjective stuff in the population. Besides being very sensitive to subpopulations studied, I think most confuse “interactive” with “more static reading” contexts (in both file names and in programming). Most text is read much more than it is written which is at least partly why TAB-completion is popular.

          In short, I don’t think the “it all depends”/subjectivity should be very contentious yet it often is in Nim conversations. This is partly what leads me to think of the Nim community as a biased pool of evaluators and why I tried to include a broader community like Lobste.rs. Implementing an “import time” feature with something that spills over to wh_Ile also seems bad.

        3. 2

          There have been times I’ve been in a code base and seen that 1 naming convention was used for 1 set of objects (records from the database or unprocessed data) and a second convention was for another set of data that was conceptually related.

          It maybe wasn’t the best code, but it at least worked and made sense.

        4. 2

          I wasn’t clear/you misunderstood. I was saying you could pick one and be forbidden from using the other without allowing both and coalescing them. That would prohibit confusing names but force stylistic continuity, enable codebase grepping, etc.

          1. 2

            You can forbid underscores in identifiers, which disables snake_case (I actually suggested that in the linked issue and got a lot of downthumbs). However, it won’t solve the situation of itemid versus itemId versus itemID, and I’m pretty sure distinguishing these is an AI-complete problem.

        5. 1

          The linked thread highlights some cases with difficulties wrapping C libraries which have unavoidable collisions when following upstream naming.

          1. 3

            Okay. I prefer to rename wrapped identifiers anyway.

    6. 4

      I don’t have much else to offer but to say that this would be an amazing change for Nim. Superficial or not, case insensitivity is a horrible feature just about everywhere it’s applied. It’s so bad that I don’t think they should just make it optional, they should burn it with fire. Nuke it from the orbit. (And provide a tool for automatically upgrading existing projects).

      1. 4

        do you think you could provide a reasoned argument?

    7. 3

      From outside the community (love the language, have written very little, just playing):

      1. It bugs me, various reasons, doesn’t matter why really
      2. Love the language. Wouldn’t stop me from using. I would get used to it, maybe even like it, because it would let me name things how I want to
      3. Other people hate it “…but because it is one of the main reasons that people do not even try Nim.” – dom96
      4. Counter to the freedom gained in 1., set official style(s) from above, this has been very well received (see go fmt and other formatters since), if it is the way, people accept it and don’t argue.

      Sadly, names probably cannot be well auto formatted.

      So, yes, get rid of it (see 2).

      But give strong guidance on the correct style so people won’t argue about it.

      edit: sorry meant to refer to 2 (not 3) as reason to get rid of it.

      1. 2

        Thanks. This is helpful feedback. Another issue is that it means one must use things like nimgrep and other Nim-specific tooling “to be certain”. (EDIT: and of course, any more precise/explicit ident-style translating suggestion might also possess that same property…)

      2. 2

        Sadly, names probably cannot be well auto formatted.

        It’s pretty easy to automatically prevent snake_case and SCREAMING_CASE.

    8. 3

      It looks like the Nim community is asking the opinion of random stranger, so here is one: I don’t see any problem with style insensitivity, it’s an uncommon feature but it seems fine if specified clearly. I’ve seen occasional issues caused by the “lack of style insensitivity” in my language, OCaml, for interoperability reasons: you automatically generate APIs from a Javascript/Typescript spec (or the other way around, provide an API for JS users implemented in OCaml), and there is a mismatch of naming conventions that can be occasionally an issue for people that want to offer a “native” experience on both sides.

      (OCaml has a dialect that people wrote to feel like JS, and it uses a different style convention from normal OCaml, but people want to write agnostic libraries that can be used in either frontends, and then this is also an issue, to the point that people have suggested – but we never took action – things like case insensitivity in the past.)