January 13, 2015
On Mon, 12 Jan 2015 22:07:13 +0000
aldanor via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com>
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. ;-)


January 13, 2015
On Mon, 12 Jan 2015 22:07:13 +0000
aldanor via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com>
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):
p.s. can't you convert most of that to free functions? thanks to UFCS you'll be able to use them with `obj.func` notation. and by either defining `package` protection for class fields, or simply writing that functions in the same module they will have access to internal object stuff.

and if you can return `obj` from each function, you can go with templates and chaining. ;-)


January 13, 2015
On Tuesday, 13 January 2015 at 08:33:57 UTC, ketmar via Digitalmars-d-learn wrote:
> On Mon, 12 Jan 2015 22:07:13 +0000
> aldanor via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com>
> 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
January 13, 2015
On Tue, 13 Jan 2015 16:08:15 +0000
aldanor via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com>
wrote:

> On Tuesday, 13 January 2015 at 08:33:57 UTC, ketmar via Digitalmars-d-learn wrote:
> > On Mon, 12 Jan 2015 22:07:13 +0000
> > aldanor via Digitalmars-d-learn
> > <digitalmars-d-learn@puremagic.com>
> > 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.


January 13, 2015
>> >> 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.
January 13, 2015
On Tue, 13 Jan 2015 17:08:37 +0000
Laeeth Isharc via Digitalmars-d-learn
<digitalmars-d-learn@puremagic.com> wrote:

> I just finished reading aldanor's blog, so I know he is slightly allergic to naked functions and prefers classes ;)
that's due to absense of modules in C/C++. and namespaces aren't of big help here too. and, of course, due to missing UFCS, that prevents nice `obj.func()` for free functions. ;-)


January 13, 2015
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.
January 13, 2015
On Tue, 13 Jan 2015 18:35:15 +0000
aldanor via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com>
wrote:

> 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.
you can make a package and set protection to `package` instead of `private`, so your function will still be able to access internal fields, but package users will not. this feature is often missed by the people who are used to `public`/`protected`/`private` triad.


January 14, 2015

> 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

>
> // 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.

Void unlink(File f){}
Void unlink(Group g){}

For simple cases maybe one can keep it simple, and despite the Byzantine interface what one is trying to do when using HDF5 is not intrinsically so complex.

January 14, 2015
On Wednesday, 14 January 2015 at 14:54:09 UTC, Laeeth Isharc wrote:
>
>
>> 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
>
>>
>> // 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.
>
> Void unlink(File f){}
> Void unlink(Group g){}
>
> For simple cases maybe one can keep it simple, and despite the Byzantine interface what one is trying to do when using HDF5 is not intrinsically so complex.
So your solution is copying and pasting the code?

But now repeat that for 200 other functions and a dozen more types that can be polymorphic in weirdest ways possible...