November 13, 2013
On Tuesday, 12 November 2013 at 22:45:15 UTC, Andrei Alexandrescu wrote:
> What are the better ways? Note that most of the time you don't "know" the name of a class - you get it down the wire during some deserialization. So there must be some way to build an object from a token representation of the object.
>

The serialization is a good example. You'll have to note that if the code has been able to serialize the data, it can generate at compile time the necessary scafolding to deserialize it.

>> - The functionality provided by Object.factory is trivially replaced by
>> a solution more specifically tailored to the problem at hand using
>> compile-time reflection.
>
> It's not quite trivial - somewhere there has to be a map and registration and lookup and whatnot. I don't see it why it's unbecoming for such functionality to be part of the standard library. I would agree, however, that it's a judgment call whether it should be wired in or provided on demand.
>

That s why this is a problem to add all that is the core of the language when it isn't used often.
November 13, 2013
On 11/12/13 4:36 PM, deadalnix wrote:
> On Tuesday, 12 November 2013 at 22:45:15 UTC, Andrei Alexandrescu wrote:
>> What are the better ways? Note that most of the time you don't "know"
>> the name of a class - you get it down the wire during some
>> deserialization. So there must be some way to build an object from a
>> token representation of the object.
>>
>
> The serialization is a good example. You'll have to note that if the
> code has been able to serialize the data, it can generate at compile
> time the necessary scafolding to deserialize it.

I think there is some confusion here. We're talking about polymorphic creation, i.e. an object comes down the wire and you don't know its type a priori. Again: grab MC++D and read the chapter on Factory, it clarifies all such stuff.

>> It's not quite trivial - somewhere there has to be a map and
>> registration and lookup and whatnot. I don't see it why it's
>> unbecoming for such functionality to be part of the standard library.
>> I would agree, however, that it's a judgment call whether it should be
>> wired in or provided on demand.
>>
>
> That s why this is a problem to add all that is the core of the language
> when it isn't used often.

That's a good point. I would tend to agree with that. But it doesn't make it a misfeature. It's a sensible feature.


Andrei

November 13, 2013
On 11/12/2013 11:45 PM, Andrei Alexandrescu wrote:
>> - Every class in any imported module will need to show up in the
>> generated code even if it is never used unless global static analysis is
>> carried out on arguments to Object.factory.
>
> Correct. On the other hand, a lot of unused classes

It is not necessary that there are a lot. Anything transitively reachable from there will be pulled in.

> in used modules
> seems to indicate a problem with the system's design.
>

Those could be classes that are only used at compile time, like a builder for a grammar for a CTFE parser generator, for lack of a better example. Furthermore, library modules may be larger than their actively used interface. (Phobos?) It would be interesting to see how much Object.factory influences the size of hello world, even though Phobos does not use too many classes

>> - If I know the fully qualified name of a class, there are better ways
>> to instantiate this class than passing a string containing that name to
>> Object.factory in order to call the default constructor.
>
> What are the better ways?

Call the default constructor. Call a delegate/virtual function that calls the default constructor.

> Note that most of the time you don't "know"
> the name of a class - you get it down the wire during some
> deserialization.

You don't want to call the default constructor during deserialization and you need actual information about the Object layout, so seems to be an instance of the next point.

> So there must be some way to build an object from a
> token representation of the object.
>
>> - The functionality provided by Object.factory is trivially replaced by
>> a solution more specifically tailored to the problem at hand using
>> compile-time reflection.
>
> It's not quite trivial - somewhere there has to be a map and
> registration and lookup and whatnot. I don't see it why it's unbecoming
> for such functionality to be part of the standard library. I would
> agree, however, that it's a judgment call whether it should be wired in
> or provided on demand.

I think that if supported at all, it should be an UDA declared somewhere in druntime.
November 13, 2013
On 11/12/13 6:03 PM, Timon Gehr wrote:
> On 11/12/2013 11:45 PM, Andrei Alexandrescu wrote:
>>> - Every class in any imported module will need to show up in the
>>> generated code even if it is never used unless global static analysis is
>>> carried out on arguments to Object.factory.
>>
>> Correct. On the other hand, a lot of unused classes
>
> It is not necessary that there are a lot. Anything transitively
> reachable from there will be pulled in.
>
>> in used modules
>> seems to indicate a problem with the system's design.
>>
>
> Those could be classes that are only used at compile time, like a
> builder for a grammar for a CTFE parser generator, for lack of a better
> example. Furthermore, library modules may be larger than their actively
> used interface. (Phobos?) It would be interesting to see how much
> Object.factory influences the size of hello world, even though Phobos
> does not use too many classes

Fair point.

>>> - If I know the fully qualified name of a class, there are better ways
>>> to instantiate this class than passing a string containing that name to
>>> Object.factory in order to call the default constructor.
>>
>> What are the better ways?
>
> Call the default constructor. Call a delegate/virtual function that
> calls the default constructor.

Wait, doesn't Object.factory call the default constructor of the created object?

>> Note that most of the time you don't "know"
>> the name of a class - you get it down the wire during some
>> deserialization.
>
> You don't want to call the default constructor during deserialization
> and you need actual information about the Object layout, so seems to be
> an instance of the next point.

If not the default constructor, which constructor? Didn't you say above that calling the default constructor is good? I feel we're talking past each other.

>> So there must be some way to build an object from a
>> token representation of the object.
>>
>>> - The functionality provided by Object.factory is trivially replaced by
>>> a solution more specifically tailored to the problem at hand using
>>> compile-time reflection.
>>
>> It's not quite trivial - somewhere there has to be a map and
>> registration and lookup and whatnot. I don't see it why it's unbecoming
>> for such functionality to be part of the standard library. I would
>> agree, however, that it's a judgment call whether it should be wired in
>> or provided on demand.
>
> I think that if supported at all, it should be an UDA declared somewhere
> in druntime.

That would be indeed nice. But I have the feeling a significant part of this dialog is marred by confusion.


Andrei

November 13, 2013
On 11/13/2013 03:15 AM, Andrei Alexandrescu wrote:
> ...
>>>> - If I know the fully qualified name of a class, there are better ways
>>>> to instantiate this class than passing a string containing that name to
>>>> Object.factory in order to call the default constructor.
>>>
>>> What are the better ways?
>>
>> Call the default constructor. Call a delegate/virtual function that
>> calls the default constructor.
>
> Wait, doesn't Object.factory call the default constructor of the created
> object?
> ...

Yes, I was listing some ways to do this that I think are better than calling Object.factory.

>>> Note that most of the time you don't "know"
>>> the name of a class - you get it down the wire during some
>>> deserialization.
>>
>> You don't want to call the default constructor during deserialization
>> and you need actual information about the Object layout, so seems to be
>> an instance of the next point.
>
> If not the default constructor, which constructor?

None, I guess you'd want to create the right object state in memory.

> Didn't you say above
> that calling the default constructor is good?

If that is what you want to do, yes.

> I feel we're talking past
> each other.
>

Maybe.

November 13, 2013
On 11/12/13 6:26 PM, Timon Gehr wrote:
> On 11/13/2013 03:15 AM, Andrei Alexandrescu wrote:
>> ...
>>>>> - If I know the fully qualified name of a class, there are better ways
>>>>> to instantiate this class than passing a string containing that
>>>>> name to
>>>>> Object.factory in order to call the default constructor.
>>>>
>>>> What are the better ways?
>>>
>>> Call the default constructor. Call a delegate/virtual function that
>>> calls the default constructor.
>>
>> Wait, doesn't Object.factory call the default constructor of the created
>> object?
>> ...
>
> Yes, I was listing some ways to do this that I think are better than
> calling Object.factory.

OK I think I figure you are confused. You can't call the default constructor of an object you don't know the type of.

Andrei

November 13, 2013
On 11/13/2013 03:48 AM, Andrei Alexandrescu wrote:
> On 11/12/13 6:26 PM, Timon Gehr wrote:
>> On 11/13/2013 03:15 AM, Andrei Alexandrescu wrote:
>>> ...
>>>>>> - If I know the fully qualified name of a class, there are better
>>>>>> ways
>>>>>> to instantiate this class than passing a string containing that
>>>>>> name to
>>>>>> Object.factory in order to call the default constructor.
>>>>>
>>>>> What are the better ways?
>>>>
>>>> Call the default constructor. Call a delegate/virtual function that
>>>> calls the default constructor.
>>>
>>> Wait, doesn't Object.factory call the default constructor of the created
>>> object?
>>> ...
>>
>> Yes, I was listing some ways to do this that I think are better than
>> calling Object.factory.
>
> OK I think I figure you are confused.

I'm not.

> You can't call the default
> constructor of an object you don't know the type of.
>
> Andrei
>

Indeed. There was a premise stating that I do. :o)

In any case, the only use for string -> new object is when there is some kind of parsing going on (and then you should make sure in some way that only objects of types in some well-defined subset can be constructed), otherwise you can always pass around richer data structures, such as an actual factory object.
November 13, 2013
On 11/12/13 7:05 PM, Timon Gehr wrote:
> On 11/13/2013 03:48 AM, Andrei Alexandrescu wrote:
>> On 11/12/13 6:26 PM, Timon Gehr wrote:
>>> On 11/13/2013 03:15 AM, Andrei Alexandrescu wrote:
>>>> ...
>>>>>>> - If I know the fully qualified name of a class, there are better
>>>>>>> ways
>>>>>>> to instantiate this class than passing a string containing that
>>>>>>> name to
>>>>>>> Object.factory in order to call the default constructor.
>>>>>>
>>>>>> What are the better ways?
>>>>>
>>>>> Call the default constructor. Call a delegate/virtual function that
>>>>> calls the default constructor.
>>>>
>>>> Wait, doesn't Object.factory call the default constructor of the
>>>> created
>>>> object?
>>>> ...
>>>
>>> Yes, I was listing some ways to do this that I think are better than
>>> calling Object.factory.
>>
>> OK I think I figure you are confused.
>
> I'm not.

Then how do you figure doing this:

class Streamable { ... }
class Foo : Streamable { ... }
class Bar : Streamable { ... }
string className = stream.readln();
Streamable obj = ...;

How do you create obj from className, when className could be either "Foo" or "Bar"? In the general case there could be any number of classes, in different modules.

>> You can't call the default
>> constructor of an object you don't know the type of.
>>
>> Andrei
>>
>
> Indeed. There was a premise stating that I do. :o)

So you say Object.factory is a misfeature based on a use case that solves a very different problem?

> In any case, the only use for string -> new object is when there is some
> kind of parsing going on (and then you should make sure in some way that
> only objects of types in some well-defined subset can be constructed),
> otherwise you can always pass around richer data structures, such as an
> actual factory object.

No parsing needs to be involved, as in e.g. binary formats. And I'm talking data not code, which excludes passing around a factory object.


Andrei

November 13, 2013

On 10.11.2013 12:38, Benjamin Thaut wrote:
> Attached you will find a e-mail conversation about the discussion of DIP
> 45. I moved the discussion here so everyone can contribute.
>
> Hi,
>
> DIP 45 is waiting for some offical approval / comment so it can be
> implemented. It would be great if one of you could look into the topic
> and give official approval or improvement suggestions as the DIP has
> been in limbo for quite some time now. I'm not willing to start working
> on it before there is official approval, because I made bad experiences
> with this in the past.
>
> In my opinion the DIP is in a state where further discussion will not
> lead to any improvements. The DIP should be implemented to see which
> problems arrise during implementation to then discuss how to solve them.
>
> I've also seen a couple of questions to the state of Windows DLL support
> and shared libraries on the newsgroup. A working export keyword is
> required to actually implement that support on windows.
>
> The DIP: http://wiki.dlang.org/DIP45
> The latest discussion on the NG:
> http://forum.dlang.org/post/kvhu2c$2ikq$1@digitalmars.com
> Bug associated with the problem:
> http://d.puremagic.com/issues/show_bug.cgi?id=9816
>
> Kind Regards
> Benjamin Thaut

I think the DIP is very reasonable. Some random comments:

- when building a single object file or library, I would expect that it won't be torn apart later, so optimizations currently limited to accesses within the same module by the DIP could be extended to the modules included in current compilation target.

- a better example where cross-DLL data accesses to globals are needed is TypeInfo, e.g. when a class info references it's base class or interfaces.

- I'd be fine with reversing the default for stripping exports from a library, i.e. replacing "-libexports" with "-stripexports".

- I agree that cross DLL TLS accesses should be possible, though it might be implemented in a second step. Last time I tried it with C++, it wasn't supported, but it is probably not missed that much as thread local data is not as ubiquitous as in D.

- The DIP should state what happens to template instances. Assuming the definition is marked "export", I guess instances will be dllexport if they are compiled together with the module that contains the definition. What will happen if it is instantiated, but the defining module is merely imported?

Rainer
November 13, 2013
Am 13.11.2013 08:31, schrieb Rainer Schuetze:
>
> - The DIP should state what happens to template instances. Assuming the
> definition is marked "export", I guess instances will be dllexport if
> they are compiled together with the module that contains the definition.
> What will happen if it is instantiated, but the defining module is
> merely imported?
>
> Rainer

That is a very good point I also thought about. But because I'm not familiar with how exactly template instanciation works I can't really provide a solution for that.

Does Walters recent template instanciation optimization also take into account template instaces of templates that are defined outside of the module that contains the template definition? I think the behaviour of exported template should mainly satisfy the needs of this optimization.

Kind Regards
Benjamin Thaut