Let's imagine we have two modules (from different developers) and their both purposes are to extend some standard type (e.g. string). These two modules have procedures with the same signature but different logic:
# mod1.nim
proc greeting*(name: string): string = name & ", hello from mod1!"
# mod2.nim
proc greeting*(name: string): string = name & ", hello from mod2!"
If I want to use both of these procedures I'm forced to call them in procedural style specifying module I wish to call it from:
import mod1
import mod2
echo mod1.greeting("Jhon") # => Jhon, hello from mod1!
echo mod2.greeting("Adam") # => Adam, hello from mod2!
But what if want to call them as methods? I can't do it because they are ambiguous in global scope. If I had an ability to import symbols from modules with renaming them, it would solve this problem:
from mod1 import greeting as greeting1
from mod2 import greeting as greeting2
echo "Jhon".greeting1() # => Jhon, hello from mod1!
echo "Adam".greeting2() # => Adam, hello from mod2!
Asking a Nim developers, didn't you think about adding such functionality? Or maybe I'm missing something and it already exists with any other syntax?You can easily create aliases:
from mod1 import greeting
from mod2 import greeting
const
greeting1 = mod1.greeting
greeting2 = mod2.greeting
echo "Jhon".greeting1() # => Jhon, hello from mod1!
echo "Adam".greeting2() # => Adam, hello from mod2!
It’s a quite defendable point of view, but the problem is that I don’t know any language without some ugly points.
In C and C++ doing separate compilation with #include is absolutely horrible (no modularity). We can find some excuses for C which is such an old language, but not for C++. Compared to this, the impossibility to rename while importing seems really a minor point. So, for a perfectionistic programmer, exit C and C++.
In Python, there are lots of ugly things, for instance the name mangling when using double underscore for private attributes, the scoping rules, the mutable default parameters, the strange reversed syntax of join to join the strings of a list, the ugly method names __str__, __add__, etc. All of this is probably enough to eliminate Python too.
I don’t know Rust well. I stopped learning the language when I discovered that it’s impossible to create references with cycles without going unsafe. As I’m somewhat perfectionistic too, exit Rust then.
We could continue with other imperatives languages such as Ruby, Lua, Julia, Go, D, Java… We could always find some misfeature or some lacking feature.
For me, to be perfectionistic means to be demanding regarding its own work and pragmatic regarding the tools we have to use. There are some things I don’t like in Nim (not a lot) and also some serious issues, but I know that the language is young and will improve over time.
Maybe Nim is just not a language for you because you have some strong expectations. So, maybe there are other languages which may better suit your needs. But I think nevertheless that it’s a pity to block on a point which I personally consider improvable, but rather minor.
I'm not a perfectionist, but I work with people who can be. I enjoy nim a great deal, but if I wanted to use nim on a project with them, then I know this will be a sticking point. The use case I'm most concerned about is when reviewers are viewing code in github or bitbucket or similar, and don't necessarily have access to quick symbol lookup.
Something I didn't see proposed, but I don't know if it would be easier: would it be possible to make a "wart" macro that would annotate a symbol as coming from a particular module, without breaking up the method call syntax? Usage like:
import pkg/wart
import dir/foo/bar as foo
import dir/baz/bar as baz
echo 5.foo@myadd(6).baz@myadd(7)
I took a stab at the above at one point, but couldn't get it to work quite the way I wanted in all cases.
Sorry if I come across as rude or ungrateful, as that was not my intent. I think nim is a great language and I like what is being done with it and to improve it. I understand that the "improvements" here probably seem unnecessary to most people using nim.
You come across fine. I don't think "everything is imperfect" is a relevant or useful response. (Nor, I think, is "I've never needed this".) OTOH, the response about using const is very useful, and the link to timotheecour's proposal is quite interesting and shows that there are broader approaches in the works (or at least being considered) that subsume the special case of aliasing an import.
When I've needed this, I've used a template, not realizing that I could use const to alias procs (thanks, lscrd).
Wait, was lscrd responding to a comment that has been deleted, rather than the top comment?
Yes exactly.
In theory, I agree with the poster. But in reality, there is something about Nim which leads to a philosophical change. I'll try to explain.
I strongly prefer to show a symbol's origin explicitly, and I like a language to enforce that. With Python, at least you have to write from foo import * explicitly if you want to import all symbols. With Nim, I personally try to use from foo import nil always, and I wish other Nim coders would also.
However, operators and macros force me to rethink all this. Operators are very useful for readable code, especially foo[index] for map/array lookups. Because Nim functions are free, not bound, they really need to be imported. I sometimes write from tables import `[]`, etc, but that can become tedious.
Even more useful -- and more specific to Nim -- macros may call named functions. A very important case is simple iteration. (Maybe iteration is a part of the langauge, not a macro, but my point is the same.)
for i in mything:
use(i)
For that code to work, mything needs a function called items(). (pairs() is also helpful.) In general, anytime you use a macro, you might need a bunch of functions that you wouldn't know about unless you read the source-code for that macro.
So the question is: Why would you want to import items() explicitly when it is never called explicitly in the same file?
Basically, the philosophy of Nim requires a different coding style that I am used to. My compromise is to use the explicit module namespace when I use things I want to highlight. E.g.
x = mymod.do_something_important()
But for modules like tables and json, I import all symbols.Yes, you are right. I really had strong expectations, so Nim let them down and made me sad. But you didn't understand my point completely. Of cource, every language has its ugly moments but my perfectionism most of all cares about "Quality of Life" of users of my code. I rejected Nim because it, as it now stands, cannot guarantee me that users of my code will feel comfortable using it. It's okay to resort to ugly workarounds. The realization that users of my code MAY have to resort to them in order to use my code is unbearable for me.
but I know that the language is young and will improve over time
Young? It's being developed since 2004.
As for the ideal language (at a level comparable to Nim)... For me, it's Kotlin. As a language, it is excellent, however there are points related to the JetBrains policy, which owns the rights to it. Especially, they strongly oppose people writing in Kotlin in editors other than their IDE, since they specialize in IDE development in the first place. There is a community plugin for VSCode, but it works very slowly and partially incorrectly. So if I need to write a small program to test something or automate some simple steps for me, I have to launch a heavyweight IDE if I want to do it quickly and comfortably. Kotlin is ideal for me, as an universal language for any tasks (even scripting), if not these moments with JB policy. So I tried to find a replacement for it, another universal language, but even more universal, without being tied to a specific IDE. And at first glance, Nim seemed like that, but later it made me very sad.
And guys, I'm sorry that my previous post offended you so much that you had to delete it and ban me. I was a little annoyed, but I didn't feel like I was resorting to personal abuse or something forbidden in it.
P.S. I'm not asking to be unbanned or anything like that. Most likely, I will not even come here anymore, but I noticed that I was banned and could not comment, only after I wrote whole this sheet of text. So I registered a new account just to publish it. In the end, I had to apologize at least.
Good luck and goodbye, guys.