February 28, 2014 Re: @disable this for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On Friday, 28 February 2014 at 11:59:40 UTC, Dicebot wrote:
> On Friday, 28 February 2014 at 01:16:41 UTC, Mike Parker wrote:
>> Ideally, I'd love for the compiler to pick up on this idiom and not generate any typeinfo in this situation.
>
> Ideally one should use modules as namespaces :P
Ideally D should have build in namespaces.
Using class to mimic namespace, but then all the functions are virtual per default ?
|
February 28, 2014 Re: @disable this for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Remo | On Friday, 28 February 2014 at 12:52:38 UTC, Remo wrote:
> On Friday, 28 February 2014 at 11:59:40 UTC, Dicebot wrote:
>> On Friday, 28 February 2014 at 01:16:41 UTC, Mike Parker wrote:
>>> Ideally, I'd love for the compiler to pick up on this idiom and not generate any typeinfo in this situation.
>>
>> Ideally one should use modules as namespaces :P
>
> Ideally D should have build in namespaces.
Why? C like tag namespaces are awful and do C++ like namespaces offer any benefit over modules? Keep in mind that we have no Koenig lookup.
|
February 28, 2014 Re: @disable this for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On 2/28/2014 8:59 PM, Dicebot wrote:
> On Friday, 28 February 2014 at 01:16:41 UTC, Mike Parker wrote:
>> Ideally, I'd love for the compiler to pick up on this idiom and not
>> generate any typeinfo in this situation.
>
> Ideally one should use modules as namespaces :P
I don't buy that. That works fine to resolve conflicts, but it doesn't work for fine-grained namespace management. And when using named imports, that means everything in the module then belongs to that namespace, which isn't at all what I want. Besides which, using either fully-qualified names or named imports puts the impetus on the caller. If I design my modules around namespaces with the understanding that the caller will type foo.bar.myfunc all the time, there are bound to be conflicts when they forget to do it.
On the other hand, by wrapping my namespaced stuff in structs or classes, I can have multiple namespaces per module, some things completely outside the namespace, and the user gets a compiler error if they don't use it. To me, that's much, much neater.
|
February 28, 2014 Re: @disable this for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Friday, 28 February 2014 at 12:59:32 UTC, Mike Parker wrote: >> Ideally one should use modules as namespaces :P > > I don't buy that. That works fine to resolve conflicts, but it doesn't work for fine-grained namespace management. And when using named imports, that means everything in the module then belongs to that namespace, which isn't at all what I want. Besides which, using either fully-qualified names or named imports puts the impetus on the caller. If I design my modules around namespaces with the understanding that the caller will type foo.bar.myfunc all the time, there are bound to be conflicts when they forget to do it. D design is based on module as smallest composition unit. If you find yourself in situation where you want to have two namespaces in a single module, you should split it into two modules. Putting impetus on caller (named imports) is good here and huge advantage over C++ way in my opinion. It gives more control over application naming scheme. > On the other hand, by wrapping my namespaced stuff in structs or classes, I can have multiple namespaces per module, some things completely outside the namespace, and the user gets a compiler error if they don't use it. To me, that's much, much neater. It simply does not fit with D type system, most importantly with accessiblity attributes. I'd hate to encounter all that you mention as "benefits" in some D library I am forced to use. |
February 28, 2014 Re: @disable this for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Remo | On Friday, 28 February 2014 at 12:52:38 UTC, Remo wrote:
> On Friday, 28 February 2014 at 11:59:40 UTC, Dicebot wrote:
>> On Friday, 28 February 2014 at 01:16:41 UTC, Mike Parker wrote:
>>> Ideally, I'd love for the compiler to pick up on this idiom and not generate any typeinfo in this situation.
>>
>> Ideally one should use modules as namespaces :P
>
> Ideally D should have build in namespaces.
>
> Using class to mimic namespace, but then all the functions are virtual per default ?
No. By design namespace is a module. You don't use classes for namespaces, you create more modules. One may not like it but it is how D module system was created and it was intentional.
|
February 28, 2014 Re: @disable this for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On Friday, 28 February 2014 at 13:23:51 UTC, Dicebot wrote:
> On Friday, 28 February 2014 at 12:52:38 UTC, Remo wrote:
>> On Friday, 28 February 2014 at 11:59:40 UTC, Dicebot wrote:
>>> On Friday, 28 February 2014 at 01:16:41 UTC, Mike Parker wrote:
>>>> Ideally, I'd love for the compiler to pick up on this idiom and not generate any typeinfo in this situation.
>>>
>>> Ideally one should use modules as namespaces :P
>>
>> Ideally D should have build in namespaces.
>>
>> Using class to mimic namespace, but then all the functions are virtual per default ?
>
> No. By design namespace is a module. You don't use classes for namespaces, you create more modules. One may not like it but it is how D module system was created and it was intentional.
Right now I do not really miss namespacec in D.
I like modules in D.
What I hate already are problems with structs and ctors.
Most time while porting C++ code to D I spend a lot of time to resolve all the problems that happens because of struct ctors.
If I forget to do this then it still compiles but does not work at all...
|
February 28, 2014 Re: @disable this for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Remo | On Friday, 28 February 2014 at 13:32:13 UTC, Remo wrote: > What I hate already are problems with structs and ctors. > Most time while porting C++ code to D I spend a lot of time to resolve all the problems that happens because of struct ctors. > If I forget to do this then it still compiles but does not work at all... It is a long-standing bug and I am sorry for that. See http://forum.dlang.org/post/wziedbjjmxvabubvankk@forum.dlang.org |
February 28, 2014 Re: @disable this for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On 2/28/2014 10:21 PM, Dicebot wrote: > > D design is based on module as smallest composition unit. If you find > yourself in situation where you want to have two namespaces in a single > module, you should split it into two modules. Consider this. enum Foo {...} interface Bar {} struct BarManager { public static { void initialize(); void terminate(); ... more stuff } } This is my use-case. I don't want my users to have to refer to Foo or Bar with any sort of prefix except to avoid name-clashes. However, I want to logically group the functions to manage Bars under a single grouping. I don't need or want a Singleton for it. I could use free functions, but I use the initialize/terminate idiom a lot. As a user of my own library, it would be horribly annoying to have to fully qualify each call. Plus, now and again I have multiple "namespace structs" in a single module. If I see them as all being closely related, why should I split them off into different modules? > > Putting impetus on caller (named imports) is good here and huge > advantage over C++ way in my opinion. It gives more control over > application naming scheme. > >> On the other hand, by wrapping my namespaced stuff in structs or >> classes, I can have multiple namespaces per module, some things >> completely outside the namespace, and the user gets a compiler error >> if they don't use it. To me, that's much, much neater. > > It simply does not fit with D type system, most importantly with > accessiblity attributes. I'd hate to encounter all that you mention as > "benefits" in some D library I am forced to use. One of the most annoying things for me in C++ is to see something like some::ridiculously::long::namespace, that I then have to use on each type declared in that namespace. That makes me add using statements to the top of each module, which defeats the purpose in the first place. I would find it equally annoying in D if every module I imported required me to use a fully-qualified module name. Luckily, that isn't the case. We only need to do it do avoid conflicts. My purpose for using namespaces in this way is twofold: to indicate that those particular functions serve a collective purpose, and to make give more meaning to the user code. I don't need to worry about naming conflicts, thanks to the module system, but I don't see the module as the smallest unit of organization. |
February 28, 2014 Re: @disable this for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Friday, 28 February 2014 at 13:42:21 UTC, Mike Parker wrote:
> Consider this.
>
> enum Foo {...}
>
> interface Bar {}
>
> struct BarManager {
> public static {
> void initialize();
> void terminate();
> ... more stuff
> }
> }
>
> This is my use-case. I don't want my users to have to refer to Foo or Bar with any sort of prefix except to avoid name-clashes. However, I want to logically group the functions to manage Bars under a single grouping. I don't need or want a Singleton for it. I could use free functions, but I use the initialize/terminate idiom a lot. As a user of my own library, it would be horribly annoying to have to fully qualify each call. Plus, now and again I have multiple "namespace structs" in a single module. If I see them as all being closely related, why should I split them off into different modules?
I'd write it this way:
=== something/bar.d ===
interface Bar {}
=== something/barmanager.d ===
import something.bar; // possibly public import
void initialize();
void terminate();
=== app.d ===
import something.bar;
import barmanager = something.barmanager;
// refer to Bar directly and to init function via barmanager.initialize()
=========
Or, even better, turn bar into package and have something.bar.manager with same usage pattern.
|
February 28, 2014 Re: @disable this for structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On 2/28/2014 11:37 PM, Dicebot wrote:
>
> I'd write it this way:
>
> === something/bar.d ===
>
> interface Bar {}
>
> === something/barmanager.d ===
>
> import something.bar; // possibly public import
>
> void initialize();
> void terminate();
>
> === app.d ===
>
> import something.bar;
> import barmanager = something.barmanager;
>
> // refer to Bar directly and to init function via barmanager.initialize()
> =========
>
> Or, even better, turn bar into package and have something.bar.manager
> with same usage pattern.
And as a user of your library, I'm going to be extremely annoyed that I have to keep remembering to declare named imports to disambiguate all the intialize/terminate functions in all the modules that have them. If you're going to design your library that way, you should do it for me :)
I see modules, loosely, as a way to group immediate family and packages as a way to group extended family. To me, Bar and BarManager are closely related, so they belong in the same module. It also makes long-term maintenance simpler, since everything related to Bar is in one place. And then there's D's module-scope access to private methods/members, which at some level encourages this approach (and which I make good use of). If I were to break all of my modules up as you have in this example, it unnecessarily inflates the number of modules, increases the maintenance cost somewhat, and takes away my module access to private.
Anyway, I have a project I'm working on right now that I'll be putting up on github within a few weeks that serves as a more complete example. One of the great things about D is that it has enough room for both approaches.
|
Copyright © 1999-2021 by the D Language Foundation