[0] https://en.wikipedia.org/wiki/Off-side_rule , [1] https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax , [2] http://nim-lang.org/docs/manual.html#procedures-method-call-...
Choice #2, Uniform Function Call Syntax (UFCS), allows you to write `a.someFunc(b)` or `someFunc(a, b)` interchangeably.
Choice #3 is case-insensitivity for identifiers: You can write `a.to_lower()`, `a.toLower()` or `a.tolower()` interchangeably.
Choice #4 is the ability to drop empty parens from the end of a function call: `a.len()` can be written as `a.len`. Combined with UFCS, this allows you to write `len(a)`, `a.len()` or `a.len` interchangeably.
I'd already been programming Python for years, so I wasn't surprised by choice #1 -- in fact, I was pleased. After initially being highly skeptical of Python's OSR syntax when I first encountered it, I've since come around completely. The most common complaint against Python's OSR syntax is that it allows both tabs & spaces, interchangeably, which has bitten just about everyone who has ever used Python in a team. Nim avoids this problem by allowing only spaces to be used for indentation, not tabs: http://nim-lang.org/docs/manual.html#lexical-analysis-indent...
My eyebrows certainly went up about #2, #3 and #4 when I first encountered them. But you know what? Much like Python's OSR syntax, I've now come around completely. Now I actually prefer #2, #3 and #4 the way Nim does them. When I'm back in Python, C++ or C, I wish they behaved the same way as Nim!
Think about it: How many stylistic debates have there been about whether an operation in C++ should be a function or a method? How many times have you pondered whether an object attribute should be a member or a method? It's just a distracting detail with no benefit. And now you don't need to care! Apparently Bjarne Stroustrup is a convert to UFCS too: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n417...
Nim is, above all, a pragmatic language. I think that in another 5 or so years, Nim's syntax choices #2, #3 and #4 will seem just as sensible as #1 seems to Python programmers today.
Most of those things are either totally accepted in the PL community (like "Uniform Function Call Syntax") or common and matter of taste, but nothing bad in themselves ("block indentation, paren-less function calls").
Case-insensitivity for identifiers WITH the underscore thing, though, is just plain bad, error prone, hampers auto-completion and IDE intelligence, and is plainly bat-shit crazy. Not to mention opening the stage for tons of bike shedding and holy style wars...
While there were languages with case-insensitivity in the past (especially pre-80s) nobody thinks that it was such a great idea in the first place, and pretty much everybody rejoiced when such features were abandoned.
People react with these strong responses ("plainly bat-shit crazy"). People focus on inconveniences due to the limitations of limited tools ("I don't want to press spacebar FOUR TIMES at the start of EVERY line of code!"). People come up with elaborate worst-case hypotheticals ("What if you want to share your code with someone using a pastebin service that removes leading whitespace?") that just don't happen in practice.
In practice, it's just all upside and no downside. Now I don't need to remember whether it's `openHTTPConnection()`, `openHTTPconnection()`, `open_http_connection()`, `openHttpConnection()`, etc. If I can say it, I know how to type it.
Any ambiguous overloads (same name, same parameter types -- which again, really doesn't occur by accident in practice) will be reported & resolved at compile-time. There's no more mystery in this than there is in any function overloading scenario.
And in practice, it seems to cause the opposite of holy wars: People realize how pointless all those identifier case-wars are in the first place.
There's really not much more that I can say. "In my experience, there's no downside to this feature, only upside."
Interesting idea.
The topic of function call syntax reminded me of something:
I'm not a language creator, but years ago, when I was fairly new to programming, I had this idea that it would be cool and maybe useful for a language to have function call syntax something like this, to more closely resemble English sentences:
hit_the_(ball)_with_the_(bat)
or just:
hit_(ball)_with_(bat)
where ball and bat are arguments. (Not too good an example, I know, because in a cricket or baseball game, the ball and bat would not vary at all, or not vary often, unlike arguments tend to do, on different calls. But I think people will get the idea.) IOW, instead of having all the arguments grouped together inside one set of parentheses, make it more like an imperative English sentence, by having multiple parentheses, one per argument, separated (if needed) by other words (which are part of the function name).
The above example would be for a language where types of function arguments are not specified. For a language where they are, it could be like this:
hit_(ball: Ball)_with_(bat: Bat)
Of course, I've left out the syntax for something like "def" (as in Python) to say that this is a function definition and for the return value/type, if any.
Don't know what the complexity of implementing something like that would be.
[hit: ball with: bat]
The method is called 'hit:with:'.
Thought they don't go overboard with the "like english" thing, they mostly use the extra keys for disambiguating arguments. E.g.:
[fileWrapper writeToFile: path atomically: YES updateFilenames: YES];
As for #3, I kinda see the motivation in statically typed languages for integrating independent libraries and frameworks with different naming conventions. In a dynamically typed language though refactoring is already bad enough, this would make it even harder. My "refactoring tool" of choice is grep (or rather ag, https://github.com/ggreer/the_silver_searcher), with choice #3 you can't just grep for an identifier anymore.
[0] http://nim-lang.org/docs/manual.html#procedures-method-call-...
You can pass functions as first-class values (which Nim calls "procedural types" [1]) by supplying the function name without any arguments or parentheses, eg, `someFunc` on its own.
[1] http://nim-lang.org/docs/manual.html#types-procedural-type
The base case occurs when the function takes no parameters: In this case, `someFunc` is a procedural type; `someFunc()` is a function invocation.
Footnote for interested readers: closures [2]; setter properties [3]; multi-methods that use dynamic dispatch [4].
[2] http://nim-lang.org/docs/manual.html#procedures-closures , [3] http://nim-lang.org/docs/manual.html#procedures-properties , [4] http://nim-lang.org/docs/manual.html#multi-methods
This looks like an enjoyable source for weird bugs: Write to functions with similar names (e.g., to_me() and tome()) and be surprised when nim doesn't distinguish between these two.
It's meant to prevent them: in Python applications it's not uncommon to see bugs introduced by an incorrect completion, e.g. updatePlayerstatus / updatePlayerStatus / update_player_status
With case/underscore insensitivity you know in advance that there can be only one "updateplayerstatus" in your codebase and write it according to your style, e.g. always update_player_status
OTOH, if your hypothetical is that programmer X writes `to_me()` while a different programmer Y writes `tome()`, and the two functions just happen to be identical in all parameter types... well, that can already happen anyway where two programmers each independently write a function with the same name.
Nim has a simple, clear specification of how identifiers will be compared: http://nim-lang.org/docs/strutils.html#normalize,string
There's no secret magic happening.
Though, looking at the code for "normalize" it appears to only support ASCII. That's even worse since now "lowercase" doesn't even apply uniformly if your identifiers have non-ASCII characters in them[0].
Doing a general normalization (as in Unicode) would probably also be bad, but for different reasons: You probably don't want the validity of programs to depend on the current locale of the machine you're compiling on. (See e.g. the "Turkish I" problem.)
In short: Case-insensitive identifiers[1] are a terrible, terrible idea.
[0] Not generally a good idea, but it happens and there are legitimate cases for it.
[1] Or, rather, "doing anything non-trivial to identifiers before lookup", I suppose.