On Tuesday, 13 January 2015 at 17:08:38 UTC, Laeeth Isharc wrote:
>> I see, thanks! :) I've started liking structs more and
>> more recently as well and been pondering on how to convert
>> a class-based code that looks like this (only the base
>> class has any data):
> it's hard to tell by brief description. but having multiple
> inheritance
> immediately rings an alarm ring for me. something is
> very-very-very
> wrong if you need to have a winged whale. ;-)
A real-world example:
http://www.hdfgroup.org/HDF5/doc/cpplus_RM/hierarchy.html
H5::File is both an H5::Location and H5::CommonFG (but not an
H5::Object)
H5::Group is both an H5::Object (subclass of H5::Location)
and H5::CommonFG
H5::Dataset is an H5::Object
i see something named "CommonFG" here, which seems to good
thing to
move out of hierarchy altogether.
bwah, i don't even sure that given hierarchy is good for D.
C++ has no
UFCS, and it's incredibly hard to check if some entity has some
methods/properties in C++, so they have no other choice than
to work
around that limitations. it may be worthful to redesign the
whole thing
for D, exploiting D shiny UFCS and metaprogramming features.
and,
maybe, moving some things to interfaces too.
I just finished reading aldanor's blog, so I know he is
slightly allergic to naked functions and prefers classes ;)
With Ketmar, I very much agree (predominantly as a user of HDF5
and less so as an inexperienced D programmr writing a wrapper
for it). It's a pain to figure out just how to do simple
things until you know the H5 library. You have to create an
object for file permissions before you even get started, then
similarly for the data series (datasets) within, another for
the dimensions of the array, etc etc - that doesn't fit with
the intrinsic nature of the domain.
There is a more general question of bindings/wrappers -
preserve the original structure and naming so existing code can
be ported, or write a wrapper that makes it easy for the user
to accomplish his objectives. It seems like for the bindings
preserving the library structure is fine, but for the wrapper
one might as well make things easy.
Eg here https://gist.github.com/Laeeth/9637233db41a11a9d1f4
line 146. (sorry for duplication and messiness of code, which
I don't claim to be perfectly written - I wanted to try
something quickly and have not yet tidied up).
So rather than navigate the Byzantine hierarchy, one can just
do something like this (which will take a struct of PriceBar -
date,open,high,low,close - and put it in your desired dataset
and file, appending or overwriting as you prefer).
dumpDataSpaceVector!PriceBar(file,ticker,array(priceBars[ticker]),DumpMode.truncate);
which is closer to h5py in Python. (It uses reflection to
figure out the contents of a non-nested struct, but won't yet
cope with arrays and nested structs inside). And of course a
full wrapper might be a bit more complicated, but I truly think
one can do better than mapping the HDF5 hierarchy one for one.
Laeeth.
In the hierarchy example above (c++ hdf hierarchy link), by using
UFCS to implement the shared methods (which are achieved by
multiple inheritance in the c++ counterpart) did you mean
something like this?
// id.d
struct ID { int id; ... }
// location.d
struct Location { ID _id; alias _id this; ... }
// file.d
public import commonfg; // ugh
struct File { Location _location; alias _location this; ... }
// group.d
public import commonfg;
struct File { Location _location; alias _location this; ... }
// commonfg.d { ... }
enum isContainer(T) = is(T: File) || is(T : Group);
auto method1(T)(T obj, args) if (isContainer!T) { ... }
auto method2(T)(T obj, args) if (isContainer!T) { ... }
I guess two of my gripes with UFCS is (a) you really have to use
public imports in the modules where the target types are defined
so you bring all the symbols in whether you want it or not (b)
you lose access to private members because it's not the same
module anymore (correct me if I'm wrong?). Plus, you need to
decorate every single free function with a template constraint.
// another hdf-specific thing here but a good example in general
is that some functions return you an id for an object which is
one of the location subtypes (e.g. it could be a File or could be
a Group depending on run-time conditions), so it kind of feels
natural to use polymorphism and classes for that, but what would
you do with the struct approach? The only thing that comes to
mind is Variant, but it's quite meh to use in practice.