Golang - my favorite programming language
I love golang and the team behind it. Rob Pike once said "golang is an open source project, not a google project.". I still trust Rob Pike and am sure he meant what he said. However, I do not trust google, and don't want their spyware running on my machine.
I refuse to install android-studio since I am sure it will be phoning home about all sorts of things. However, I naively believed that command line tools like compilers are safe from such network backdoors. This comes from using tools like vi, awk, Perl, python and GCC. One would never imagine they were sending information across the network.
Unfortunately this is no longer true as compilers and editors now have integrated package managers. We expect them to communicate on the network and we don't really know everything they might be communicating.
Obviously I'm not singling out google here. The same goes for swift (apple) and C# (microsoft). I don't want to work in those languages since I don't want to install the ecosystem that comes with them, on my machine.
Something I read recently and my own experiences with the golang package proxy reminded my how much I trust the golang tools on my machine, and yet how little I should trust them.
Remember when command line tools were safe from this behavior? Admittedly C also came from a corporation but it came free with every unix install and soon after I started using it, Richard Stallman et al. gave us GCC, a free C compiler.
GCC, in turn, allowed the development of new languages like Perl and python. No corporations in sight! We got a lot done with these languages. It's not like we are incapable of creating ecosystems without corporate "help". We have proved that, with countless projects in the past.
Using java for free software was the first misstep. We were warned against it but ignored those warnings. Much later the oracle/google battle showed how precarious it is to build on languages controlled by corporations.
Let's not keep making this mistake. Are there still free languages out there? Well, yes there are quite a few (and surely many more I forget to mention).
I'm focusing on compiled/statically-typed languages here so will be skipping over Common Lisp (a venerable language we should all seriously consider). A brief review reminded me of Zig and Nim. I had some problems building Zig from source, so moved on to Nim (which I also failed to build from source as it set my laptop on fire). I gave up at this stage and installed the pre-compiled binaries for Nim. So, just by luck I ended up choosing Nim for a deeper look.
Something else which I really like to have in a language is meta-programming and Nim has it (Zig also has meta-programming I understand).
Nim - my new favorite programming language (corporation free)
A brief overview of the main features I encountered while doing some coding beyond the 'hello world' level.
(using nim v1.6.10 on Alpine Linux v3.17)
- Python Syntax: Nim syntax is vaguely like python, indenting and colons for block structure. Counter to golang's tab-only approach, Nim insists on spaces-only.
- Large Language: Nim is a syntactically large language, like C++, and indeed lots of my earlier attempts at using generics threw up error messages which were as helpful as C++ (i.e. not very). I struggled thru. I probably prefer the simplicity of languages like golang but I have enjoyed overloading operators again and writing type converters, like in the "good old" C++ days.
- Many Styles Supported: Nim includes many programming styles and variations: functions, objects, macros and relies heavily on exception handling as opposed to golang's explicit rejection of exceptions. I have mixed feelings about exceptions, but it hasn't been a deal breaker.
- Modules: Separate compilation is supported by modules. The module/import system is much lighter than golang's and there is not nearly as much cognitive
overhead to setting up your first module. Just create
import xyz, done.
- Garbage Collected: The language is garbage collected, although there are escape hatches for doing your own memory management if you want (I have not tried).
- Meta-programming (aka macros) - the compiler must be able to run code at compile time and it seems Nim does this by including a VM in the compiler. It's all quite seamless (nothing like as good as Common Lisp, of course, but we don't expect that in a syntax-heavy, statically-typed language).
- Good Standard Library: As opposed to very simple languages, like C, all the expected data types are supported. There is good hash-table support. Libraries for HTML templating, http server and sql database access are part of the standard download.
- Async: Nim uses the Future/Async/Await style of concurrency which allows the language to avoid total integration of a concurrency model. This approach is also favored by Zig and Rust. Nothing I have seen beats golang for the simplicity and integration of its concurrency model. Alas. However, I managed to get we full web based system built without hitting any problems. I have learned a lot about the async/await style from Nim.
- Nim compiles to C. This has the advantage over LLVM of removing a dependency. In theory any C compiler (clang/gcc/..) can be used for the final compilation state.
In summary I managed to get quite a bit done with Nim, without hitting any major stumbling blocks. The language has been around for a long time now and the standard library contains most things you'll want.
Nim - Some Rough Edges and Stumbling Blocks
Of course, Nim relies on volunteers and volunteer time. That's to be expected from a free language. This means that Nim doesn't have every library you could possibly want and some things feel slightly unfinished.
None of the problems listed below were show stoppers. Indeed I dreaded hitting some problem or unfinished section of the language which would make it unusable. That never happened. People tend not to list the problems they had with their new favorite language but I think it is important to mention these things so that new adopters can learn about the rough edges, while also being assured that no major problems exist.
- noisy compiler. Coming from a unix background I expect tools to be quiet, unless there is a problem. Nim is quite noisy even when successfully compiling.
This is easily fixed with
[alias nimc='nim c --hints:off']. Sometimes compile with the noisy version to get warnings about unused imports/vars.
import std/db_sqlite- importing this module produces a warning every time. It seems to have to do with an experimental pragma in the module. I was able to rewrite the module slightly and remove the pragma. No more warning. It seems the Nim people are not bothered by the warning since it turned up in some posts, without remark.
std/db_sqlite- using prepared statements seems not so well handled. The module expected prepare/bind/exec separately, but calling bind again on a prepared statement results in an error. I had to modify the module again, to export clear_bindings and reset, so that I could make prepared statements work. As they are they only work if they are prepare/bind/destroy each time, which negates the advantage of preparing sql statements. I like that the source code for the standard library is easy to access [/usr/lib/nim/] and much appreciate that changes to the source code here are picked up in the next normal Nim compilation. In fact, it seems Nim compiles the standard library from source, lazily as it is used.
std/db_sqlite- there were some other functions/macros I needed to deal with prepared statements and these variants were missing in the std module. I think the prepared statement api is underused and under-implemented. I had to export some functions from the module and write my own helper macros in my app code to get around these problems. This is probably a case of the developers just not having enough time to do everything. I read somewhere that they are thinking of spinning off the db stuff as an external package. I think it's nice to have in the standard, included library.
std/db_sqlite- (update: 2023-01-20) I found another problem. If I get a unique constraint violation during insert, the next time I try using that SqlPrepared statement,
reset()fails and the next time I get a segv/nil pointer access on the prepared statement. I haven't found the solution to this yet.
- mutual import is not handled. There are lots of issues surrounding this online and the developers plan to include this feature in 2023. I have 2 types which I'd like in separate modules, however each type references the other and the import system won't allow this. I had to move both types into a single module file to make this work. The lead developer, Araq, says that the lack of this feature is to keep (incremental) compilation times fast, and that is a worthy goal.
Other free languages
This is just a list from memory. I'm sure there other great ones I've forgotten. (since augmented by HN suggestions).
I'll be following this post up soon with an in-depth look at my first real Nim project, a macro-based, html template generator for use in web server handler code.