On Saturday, 8 April 2017 at 14:20:49 UTC, Boris-Barboris wrote:
Looks like your current implementation does not go in that
direction, seeing as it uses properties for field access.
Am i mistaken in assumption that such simple getter property
will be optimized to direct field access? Anyways, that's minor
detail.
I don't know the type of CONF.root, but from the usage syntax in
your example, it looks like an associative array. Associative
array lookup will be slower than simply accessing a variable.
Individual components' configuration can be delegated to their
components; their modules could contain public struct
definitions that you can add to the global Config struct,
which describes the configuration of the entire application.
I've used this pattern successfully in some projects, incl.
Digger:
https://github.com/CyberShadow/Digger/blob/master/config.d#L31-L36
Ok, that's nice, but it still requires manual inclusion of such
field into global config struct.
Yes; in my opinion, I think that's desirable because it is
aligned with the unidirectional flow of information from
higher-level components to lower-level ones, and does not impose
a particular configuration framework onto the lower-level
components (they only need to declare their configuration in
terms of a POD type).
Some "compile-time callback" system still would scale better in
my opinion.
A similar effect can be achieved by allowing components to
register themselves in a static constructor (not at compile-time,
but at program start-up).
I understand that you seem to be looking for a way to change
types (definitions in general) inside modules you import. This
is problematic from several aspects, such as other modules
depending on that module may find that the definitions "change
under their feet".
As expected since class that allows itself to be modified in
compile-time, always does so explicitly via mixin. Most of the
times such manipulation is used to extend functionality (add
field, plugin, method) without removing or modifying existing
ones. And if the names conflict, we get nice compile-time error
anyways.
Then you have problems such as the instance size of a class
changing depending on whether the code that requires the instance
size is seen by the compiler before the code that modifies the
instance size. I think it would cause complicated design problems
that limit the scalability of the language. Even without such
features, DMD had to go through a number of bugs to iron out the
correct semantics of evaluating types (e.g. with
"typeof(this).sizeof" inside a struct declaration, or recursive
struct template instantiations).
In D, once a type is declared and its final curly brace is
closed, you will know that its definition will remain the same
from anywhere in the program.
That's kinda my point - definition needs to stay the same
because it's built by compiler as many times as there are
transtaltion units, because evil old C grandpa.
I think this is not about technical limitations, but intentional
design choices. Allowing types to be modified post-declaration
invalidates many contracts and assumptions that code may have,
and make it harder to reason about the program as a whole.
Compare with e.g. INTERCAL's COMEFROM instruction.
D's answer to partial classes is UFCS, however this does not
allow "adding" fields, only methods.
Adding fields, or, generally, objects \ collections of objects,
is the main use case. Adding methods in my experience is rare
scenario.
UFCS is widely used in D for component programming:
http://www.drdobbs.com/architecture-and-design/component-programming-in-d/240008321