Autore: Daniel Abrecht Data: To: dng Oggetto: Re: [DNG] About the rust language
I think the thing I dislike most about modern languages in general, is
the way they are built.
With C, I have independent compilation units, and header files, which
serve as interfaces.
Header files in the way of including code aren't good design. But having
a separation between interface and implementation on this level, is very
useful.
Modern languages not only get rid of headers, but also of independent
interfaces. You need the actual implementation, just to get the
interface. Code units are not truly Independent.
There are various things, the way C programs are built, allow, that is
not possible like that in other modern languages.
The most obvious, is that I do not need all the source files just to
build one of them, I only need the headers. But this has further
implications.
For example, I can write programs, which require libraries, which I do
not actually need to possess. I only really need the Interface (header).
More importantly though, this also works the other way around. Given an
Interface (header), I can write a library implementing it.
This also has implications of who can control these things. If the
Implementation is authoritative, and the interface derived from it, then
the developer of the library decides what it will do and how it looks
like.
But if the interface is authoritative, then whomever is in control of it
gets to decide what the libraries implementing it are going to be able
to do.
I think the ability to manage the Interface separately, is very
powerful. It makes it easy for many implementations to provide the
interface, and for the interface to stay consistent between
implementations.
This is very useful for diversity, for alternatives, for choice. Looking
at modern programs, it appears to me many do not realize that this can
be done like this, they only know importing a specific implementation
they downloaded with their limited package manager, because that's how
their limited language is designed to work.
The separation of Interfaces from Implementations also allow for some
other neat things. In my C Programs, I sometimes use it, combined with
`__attribute((constructor))` and `__attribute__((weak))`, for a sort of
inversion of control.
The way this works is rather simple. Ordinarily, when you have multiple
objects of a certain kind, or multiple implementations of something,
then some compilation unit has a list of them, and needs to know them,
that is how people know to deal with this.
However, I tend to use `__attribute((constructor))` to add the object to
the list on startup. So instead of some files depending on all the
implementations, the implementations depend on the program, from a
symbol perspective.
For interfaces, I just put function pointers in structs. I can then
change the functionality of my programs, simply by deciding which
Objects I link, without needing to alter any code before compiling it
(such as with macros).
And I use weak symbols for optional functionality.
This has kind of became my style over the years, but I can't really do
any of this in a convenient way using modern languages.