Re: Can I create static c callable library?

2018-09-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/27/18 8:16 AM, Atila Neves wrote:

On Tuesday, 25 September 2018 at 14:13:50 UTC, Jacob Carlborg wrote:

On Tuesday, 25 September 2018 at 12:05:21 UTC, Jonathan M Davis wrote:

If you use -betterC, then it's trivial, because your D program is 
restricted to extern(C) functions and features which don't require 
druntime. It can also be done without -betterC (and thus with 
druntime), but it gets to be _way_ more of a pain, because it 
requires that you manually initialize druntime - either by forcing 
whatever is using your "C" library to call a specific function to 
initialize druntime before using any of its normal functions or by 
having every function in the library check whether druntime has been 
initialized yet and initialize it if it hasn't been before it does 
whatever it's supposed to do.


Shouldn't it be possible to use a C initialization function, i.e. 
pragma(crt_constructor) to initialize druntime? Then it only needs to 
be initialized once and it's not required to check if it's initialized 
all the time.


--
/Jacob Carlborg


Even easier, compile this C file and add the resulting object file to 
your (now mostly) D static library:


---
extern int rt_init(void);
extern int rt_term(void);

__attribute__((__constructor__)) void dinit(void) {
     rt_init();
}
__attribute__((__destructor__)) void dterm(void) {
     rt_term();
}
---

The C runtime will initialise the D runtime for you.



I will point out that this is EXACTLY what pragma(crt_constructor) does.

And my comments still aren't answered -- I'm not sure whether this works 
correctly or not, as we don't test initializing druntime before C main runs.


-Steve


Re: Can I create static c callable library?

2018-09-27 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Sep 27, 2018 at 09:48:50PM +, Adam D. Ruppe via Digitalmars-d-learn 
wrote:
> On Thursday, 27 September 2018 at 21:41:31 UTC, H. S. Teoh wrote:
> > Though I'm not sure what will happen if your C program tries loading
> > two or more D libraries that use this trick... is rt_init()
> > idempotent?
> 
> It just refcounts itself.

Does that mean we could potentially make this "trick" the standard
druntime initialization?  Then we could make things work by default
whether you compile a standalone executable or a shared library.

Though I'm not sure what happens if multiple libraries each ship with
their own copy of druntime...


T

-- 
Bomb technician: If I'm running, try to keep up.


Re: Can I create static c callable library?

2018-09-27 Thread Adam D. Ruppe via Digitalmars-d-learn

On Thursday, 27 September 2018 at 21:41:31 UTC, H. S. Teoh wrote:
Though I'm not sure what will happen if your C program tries 
loading two or more D libraries that use this trick... is 
rt_init() idempotent?


It just refcounts itself.


Re: Can I create static c callable library?

2018-09-27 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Sep 27, 2018 at 03:11:26PM -0600, Jonathan M Davis via 
Digitalmars-d-learn wrote:
> On Thursday, September 27, 2018 6:16:13 AM MDT Atila Neves via Digitalmars-
> d-learn wrote:
[...]
> > Even easier, compile this C file and add the resulting object
> > file to your (now mostly) D static library:
> >
> > ---
> > extern int rt_init(void);
> > extern int rt_term(void);
> >
> > __attribute__((__constructor__)) void dinit(void) {
> >  rt_init();
> > }
> > __attribute__((__destructor__)) void dterm(void) {
> >  rt_term();
> > }
> > ---
> >
> > The C runtime will initialise the D runtime for you.
> 
> That's a neat trick.
[...]

Indeed!

Though I'm not sure what will happen if your C program tries loading two
or more D libraries that use this trick... is rt_init() idempotent? If
not, it could lead to a fun mess on startup... :-D  It also doesn't
address the very thorny issue of how to make multiple D libraries work
nicely with each other's copy of druntime, or how to make them share a
single druntime.


T

-- 
Без труда не выловишь и рыбку из пруда. 


Re: Can I create static c callable library?

2018-09-27 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, September 27, 2018 6:16:13 AM MDT Atila Neves via Digitalmars-
d-learn wrote:
> On Tuesday, 25 September 2018 at 14:13:50 UTC, Jacob Carlborg
>
> wrote:
> > On Tuesday, 25 September 2018 at 12:05:21 UTC, Jonathan M Davis
> >
> > wrote:
> >> If you use -betterC, then it's trivial, because your D program
> >> is restricted to extern(C) functions and features which don't
> >> require druntime. It can also be done without -betterC (and
> >> thus with druntime), but it gets to be _way_ more of a pain,
> >> because it requires that you manually initialize druntime -
> >> either by forcing whatever is using your "C" library to call a
> >> specific function to initialize druntime before using any of
> >> its normal functions or by having every function in the
> >> library check whether druntime has been initialized yet and
> >> initialize it if it hasn't been before it does whatever it's
> >> supposed to do.
> >
> > Shouldn't it be possible to use a C initialization function,
> > i.e. pragma(crt_constructor) to initialize druntime? Then it
> > only needs to be initialized once and it's not required to
> > check if it's initialized all the time.
> >
> > --
> > /Jacob Carlborg
>
> Even easier, compile this C file and add the resulting object
> file to your (now mostly) D static library:
>
> ---
> extern int rt_init(void);
> extern int rt_term(void);
>
> __attribute__((__constructor__)) void dinit(void) {
>  rt_init();
> }
> __attribute__((__destructor__)) void dterm(void) {
>  rt_term();
> }
> ---
>
> The C runtime will initialise the D runtime for you.

That's a neat trick.

- Jonathan M Davis





Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Chad Joan via Digitalmars-d-learn
On Thursday, 27 September 2018 at 09:58:25 UTC, Jonathan M Davis 
wrote:


For two types to be compared, they must be the the same type - 
or they must be implicitly convertible to the same type, in 
which case, they're converted to that type and then compared. 
So, as far as D's design of comparison goes, there is no need 
worry about comparing differing types. At most, you need to 
worry about what implicit type conversions exist, and D isn't 
big on implicit type conversions, because they tend to cause 
subtle bugs. So, while they definitely affect comparison, they 
don't affect anywhere near as much as they would in a language 
like C++. In general, you're not going to get very far if 
you're trying to make it possible to compare a user-defined 
type against other types in D without explicitly converting it 
first.


- Jonathan M Davis


That makes sense, but requiring types to be explicitly converted 
before comparisons kinda throws sand on the cake when I'm 
ostensibly trying to make things that interact seamlessly with 
existing types.


"alias this" is still awesome, so it's usually fine regardless :)

Thanks for the explanation.


Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Chad Joan via Digitalmars-d-learn
On Thursday, 27 September 2018 at 13:23:15 UTC, Adam D. Ruppe 
wrote:

On Thursday, 27 September 2018 at 05:04:09 UTC, Chad Joan wrote:
As above, I think this might be a very clean and effective 
solution for a different class of use-cases :)  I'll keep it 
in mind though.


Yeah. And I did make one mistake: the tupleof assignment trick 
wouldn't work well for references, so lol it isn't much of a 
deep copy. You'd want to deep copy any arrays too probably.


But sounds like you are already doing that, yay.


You're right though, if I end up adding boilerplate anyways, I 
may as well have a good shallow copy to begin with.


Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Chad Joan via Digitalmars-d-learn
On Thursday, 27 September 2018 at 14:23:48 UTC, Steven 
Schveighoffer wrote:

On 9/27/18 10:20 AM, Steven Schveighoffer wrote:
typeid sometimes gives you a more derived type than TypeInfo. 
Including for classes and structs.


In the past, .classinfo gave you a different thing than 
typeid(obj), but now it is the same thing:



     auto obj = new Object;
     // classinfo and typeid are the same object
     assert(obj.classinfo is typeid(obj));
     // and the same type
     static assert(is(typeof(obj.classinfo) == 
typeof(typeid(obj;


I wouldn't use classinfo any more, I generally use typeid.


I should add that typeid does give you the derived 
TypeInfo_Class, not the concrete one.


that is:

Object obj; // = null

//typeid(obj); // segfault, can't dereference null pointer

class C {}

obj = new C;

static assert(is(typeof(obj) == Object));

writeln(typeid(obj)); // C, not Object

So it really is a drop-in replacement for classinfo. I think 
classinfo is still there to avoid breaking existing code that 
uses it.


-Steve


Interesting!  That's yet another thing I hadn't realized had 
changed.  Good to know.


Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Chad Joan via Digitalmars-d-learn
On Thursday, 27 September 2018 at 13:16:58 UTC, Adam D. Ruppe 
wrote:

On Thursday, 27 September 2018 at 05:18:14 UTC, Chad Joan wrote:

How does this work?

The language reference states that typeid(Type) returns "an 
instance of class TypeInfo corresponding to Type".

(https://dlang.org/spec/expression.html#typeid_expressions)

But then the TypeInfo class doesn't seem to have a .create() 
method, or at least not one in the documentation:

https://dlang.org/phobos/object.html#.TypeInfo



I forgot about the create method, lol, that is what you want.

But typeid(obj) - pass it an existing object of the type btw - 
when obj is a class will return TypeInfo_Class - a subclass of 
TypeInfo.


It is *that* which has the create method.
https://dlang.org/phobos/object.html#.TypeInfo_Class.create

(or less horrible docs
http://dpldocs.info/experimental-docs/object.TypeInfo_Class.html
)


Yep, that solves the mystery!  Thanks!


Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Chad Joan via Digitalmars-d-learn

On Thursday, 27 September 2018 at 18:37:27 UTC, Chad Joan wrote:


I will probably end up going with the latter suggestion and 
have Extended use the Root's T.  That would probably make sense 
for what I'm doing.  In my case, the T allows the caller to 
configure what kind of output the thing provides... IIRC (it's 
been a while since I touched this code o.O).


Thanks for pointing that out.


Wait, actually the T is the element type of the input range, like 
"char" if the parser is to parse UTF8 strings.  I'd already 
figured that out too.  (*゚ー゚)ゞ


Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Chad Joan via Digitalmars-d-learn

On Thursday, 27 September 2018 at 08:56:22 UTC, Alex wrote:
On Wednesday, 26 September 2018 at 20:41:38 UTC, Chad Joan 
wrote:



class Root(T)
{
T x;
}

class Extended(T) : Root!T
{
T y;
}



Sorry for a technical aside, but would this be something for 
you?

https://forum.dlang.org/post/vtaxcxpufrovwfrkb...@forum.dlang.org

I mean... In either case, there is something curious in the 
Extended/Root usage, as they both are bound to the same type. 
And if so, you could get rid of the templatization in the 
Extended class, either by templating Root on the Extended or 
use the T of Root in Extended.


Perhaps it's half some form of unintended neural network 
fabrication that happened as I wrote the example and half that 
the original code isn't that well thought out yet.  The original 
code looks more like this:


template Nodes(T)
{
class Root
{
T x;
}

class Extended : Root
{
T y;
}
}

I will probably end up going with the latter suggestion and have 
Extended use the Root's T.  That would probably make sense for 
what I'm doing.  In my case, the T allows the caller to configure 
what kind of output the thing provides... IIRC (it's been a while 
since I touched this code o.O).


Thanks for pointing that out.


vibe.d error

2018-09-27 Thread hridyansh thakur via Digitalmars-d-learn

i've tried both on linux and windows

whenever i try to start a vibe.d project , it fails while running 
DUB

giving exist status one on both , here is the thing

linux:

hridyansh@dilawar-PC:~/d/web$ dub

vibe-core 1.4.3: building configuration "epoll"...
../../.dub/packages/vibe-core-1.4.3/vibe-core/source/vibe/internal/interfaceproxy.d:194:10:
 error: interface 
vibe.internal.interfaceproxy.InterfaceProxy!(Stream).InterfaceProxy.Proxy 
ambiguous virtual function _destroy
  private interface Proxy : staticMap!(ProxyOf, BaseTypeTuple!I) {
  ^

  ^
../../.dub/packages/vibe-core-1.4.3/vibe-core/source/vibe/internal/interfaceproxy.d:194:10:
 error: interface 
vibe.internal.interfaceproxy.InterfaceProxy!(RandomAccessStream).InterfaceProxy.Proxy
 ambiguous virtual function _typeInfo
  private interface Proxy : staticMap!(ProxyOf, BaseTypeTuple!I) {
  ^
/usr/bin/gdc failed with exit code 1.

windows : unexpected optlink termination at EIP = 0040F60A

is there any trouble with vibe.d or D lang? i just followed the 
intruction


i have made servers in Go , but i dont like Go's syntax so i want 
to do it in D , and leverage my existing C/C++ libraries


Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/27/18 10:20 AM, Steven Schveighoffer wrote:
typeid sometimes gives you a more derived type than TypeInfo. Including 
for classes and structs.


In the past, .classinfo gave you a different thing than typeid(obj), but 
now it is the same thing:



     auto obj = new Object;
     // classinfo and typeid are the same object
     assert(obj.classinfo is typeid(obj));
     // and the same type
     static assert(is(typeof(obj.classinfo) == typeof(typeid(obj;

I wouldn't use classinfo any more, I generally use typeid.


I should add that typeid does give you the derived TypeInfo_Class, not 
the concrete one.


that is:

Object obj; // = null

//typeid(obj); // segfault, can't dereference null pointer

class C {}

obj = new C;

static assert(is(typeof(obj) == Object));

writeln(typeid(obj)); // C, not Object

So it really is a drop-in replacement for classinfo. I think classinfo 
is still there to avoid breaking existing code that uses it.


-Steve


Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/27/18 1:18 AM, Chad Joan wrote:
On Wednesday, 26 September 2018 at 21:25:07 UTC, Steven Schveighoffer 
wrote:

...
Object.factory is a really old poorly supported type of reflection. I 
would not depend on it for anything.




Roger that.  Will avoid :)


You are better off using your own registration system.

As far as choosing the design for your problem, you can use:

auto obj = typeid(obj).create();

which is going to work better, and doesn't require a linear search 
through all modules/classes like Object.factory.




How does this work?

The language reference states that typeid(Type) returns "an instance of 
class TypeInfo corresponding to Type".

(https://dlang.org/spec/expression.html#typeid_expressions)

But then the TypeInfo class doesn't seem to have a .create() method, or 
at least not one in the documentation:

https://dlang.org/phobos/object.html#.TypeInfo


typeid sometimes gives you a more derived type than TypeInfo. Including 
for classes and structs.


In the past, .classinfo gave you a different thing than typeid(obj), but 
now it is the same thing:



auto obj = new Object;
// classinfo and typeid are the same object
assert(obj.classinfo is typeid(obj));
// and the same type
static assert(is(typeof(obj.classinfo) == typeof(typeid(obj;

I wouldn't use classinfo any more, I generally use typeid.

-Steve


Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Adam D. Ruppe via Digitalmars-d-learn

On Thursday, 27 September 2018 at 05:04:09 UTC, Chad Joan wrote:
The tree nodes are potentially very diverse, but the tree 
structure itself will be very homogeneous.


The virtual method can still handle that case!

But, if your child array of expressions is already accessible 
through the base interface, I think now your code is going to 
look something more like:


Expression copy(Expression e) {
   // I kinda hate the cast, but create is too generic lol
   // and we already know so it ok here
   Expression n = cast(Expression) typeid(e).create();

   foreach(child; e.children)
  n.children ~= copy(child);

   return n;
}

that's not too bad :)


I'm having trouble looking this up.  Could you link me to the 
docs for this?


Well, the create method is actually better anyway (and actually 
documented! I just forgot about it in that first post) but you 
can see more of the guts here 
http://dpldocs.info/experimental-docs/object.TypeInfo_Class.html



As above, I think this might be a very clean and effective 
solution for a different class of use-cases :)  I'll keep it in 
mind though.


Yeah. And I did make one mistake: the tupleof assignment trick 
wouldn't work well for references, so lol it isn't much of a deep 
copy. You'd want to deep copy any arrays too probably.


But sounds like you are already doing that, yay.


Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Adam D. Ruppe via Digitalmars-d-learn

On Thursday, 27 September 2018 at 05:18:14 UTC, Chad Joan wrote:

How does this work?

The language reference states that typeid(Type) returns "an 
instance of class TypeInfo corresponding to Type".

(https://dlang.org/spec/expression.html#typeid_expressions)

But then the TypeInfo class doesn't seem to have a .create() 
method, or at least not one in the documentation:

https://dlang.org/phobos/object.html#.TypeInfo



I forgot about the create method, lol, that is what you want.

But typeid(obj) - pass it an existing object of the type btw - 
when obj is a class will return TypeInfo_Class - a subclass of 
TypeInfo.


It is *that* which has the create method.
https://dlang.org/phobos/object.html#.TypeInfo_Class.create

(or less horrible docs
http://dpldocs.info/experimental-docs/object.TypeInfo_Class.html
)


Re: Can I create static c callable library?

2018-09-27 Thread Atila Neves via Digitalmars-d-learn
On Tuesday, 25 September 2018 at 14:13:50 UTC, Jacob Carlborg 
wrote:
On Tuesday, 25 September 2018 at 12:05:21 UTC, Jonathan M Davis 
wrote:


If you use -betterC, then it's trivial, because your D program 
is restricted to extern(C) functions and features which don't 
require druntime. It can also be done without -betterC (and 
thus with druntime), but it gets to be _way_ more of a pain, 
because it requires that you manually initialize druntime - 
either by forcing whatever is using your "C" library to call a 
specific function to initialize druntime before using any of 
its normal functions or by having every function in the 
library check whether druntime has been initialized yet and 
initialize it if it hasn't been before it does whatever it's 
supposed to do.


Shouldn't it be possible to use a C initialization function, 
i.e. pragma(crt_constructor) to initialize druntime? Then it 
only needs to be initialized once and it's not required to 
check if it's initialized all the time.


--
/Jacob Carlborg


Even easier, compile this C file and add the resulting object 
file to your (now mostly) D static library:


---
extern int rt_init(void);
extern int rt_term(void);

__attribute__((__constructor__)) void dinit(void) {
rt_init();
}
__attribute__((__destructor__)) void dterm(void) {
rt_term();
}
---

The C runtime will initialise the D runtime for you.



Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, September 27, 2018 2:44:25 AM MDT Chad Joan via Digitalmars-d-
learn wrote:
> The spec seems to have the homogeneous cases covered: classes
> with classes or structs with structs.  What I'm more worried
> about is stuff like when you have a class compared to a struct or
> builtin type, or maybe a struct compared to a builtin type
> (especially more complicated builtin types like arrays!).  The
> homogeneous cases are important for making a type consistent with
> itself, but the other cases are important for integrating a type
> with everything else in the ecosystem.
>
> Notably, "alias this" is awesome and has more or less solved that
> for me in the pedestrian cases I tend to encounter.  I can write
> a struct and alias this to some reference variable that will be
> representative of my struct's "nullness" or other states of
> existence.
>
> But I wouldn't be surprised if there are corner-cases I haven't
> encountered yet (actually I think I just remembered that this bit
> me a little bit once or twice) where having a single alias-this
> isn't sufficient to cover all of the possible things my
> struct/class could be compared to (ex: if the type's null-state
> corresponded to int.max for ints and float.nan for floats, and
> you can't just use opEquals, such as when the type is a class and
> could be precisely null).

For two types to be compared, they must be the the same type - or they must
be implicitly convertible to the same type, in which case, they're converted
to that type and then compared. So, as far as D's design of comparison goes,
there is no need worry about comparing differing types. At most, you need to
worry about what implicit type conversions exist, and D isn't big on
implicit type conversions, because they tend to cause subtle bugs. So, while
they definitely affect comparison, they don't affect anywhere near as much
as they would in a language like C++. In general, you're not going to get
very far if you're trying to make it possible to compare a user-defined type
against other types in D without explicitly converting it first.

- Jonathan M Davis





Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Alex via Digitalmars-d-learn

On Wednesday, 26 September 2018 at 20:41:38 UTC, Chad Joan wrote:


class Root(T)
{
T x;
}

class Extended(T) : Root!T
{
T y;
}



Sorry for a technical aside, but would this be something for you?
https://forum.dlang.org/post/vtaxcxpufrovwfrkb...@forum.dlang.org

I mean... In either case, there is something curious in the 
Extended/Root usage, as they both are bound to the same type. And 
if so, you could get rid of the templatization in the Extended 
class, either by templating Root on the Extended or use the T of 
Root in Extended.


Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Chad Joan via Digitalmars-d-learn
On Thursday, 27 September 2018 at 08:19:41 UTC, Jonathan M Davis 
wrote:
On Thursday, September 27, 2018 1:41:23 AM MDT Chad Joan via 
Digitalmars-d- learn wrote:
On Thursday, 27 September 2018 at 05:12:06 UTC, Jonathan M 
Davis


This is also reminding me of how it's always bugged me that 
there isn't a way to operator overload opEquals with a static 
method (or even a free function?), given that it would allow 
the class/struct implementer to guard against (or even 
interact intelligently with) null values:


That's not really an issue with D. With classes, when you have 
a == b, it
doesn't lower to a.opEquals(b). Rather, it lowers to 
opEquals(a, b), and the

free function opEquals is defined as

bool opEquals(Object lhs, Object rhs)
{
// If aliased to the same object or both null => equal
if (lhs is rhs) return true;

// If either is null => non-equal
if (lhs is null || rhs is null) return false;

// If same exact type => one call to method opEquals
if (typeid(lhs) is typeid(rhs) ||
!__ctfe && typeid(lhs).opEquals(typeid(rhs)))
/* CTFE doesn't like typeid much. 'is' works, but 
opEquals

doesn't
(issue 7147). But CTFE also guarantees that equal 
TypeInfos are
always identical. So, no opEquals needed during 
CTFE. */

{
return lhs.opEquals(rhs);
}

// General case => symmetric calls to method opEquals
return lhs.opEquals(rhs) && rhs.opEquals(lhs);
}

/
* Returns true if lhs and rhs are equal.
*/
bool opEquals(const Object lhs, const Object rhs)
{
// A hack for the moment.
return opEquals(cast()lhs, cast()rhs);
}

So, it already takes care of checking for null or even if the 
two references point to the same object. For structs, a == b, 
does lower to a.opEquals(b), but for better or worse, structs 
are designed so that their init values need to be valid, or 
you're going to have problems in general. Trying to work around 
that is fighting a losing battle.




The spec seems to have the homogeneous cases covered: classes 
with classes or structs with structs.  What I'm more worried 
about is stuff like when you have a class compared to a struct or 
builtin type, or maybe a struct compared to a builtin type 
(especially more complicated builtin types like arrays!).  The 
homogeneous cases are important for making a type consistent with 
itself, but the other cases are important for integrating a type 
with everything else in the ecosystem.


Notably, "alias this" is awesome and has more or less solved that 
for me in the pedestrian cases I tend to encounter.  I can write 
a struct and alias this to some reference variable that will be 
representative of my struct's "nullness" or other states of 
existence.


But I wouldn't be surprised if there are corner-cases I haven't 
encountered yet (actually I think I just remembered that this bit 
me a little bit once or twice) where having a single alias-this 
isn't sufficient to cover all of the possible things my 
struct/class could be compared to (ex: if the type's null-state 
corresponded to int.max for ints and float.nan for floats, and 
you can't just use opEquals, such as when the type is a class and 
could be precisely null).


Wouldn't it be helpful to have a root class type just to have 
a "Top" type at runtime, even if it had no members?  Ex: so 
you could do things like make an array ProtoObject[] foo; that 
can contain any runtime polymorphic variables.


Maybe? It's not something that I've personally found to be 
particularly
useful. Once you can templatize code, the need to have a common 
base class
gets pretty hard to argue for, but I don't know that it's 
non-existent.
Also, for better or worse, you can already get it with void* - 
and cover
more types no less (albeit less @safely). But from what I 
understand of what
Andrei is intending, ProtoObject will end up being the new root 
class for
all D classos, so having ProtoObject[] would work for all 
extern(D) classes.
Of course, that still potentially leaves exern(C++) classes and 
interfaces
(which could be extern(C++) or COM even right now and aren't 
derived from
Object). So, things are already a bit weird with classes when 
you start

interacting with other languages through D. is(T : Object) and
is(T == class) do _not_ mean quite the same thing even though 
you'd think
that they would. And I haven't done enough with extern(C++) or 
COM in D to
claim to understand all of the subtleties. If you're not 
messing with them
directly or writing generic code that's going to mess with 
them, it doesn't

really matter though.

-Jonathan M Davis


Gotcha.  Quite a rabbit hole :)


Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, September 27, 2018 1:41:23 AM MDT Chad Joan via Digitalmars-d-
learn wrote:
> On Thursday, 27 September 2018 at 05:12:06 UTC, Jonathan M Davis

> This is also reminding me of how it's always bugged me that there
> isn't a way to operator overload opEquals with a static method
> (or even a free function?), given that it would allow the
> class/struct implementer to guard against (or even interact
> intelligently with) null values:

That's not really an issue with D. With classes, when you have a == b, it
doesn't lower to a.opEquals(b). Rather, it lowers to opEquals(a, b), and the
free function opEquals is defined as

bool opEquals(Object lhs, Object rhs)
{
// If aliased to the same object or both null => equal
if (lhs is rhs) return true;

// If either is null => non-equal
if (lhs is null || rhs is null) return false;

// If same exact type => one call to method opEquals
if (typeid(lhs) is typeid(rhs) ||
!__ctfe && typeid(lhs).opEquals(typeid(rhs)))
/* CTFE doesn't like typeid much. 'is' works, but opEquals 
doesn't
(issue 7147). But CTFE also guarantees that equal TypeInfos are
always identical. So, no opEquals needed during CTFE. */
{
return lhs.opEquals(rhs);
}

// General case => symmetric calls to method opEquals
return lhs.opEquals(rhs) && rhs.opEquals(lhs);
}

/
* Returns true if lhs and rhs are equal.
*/
bool opEquals(const Object lhs, const Object rhs)
{
// A hack for the moment.
return opEquals(cast()lhs, cast()rhs);
}

So, it already takes care of checking for null or even if the two references
point to the same object. For structs, a == b, does lower to a.opEquals(b),
but for better or worse, structs are designed so that their init values need
to be valid, or you're going to have problems in general. Trying to work
around that is fighting a losing battle.

> Wouldn't it be helpful to have a root class type just to have a
> "Top" type at runtime, even if it had no members?  Ex: so you
> could do things like make an array ProtoObject[] foo; that can
> contain any runtime polymorphic variables.

Maybe? It's not something that I've personally found to be particularly
useful. Once you can templatize code, the need to have a common base class
gets pretty hard to argue for, but I don't know that it's non-existent.
Also, for better or worse, you can already get it with void* - and cover
more types no less (albeit less @safely). But from what I understand of what
Andrei is intending, ProtoObject will end up being the new root class for
all D classos, so having ProtoObject[] would work for all extern(D) classes.
Of course, that still potentially leaves exern(C++) classes and interfaces
(which could be extern(C++) or COM even right now and aren't derived from
Object). So, things are already a bit weird with classes when you start
interacting with other languages through D. is(T : Object) and
is(T == class) do _not_ mean quite the same thing even though you'd think
that they would. And I haven't done enough with extern(C++) or COM in D to
claim to understand all of the subtleties. If you're not messing with them
directly or writing generic code that's going to mess with them, it doesn't
really matter though.

-Jonathan M Davis





Re: Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

2018-09-27 Thread Chad Joan via Digitalmars-d-learn
On Thursday, 27 September 2018 at 05:12:06 UTC, Jonathan M Davis 
wrote:
On Wednesday, September 26, 2018 10:20:58 PM MDT Chad Joan via 
Digitalmars- d-learn wrote:

...

That's interesting!  Thanks for mentioning.

If you don't mind, what are the complaints regarding Object?  
Or can you link me to discussions/issues/documents that point 
out the shortcomings/pitfalls?


I've probably run into a bunch of them, but I realize D has 
come a long way since that original design and I wouldn't be 
surprised if there's a lot more for me to learn here.


I can point you to the related DIP, though it's a WIP in 
progress


https://github.com/andralex/DIPs/blob/ProtoObject/DIPs/DIP.md

There are also these enhancement requests for removing the 
various member functions from Object (though they're likely to 
be superceded by the DIP):


https://issues.dlang.org/show_bug.cgi?id=9769 
https://issues.dlang.org/show_bug.cgi?id=9770 
https://issues.dlang.org/show_bug.cgi?id=9771 
https://issues.dlang.org/show_bug.cgi?id=9772


Basically, the problems tend to come in two areas:

1. Because of how inheritance works, once you have a function 
on a class, you're forcing a certain set of attributes on that 
function - be it type qualifiers like const or shared or scope 
classes like pure or @safe. In some cases, derived classes can 
be more restricted when they override the function (e.g. an 
overide can be @safe when the original is @system), but that 
only goes so far, and when you use the base class API, you're 
stuck with whatever attributes it has. Regardless, derived 
classes can't be _less_ restrictive. In fact, the only reason 
that it's currently possible to use == with const class 
references in D right now is because of a hack. The free 
function opEquals that gets called when you use == on two class 
references actually casts away const so that it can then call 
the member function opEquals (which doesn't work with const). 
So, if the member function opEquals mutates the object, you 
actuall get undefined behavior. And because Object.opEquals 
defines both the parameter and invisible this parameter as 
mutable, derived classes have to do the same when they override 
it; otherwise, they'd be overloading it rather than overriding 
it.




You're right, I wouldn't be caught dead wearing that.

:)

But yeah, thanks for pointing that out.  Now I know not to mutate 
things in an opEquals, even if it makes sense from the class's 
point of view, just in case.  At least until this all gets sorted 
out and code gets updated to not inherit from Object.


Object and its member functions really come from D1 and predate 
all of the various attributes in D2 - including const. But even 
if we could just add all of the attributes that we thought 
should be there without worrying about breaking existing code, 
there would be no right answer. For instance, while in the vast 
majority of cases, opEquals really should be const, having it 
be const does not work with types that lazily initialize some 
members (since unlike in C++, D does not have backdoors for 
const - when something is const, it really means const, and 
it's undefined behavior to cast away const and mutate the 
object). So, having Object.opEquals be const might work in 99% 
of cases, but it wouldn't work in all. The same could be said 
for other attributes such as pure or nothrow. Forcing a 
particular set of attributes on these functions on everyone is 
detrimental. And honestly, it really isn't necessary.


Having them on Object comes from a Java-esque design where you 
don't have templates. With proper templates like D2 has, there 
normally isn't a reason to operate on an Object. You templatize 
the code rather than relying on a common base class. So, 
there's no need to have Object.toString in order have toString 
for all classes or Object.opEquals to have opEquals for all 
classes. Each class can define it however it sees fit. Now, 
once a particular class in a hierarchy has defined a function 
like opEquals or toString, that affects any classes derived 
from it, but then only the classes derived from it are 
restricted by those choices, not every single class in the 
entire language as has been the case with Object.




That makes sense.  Also, compile-time inheritance/duck-typing 
FTW, again.


This is also reminding me of how it's always bugged me that there 
isn't a way to operator overload opEquals with a static method 
(or even a free function?), given that it would allow the 
class/struct implementer to guard against (or even interact 
intelligently with) null values:


import std.stdio;

class A
{
int payload;

bool opEquals(int rhs)
{
if ( rhs == int.max )
return false;
else
return this.payload == rhs;
}
}

class B
{
int payload;

static bool opEquals(B lhs, int rhs)
{
if ( lhs is null && rhs ==