Hi to all! First of all I want to thank all the passionate Nimmers spending their time to spread their knowledge about Nim and programming in general... Araq (waiting for your book on Nim), Dominik (I bought your book, wonderful!), Dr. Salewski, Narimiran, Mratism, Vindaar, just to name a few. Since this community is full of brilliant and smart computers scientists (no joke... I'm full of admiration for people able to build / modify compilers, to develop meta-programming DSL or to build data science libraries from scratch), I think there is no better place to ask this question.
Quite a "few" years ago, in my course of Telecommunications Engineering, I have been exposed a little bit to Pascal programming (I enjoyed it... this is probably one of the reason I immediately liked Nim a lot), and in a very limited way to C. I was (and I'm still) fascinated from computers and programming languages, but not that passionate to pursue a career as developer. I like the creative, "crafting" side of programming (e.g. when I need to develop something to get the answer to a small problem, or to automate some tedious and repetitive tasks) but I was never attracted from the idea to live by developing large, complex programs to suit someone else requirements about topics I'm not interested at all. I've used a bit Matlab at time for my thesis (digital signal processing simulation stuff), and much later, I started to use (and I still do) Python in my job to speed up some work that in many cases could be done with simple (but much more boring) spreadsheets. But I became more and more aware of my relevant gaps in the understanding of the programming art (Python shields you from a lots of details... but there is a price to pay for convenience, as always) and I start to think that maybe I should have tried to study some system programming language, like Nim... and C. Why C? Let me clarify that I really can't love most of the system programming languages like C++ and Rust. Nim is a completely other story, it's truly one of a kind. I think that safe types and automatic memory management (aka garbage collection) are great inventions, and I really appreciate those gifts Nim offers, along with language clarity, syntactic sugar, rich built-in library, flexibility, and simplicty/speed to compile code in small and efficient executables. My interest in C is primarily to understand better the context behind Nim, and also to learn to interface C libraries, a task where I know Nim shines, but requires some reasonable knowledge about C. I'm not planning at all to use extensively C to develop large programs / complex libraries (far beyond my capabilities).
So, given the context, which C programming book would you suggest?
On one side I was thinking about K&R C programming language, a timeless classic, still revered as THE BOOK to learn C. It's concise, and written by real computer scientists who know THEIR stuff. My primary concerns are about the "right edition" to get, and possibly lack of guidance about tools/utilities to go from a formally C correct program to a working binary executable or library (but maybe this can be complemented with other resources?).
Another one I was considering is King's C Programming: A Modern Approach. Bulkier book, maybe cover more topics... but it's the right one to get a good understanding of C ? Some of you may have completely different suggestions... thank you in advance for your time and advices.
Best C book so far in my opinion https://www.academia.edu/8533062/C_Programming_A_Modern_Approach_2nd_Edition
I will be buying the hardcover soon.
Since you're not new to programming, definitely start with Robert C. Seacord - "Effective C. An Introduction to Professional C Programming". Then go with Ben Klemens - "21st Century C". Accompany by Jens Gustedt's "Modern C" (available for free!).
All are well written, concise, to the point, not overwhelming and have stellar reviews on ACCU.
Don't take my word for granted, though, I'm not a C programmer.
My interest in C is primarily to understand better the context behind Nim.
Nim has not much "context" with C, whatever that means, it's Modula 3 with Python's syntax and Lisp's macro system.
There is nothing wrong with learning C, of course, but learning a real assembler is usually more effective IMHO. C is not particularly "low level", that's just its excuse for being particularly unhelpful.
C is not particularly "low level", that's just its excuse for being particularly unhelpful.
What a punchline @Araq ! 😁 😁 It's just true.
Actually since @araq comment , I would read this: https://ia802906.us.archive.org/8/items/systems-programming-with-modula-3/Systems_Programming_with_Modula-3.pdf
It will help you decipher more of Nim's types , generics , etc..
Nim has not much "context" with C, whatever that means, it's Modula 3 with Python's syntax and Lisp's macro system.
But where is Modula-3's opaque type then?
It seems that a "tiny" abstraction layer is missing in Nim. If this is intentional or accidential, I don't know. Anyhow, it has some daring consequences, e.g. for "concepts".
Both Modula-3 and ML were frontrunners in the late 80ies with regard to type theory. They both introduced module abstraction and abstract data types - we'd call them existential types today.
The connection between ML and Modula-3 is revealed in : "From ML to C via Modula-3" https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.123.8192&rep=rep1&type=pdf
The version of Modula 3 that I looked at had no generics
Modula-3 has abstract types like Modula-2 has. They allow for modular (separate) compilation.
Nim follows C++'s take on generics
C++'s templates allow for abstract types too. It is a hidden feature though. I demonstrated it within: https://forum.nim-lang.org/t/8728#56876
Nim stays "just a little bit" away from it. Nim tries to simulate abstract types with type schemes. But, these don't have enough power to allow for separate compilation.
Just recently, C++ aims to introduce module descriptions in Modula-2 Style. They could, in principle though, achieve the same effects with template abstractions.
Abstract types belong to the decidable fragment of Second Order Logic. It is a bit ironic that such a "simple" thing as separate compilation can lead to far reaching questions.
Gnu C programming tutorial, good for beginners:
http://www.crasseux.com/books/ctutorial/
GLIBC reference manual, more detailed info:
https://www.gnu.org/software/libc/manual/
The function index is often helpful, there are some other indexes too:
https://www.gnu.org/software/libc/manual/html_node/Function-Index.html
So 2.5.5 isn't generics ?
Yes, it is. Both Modula-2 and Modula-3 allow module-wide "polymorphic" (abstract) types. In addition, Modula-3 allows "generic" types (explicit type parameters) on the interface and module level.
Due to abstract types, both Modula(s) support static polymorphism without any runtime layer. Looking back to the 1980s , these things were still almost uncharted territory. Both languages were ahead of their time.
Nim would also benefit greatly from module-wide abstract types and type parameters.
As I said, the version of Modula 3 that I looked at had no "GENERIC INTERFACE". Or maybe I misremember. Regardless of the history the design requires explicit instantiation via
MODULE Integer; TYPE T = INTEGER; END;
MODULE IntStack = Stack(Integer) END;
And that makes it inferior to C++'s template mechanism. Yes, it really does and explicit instantiation is unheard of in Java, C#, Scala... for this reason.
And that makes it inferior to C++'s template mechanism. Yes, it really does and explicit instantiation is unheard of in Java, C#, Scala... for this reason.
Indeed, Ada generics suffer from this deficiency as well. It was an important factor in my decision to stop using Ada, even though I liked many other aspects of it.
I can offer you another language comparison: Oberon-2, Modula-3, Sather and Self with focus on "object orientation". It is particularly because of the asterisk "*" annotation that you can find both in Oberon and in Nim.
https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.14.6912&rep=rep1&type=pdf
Indeed, Ada generics suffer from this deficiency as well. It was an important factor in my decision to stop using Ada, even though I liked many other aspects of it.
If you have module-wide types, you might be tempted to instantiate or over-instantiate them. Both Ada and Modula-3 allow this. The other module-wide type is the abstract type, which cannot be instantiated. Much more difficult to manage. When these features came out, Modula-2 was introduced in 1978, these things were in their infancy and 10 years later still not clearly understood.
Can we do better? Yes - with the ML module design. It emerged in the 90ies - too late for Ada, C++, Modula-2/3 , sadly. Within ML (SML, OCAML), modules are types themselves and we can even transform them with functor-like transformers.