www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Many questions

reply Fractal <d294934 bsnow.net> writes:
Hello

After using the D1 language i have some questions about it:

- Why i cant use many files with the same module name? I want to use modules
like .NET or C++ namespaces and the file has 10K lines and finding a line takes
many time...

- Why there is no ranged foreach in D1?

- Why there is no pure keyword in D1?

- Why cent (128 bit integer) is not implemented?

- If a base class constructor has some parameters, when 
creating a class that extends that base, if there is no constructor, create it
automatically with the same parameters as the base class, and
call it. Is possible to add this capability to D?

- Why methods are virtual by default? if i export a class in a DLL, all methods
are threated as virtual?

- Why enum uses int by default? why not ubyte? or the integral type that
matches best with the min and max?

- Why exists typedef and alias? in modern languages like C#, i can not see
these things (these are confusing)...

- Assosiative array: why stores the keys? why not the hashes? 

- Why no multiple inheritace? if i have a simple (3 lines function) code and i
need share it between many classes, i use an interface, and implementing the
function in all the classes grows the code potentially. Simply if a class
member name collides, threat as error. No virtual classes like C++...

- Hiding class implementation like Windows COM can be done with an interface.
but it makes all methods virtual... is there any way to make a class like an
opaque pointer? (but with the same sintax of a common class)

- When overriding a method: is possible force an inherited class to call the
base method?

- Why there is no XML module in Phobos for D1?

- Is there any standard API like the .NET base classes for D?

- Why the overrided method does not inherit the default values for arguments?

Thanks in advance
May 03 2009
next sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Fractal wrote:
 - Why i cant use many files with the same module name? I want to use 

finding a line takes many time... Errr... no offense, but that kinda sounds like a bad design...
 - Why there is no ranged foreach in D1?

It was introduced after D2 was started... really, this is such a benign (and useful!) feature I think it should be backported, but whatever.
 - Why there is no pure keyword in D1?

Pure requires immutable (constant) storage for guarantees. If you want const and pure, you should be using D2.
 - Why cent (128 bit integer) is not implemented?

What's your use case? I honestly can't think of any time I'd prefer cent over an actual BigInteger class.
 - If a base class constructor has some parameters, when 
 creating a class that extends that base, if there is no constructor, create it
automatically with the same parameters as the base class, and
 call it. Is possible to add this capability to D?

You could do some template/mixin magic to do it, probably. I wouldn't mind having this in the core language, but... eh...
 - Why methods are virtual by default? if i export a class in a DLL, all
methods are threated as virtual?

It reduces unexpected behavior in the common case. Exporting D classes in a DLL... in a lot of cases it won't work (DLLs have issues); I'd recommend DDL.
 - Why enum uses int by default? why not ubyte? or the integral type that
matches best with the min and max?

Not sure. FWIW, int is the same speed or faster than ubyte/ushort/etc. on 32-bit processors, so it really only matters for packed structs.
 - Why exists typedef and alias? in modern languages like C#, i can not see
these things (these are confusing)...

IMO, they're very useful, especially for backwards compatibility or long template names.
 - Assosiative array: why stores the keys? why not the hashes? 

So you can enumerate through the keys/make a set type. If you want a hash-only hash, you can make one pretty easily.
 - Why no multiple inheritace? if i have a simple (3 lines function) code and i
need share it between many classes, i use an interface, and implementing the
function in all the classes grows the code potentially. Simply if a class
member name collides, threat as error. No virtual classes like C++...

MI has issues, especially with data layout. Use a mixin to share the code between classes: template FooImpl() { void foo() { ... } } class A : B { mixin FooImpl!() } class C : D { mixin FooImpl!() }
 - Hiding class implementation like Windows COM can be done with an interface.
but it makes all methods virtual... is there any way to make a class like an
opaque pointer? (but with the same sintax of a common class)

I'm not sure what you mean. If you mark an overridden method as "final" any calls to it from something of the class type will be direct. interface I { void shine(); } class C : I { final void shine() { } } void main() { C c = new C(); I i = c; i.shine(); // Virtual c.shine(); // Direct }
 
 - When overriding a method: is possible force an inherited class to call the
base method?

No.
 - Why there is no XML module in Phobos for D1?

It just wasn't implemented before D2 came out. Honestly, I'd recommend either Tango+D1 or Phobos+D2... Phobos+D1 is the least supported of the three, and D1 Phobos is pretty skimpy.
 - Is there any standard API like the .NET base classes for D?

Um... the classes in Phobos or the classes in Tango? (The Tango ones are more .NET-like).
 - Why the overrided method does not inherit the default values for arguments?

No idea, but that would be useful.
 Thanks in advance

May 03 2009
parent reply "Saaa" <empty needmail.com> writes:
 interface I
 {
 void shine();
 }

 class C : I
 {
 final void shine() { }
 }

 void main()
 {
 C c = new C();
 I i = c;

this wrong?
 i.shine(); // Virtual
 c.shine(); // Direct
 }

May 03 2009
parent Robert Fraser <fraserofthenight gmail.com> writes:
Saaa wrote:
 void main()
 {
 C c = new C();
 I i = c;

this wrong?

In this case, both c and i are pointers to the data.
May 03 2009
prev sibling next sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Fractal wrote:
 Hello
 
 After using the D1 language i have some questions about it:
 
 - Why i cant use many files with the same module name? I want to use modules
like .NET or C++ namespaces and the file has 10K lines and finding a line takes
many time...

Because in D, the module name maps to a file. If the file is too big, break it up. You can use mixins, aliases or even public imports to combine modules together.
 - Why there is no ranged foreach in D1?

Because it's in D2.*
 - Why there is no pure keyword in D1?

Because it's in D2.*
 - Why cent (128 bit integer) is not implemented?

Because no one's given a convincing argument why Walter should spend time implementing it yet. I could be wrong, but I don't think there's any CPU support for them, either.
 - If a base class constructor has some parameters, when 
 creating a class that extends that base, if there is no constructor, create it
automatically with the same parameters as the base class, and
 call it. Is possible to add this capability to D?

You could do it in D2 with a mixin.
 - Why methods are virtual by default? if i export a class in a DLL, all
methods are threated as virtual?

Because it's more useful. If you want to make them non-virtual, declare them final. That said, speaking from personal (and recent) experience, there's nothing more annoying than a class you want to subclass where all the methods are final.
 - Why enum uses int by default? why not ubyte? or the integral type that
matches best with the min and max?

Because ints are faster. I am not an expert, but I believe that most 32-bit CPUs can move ints around with the same speed, if not faster, than smaller types. The smaller moves are implemented as big moves + shifts and masks.
 - Why exists typedef and alias? in modern languages like C#, i can not see
these things (these are confusing)...

Because D is a modern language and they are very useful. Well, alias is definitely very useful; typedef is good to have.
 - Assosiative array: why stores the keys? why not the hashes? 

Because hashes are non-unique and if you didn't, you could NEVER guarantee you'd found the correct slot. You should brush up on your data structures.
 - Why no multiple inheritace? if i have a simple (3 lines function) code and i
need share it between many classes, i use an interface, and implementing the
function in all the classes grows the code potentially. Simply if a class
member name collides, threat as error. No virtual classes like C++...

Because Walter feels that MI isn't worth it. Ever tried to work out out to construct a Python object with multiple base class trees? It's horrible. Just use interfaces and mixins.
 - Hiding class implementation like Windows COM can be done with an interface.
but it makes all methods virtual... is there any way to make a class like an
opaque pointer? (but with the same sintax of a common class)

Because... oh damn, so much for that idea. I'm honestly not sure what you're asking here. If it's an opaque pointer, how would you do anything with it?
 - When overriding a method: is possible force an inherited class to call the
base method?

And this is why methods are virtual by default. If it's not virtual, then no.
 - Why there is no XML module in Phobos for D1?

Because it's in D2.*
 - Is there any standard API like the .NET base classes for D?

That would be Phobos or Tango, depending on which you're using.
 - Why the overrided method does not inherit the default values for arguments?

It just doesn't.
 Thanks in advance

* "Because it's in D2": changes made to D2 are, in general, not ported back to D1. D1 is supposed to be "stable" in the sense that only bug fixes and new features that don't impact any existing code are made. -- Daniel
May 03 2009
prev sibling next sibling parent dsimcha <dsimcha yahoo.com> writes:
== Quote from Fractal (d294934 bsnow.net)'s article
 Hello
 After using the D1 language i have some questions about it:
 - Why i cant use many files with the same module name? I want to use modules

many time... If I understand your question correctly, you can very easily simulate this with a public import. Put some of the code in a different module, and publicly import that module in your main module.
 - Why there is no ranged foreach in D1?

D1 is supposed to be stable, and they were thought of after D1 was declared stable. D1 is supposed to receive bug fixes only, not changes to spec.
 - Why there is no pure keyword in D1?

Same reason as no ranged foreach.
 - Why cent (128 bit integer) is not implemented?

It's just a low priority and noone's gotten around to it. There aren't too many use cases where 64 bits isn't big enough, but 128 is.
 - If a base class constructor has some parameters, when
 creating a class that extends that base, if there is no constructor, create it

 call it. Is possible to add this capability to D?

Would be nice. I've thought of the same thing before, but never really brought it up b/c it seemed like a relatively minor thing.
 - Why methods are virtual by default? if i export a class in a DLL, all methods

Methods are virtual by default because it avoids subtle bugs caused by not declaring something virtual and then overriding it. If you really want to avoid the overhead of virtual methods, make the method final. You won't be able to override it, but if it's not virtual, you probably shouldn't anyhow.
 - Why enum uses int by default? why not ubyte? or the integral type that
matches

I guess b/c the spec was created with 32-bit hardware in mind and int and uint are fastest on 32-bit hardware.
 - Why exists typedef and alias? in modern languages like C#, i can not see
these

typedef is strong, i.e. the following would not work: typedef int INT; INT foo; int bar; bar = foo; // Would require a cast. alias is weak, i.e. the above would work. They're really two different concepts, albeit in a subtle way.
 - Assosiative array: why stores the keys? why not the hashes?

1. The hashes are also stored for speed. 2. You need to know the key to resolve hash collisions and to iterate over the AA.
 - Why no multiple inheritace? if i have a simple (3 lines function) code and i

function in all the classes grows the code potentially. Simply if a class member name collides, threat as error. No virtual classes like C++... This one is somewhat controversial, and I won't start a multiple inheritance holy war. However, I will suggest looking into template mixins and string mixins as a possible substitute for many use cases of multiple inheritance.
 - Hiding class implementation like Windows COM can be done with an interface.

opaque pointer? (but with the same sintax of a common class)
 - When overriding a method: is possible force an inherited class to call the

Not any way I'm aware of. This is something that might just have to be enforced by convention. Then again, you could check to make sure whatever the base method is supposed to do has been done, using invariant() contracts.
 - Why there is no XML module in Phobos for D1?

Because the D1 version of Phobos just plain sucks, to be honest. I highly recommend against its use. Phobos has improved by leaps and bounds for D2. If you use D1, you should use Tango.
 - Is there any standard API like the .NET base classes for D?
 - Why the overrided method does not inherit the default values for arguments?

Because this would require that the compiler have the full source code for the base class when compiling the derived class. Default arguments are compile time syntactic sugar. The only ways to do this would be to get rid of separate compilation entirely, or to make default arguments a part of the interface.
 Thanks in advance

May 03 2009
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Hello, and welcome Fractal. I can give you some answers; other people will fill
the missing ones.

I can see you come from C#. D isn't C#, and not everything C# does differently
from D is an mistake of the D design. Sometimes it's just a different way to do
things, sometimes it's a design that is more fit for the other features of D,
some times it's a design error of D, and sometimes it's a design error of C#.


- Why i cant use many files with the same module name?<

Because that's messy.
I want to use modules like .NET or C++ namespaces and the file has 10K lines
and finding a line takes many time...<

My serious (wise) advice is to use smaller files.
- Why there is no ranged foreach in D1? - Why there is no pure keyword in D1?<

Because D is developed mostly by a person (Walter), and such person can't keep two (three) compilers updated. And maybe because Walter wants people to slowly leave D1 behind and use D2.
- Why cent (128 bit integer) is not implemented?<

Probably because not enough people have asked for it, because it's not easy to find purposes for them, and because Don (and you) have not implemented them yet. LDC compiler already has a partial support for them, probably once LLVM 2.6 comes out they may become usable.
- Why methods are virtual by default?<

To simplify the life of the programmer, I presume (see Java). And because smart compilers are supposed to magically devirtualize them.
- Why enum uses int by default? why not ubyte?<

Probably because int/uint are the faster types to manage by the CPU, because today memory is cheap, and because even if you use an ubyte often you don't save memory anyway because the following variables in the stack/heap may be aligned to 4 bytes aniway, so you often end with 3 bytes of padding after it.
- Why exists typedef and alias?<

Alias is very useful, to "change" name of member functions, to define different names and types, etc. You can see why typedef is useful if you come from Pascal-like languages, and when you don't use much Object oriented programming. For example you may have some functions that take an array, with a typedef you can be sure it's the right kind of array and not an array with the same number of dimensions and the same base type.
in modern languages like C#, i can not see these things (these are
confusing)...<

Typedef isn't confusing. In the universe there are things that C# doesn't have yet. D is modern but has typedef.
- Assosiative array: why stores the keys? why not the hashes?<

Where do you want to keep the keys?
- Why no multiple inheritace?<

Probably because Walter thinks it's a complex feature that often you don't really need. D tries to be less quite complex than C++, even if this reduces the power of D a bit.
if i have a simple (3 lines function) code and i need share it between many
classes, i use an interface, and implementing the function in all the classes
grows the code potentially. Simply if a class member name collides, threat as
error. No virtual classes like C++...<

I don't understand you much. Have you tried a "template mixin"?
is there any way to make a class like an opaque pointer? (but with the same
sintax of a common class)<

I don't think so.
- Why there is no XML module in Phobos for D1?<

Because Walter has not found the time to do it. Take a look at Phobos.
- Is there any standard API like the .NET base classes for D?<

Nope. Not in Phobos. Maybe something vaguely similar may be created in the future.
- Why the overrided method does not inherit the default values for arguments?<

I don't know. Maybe Walter has not thought about this yet. Bye, bearophile
May 03 2009
prev sibling parent reply Fractal <d294934 bsnow.net> writes:
Hello again...

Thanks for the quick responses! and sorry... if my english is very bad :)

C#: No, i dont have been used C# for anything. But i like the .NET framework
structure. How ever not at all (it also uses interfaces).

The namespaces: i used them with C++, and the idea of separation between the
uses of types, makes a very good layout. Because some namespaces requires more
types, always i write each class in separate files. D simply breaks it, making
a big amount of lines for imports.

Automatic contructor: for example the exceptions. Exception is a simple class
that takes one argument. When making others exceptions,
it is not necessary write the constructor (if not takes other args)

Force super call: if a base class uses a method for releasing system resources,
and in a inherited class, i "forget", (or intencionally?), write the
super.release() or something when overriding the method, many problems will
occour...

Templates: i dont use templates or mixins. they really confuses me and i think
so that they only should be used for "array classes" or something similar.

Associative arrays: yes, i can make my own implementation, but also the
language provides it natively, and with optimizations...

Foreach ranged: it cannot be added to D1? it simplies the life, and not breaks
any existing code

cent: just for hashing... in C++ i can see the type __int128 (using Visual
Studio)

Tango and Phobos: Tango is good, but the File class makes more problems than it
solves. And i dont like the Phobos design, but I really need the XML... just
writing other API?

And.. thanks again
May 03 2009
next sibling parent reply "Saaa" <empty needmail.com> writes:
 Templates: i dont use templates or mixins. they really confuses me and i 
 think so that they only should be used for "array classes" or something 
 similar.

reading the code more difficult? If it is the first then I don't really get it: you sound like somebody who gets a lot of things. mixins are just code in string form, right?
May 03 2009
next sibling parent reply Fractal <d294934 bsnow.net> writes:
Saaa Wrote:

 
 Templates: i dont use templates or mixins. they really confuses me and i 
 think so that they only should be used for "array classes" or something 
 similar.

reading the code more difficult? If it is the first then I don't really get it: you sound like somebody who gets a lot of things. mixins are just code in string form, right?

It is the second. Mixins for me, makes difficult to read the code. but I have to admit that they are useful.
May 03 2009
parent reply "Saaa" <empty needmail.com> writes:
 Templates: i dont use templates or mixins. they really confuses me and 
 i
 think so that they only should be used for "array classes" or something
 similar.

reading the code more difficult? If it is the first then I don't really get it: you sound like somebody who gets a lot of things. mixins are just code in string form, right?

It is the second. Mixins for me, makes difficult to read the code. but I have to admit that they are useful.

Thats what you get with a systems programming language ; ) But I understand where you are coming from. Please ask as many questions as you want. They teach me as well :)
May 03 2009
parent Fractal <d294934 bsnow.net> writes:
Saaa Wrote:

 Thats what you get with a systems programming language ; )
 But I understand where you are coming from.

D is very flexible, everything that i want to do at the time, is possible to do with D. I have only listed things that can be enhanced. I used .NET for some utilities, (nothing big, and with Visual Basic), but it was surprised me the quick development that it provides.
May 03 2009
prev sibling parent reply BCS <none anon.com> writes:
Hello Saaa,

 mixins are just code in string form, right?

No that's "mixin(string)", there is also "mixin Template!();" that plops the template content into its scope.
May 04 2009
parent "Saaa" <empty needmail.com> writes:
Ah, ok thanks.

I should really start reading about those template things :)

 Hello Saaa,

 mixins are just code in string form, right?

No that's "mixin(string)", there is also "mixin Template!();" that plops the template content into its scope.

May 04 2009
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Fractal" <d294934 bsnow.net> wrote in message 
news:gtlihm$tt0$1 digitalmars.com...
 The namespaces: i used them with C++, and the idea of separation between 
 the uses of types, makes a very good layout. Because some namespaces 
 requires more types, always i write each class in separate files. D simply 
 breaks it, making a big amount of lines for imports.

That is easy to work around. Instead of this (which doesn't work in D): ------------------------------------- //File: foo/fooA.d module foo; class fooA {} //File: foo/fooB.d module foo; class fooB {} //File: foo/fooC.d module foo; class fooC {} //File: main.d import foo; void main() {...} ------------------------------------- Do this: ------------------------------------- //File: foo/fooA.d module foo.fooA; class fooA {} //File: foo/fooB.d module foo.fooB; class fooB {} //File: foo/fooC.d module foo.fooC; class fooC {} //File: foo/all.d module foo.all; public import foo.fooA; public import foo.fooB; public import foo.fooC; //File: main.d import foo.all; void main() {...} ------------------------------------- This works fine and does exactly what you want. Also, there are tools (rebuild, bud) that you give *just* the main file, and they automatically find and compile all of files needed. (ie, "rebuild main.d" instead of "cpp main.c fooA.c fooB.c...etc..."). These tools would not be possible if D allowed you to split a module across multiple files.
 Templates: i dont use templates or mixins. they really confuses me and i 
 think so that they only should be used for "array classes" or something 
 similar.

You really should use them. If you don't, you will be writing A LOT of duplicate code.
 Foreach ranged: it cannot be added to D1? it simplies the life, and not 
 breaks any existing code

There are a lot of features that could be added to D1 and people want added to D1. But that's not going to happen. That's what D2 is for. New features go into D2. If you want the new features, you should use D2.
 Tango and Phobos: Tango is good, but the File class makes more problems 
 than it solves. And i dont like the Phobos design, but I really need the 
 XML... just writing other API?

I agree, Tango's file routines are very confusing (or maybe just the documentation for Tango's file routines) and D1's Phobos is a mess. Hopefully this will all improve.
May 03 2009
next sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Nick Sabalausky wrote:
 -------------------------------------
 //File: foo/fooA.d
 module foo.fooA;
 class fooA {}
 
 //File: foo/fooB.d
 module foo.fooB;
 class fooB {}
 
 //File: foo/fooC.d
 module foo.fooC;
 class fooC {}
 
 //File: foo/all.d
 module foo.all;
 public import foo.fooA;
 public import foo.fooB;
 public import foo.fooC;
 
 //File: main.d
 import foo.all;
 void main() {...}
 -------------------------------------
 
 This works fine and does exactly what you want.
 

How well will this work if there is fairly tight coupling between these three classes?
May 03 2009
parent Robert Fraser <fraserofthenight gmail.com> writes:
Ellery Newcomer wrote:
 Nick Sabalausky wrote:
 -------------------------------------
 //File: foo/fooA.d
 module foo.fooA;
 class fooA {}

 //File: foo/fooB.d
 module foo.fooB;
 class fooB {}

 //File: foo/fooC.d
 module foo.fooC;
 class fooC {}

 //File: foo/all.d
 module foo.all;
 public import foo.fooA;
 public import foo.fooB;
 public import foo.fooC;

 //File: main.d
 import foo.all;
 void main() {...}
 -------------------------------------

 This works fine and does exactly what you want.

How well will this work if there is fairly tight coupling between these three classes?

Not well at all :-). Technically, it should work the same as if they were in the same module, but compiler bugs dealing with forward references keep this from happening. I think a while back there was a version of LDC that pretty much fixed forward reference issues, but it introduced a bunch of regressions.
May 03 2009
prev sibling parent reply Liang Du <duliang.21 163.com> writes:
Nick Sabalausky Wrote:

 "Fractal" <d294934 bsnow.net> wrote in message 
 news:gtlihm$tt0$1 digitalmars.com...
 The namespaces: i used them with C++, and the idea of separation between 
 the uses of types, makes a very good layout. Because some namespaces 
 requires more types, always i write each class in separate files. D simply 
 breaks it, making a big amount of lines for imports.

That is easy to work around. Instead of this (which doesn't work in D): ------------------------------------- //File: foo/fooA.d module foo; class fooA {} //File: foo/fooB.d module foo; class fooB {} //File: foo/fooC.d module foo; class fooC {} //File: main.d import foo; void main() {...} ------------------------------------- Do this: ------------------------------------- //File: foo/fooA.d module foo.fooA; class fooA {} //File: foo/fooB.d module foo.fooB; class fooB {} //File: foo/fooC.d module foo.fooC; class fooC {} //File: foo/all.d module foo.all; public import foo.fooA; public import foo.fooB; public import foo.fooC; //File: main.d import foo.all; void main() {...} ------------------------------------- This works fine and does exactly what you want.

The namespaces is better !!!
May 04 2009
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Liang Du wrote:
 Nick Sabalausky Wrote:
 
 "Fractal" <d294934 bsnow.net> wrote in message 
 news:gtlihm$tt0$1 digitalmars.com...
 The namespaces: i used them with C++, and the idea of separation between 
 the uses of types, makes a very good layout. Because some namespaces 
 requires more types, always i write each class in separate files. D simply 
 breaks it, making a big amount of lines for imports.

This works fine and does exactly what you want.

The namespaces is better !!!

That's debatable. The hateful thing about namespaces is that they give you absolutely ZERO clue as to where any particular thing is coming from. If I see "tango.io.device.File", I know exactly where the source for that module is. -- Daniel
May 04 2009
next sibling parent reply Yigal Chripun <yigal100 gmail.com> writes:
Daniel Keep wrote:
 
 Liang Du wrote:
 Nick Sabalausky Wrote:

 "Fractal" <d294934 bsnow.net> wrote in message 
 news:gtlihm$tt0$1 digitalmars.com...
 The namespaces: i used them with C++, and the idea of separation between 
 the uses of types, makes a very good layout. Because some namespaces 
 requires more types, always i write each class in separate files. D simply 
 breaks it, making a big amount of lines for imports.

This works fine and does exactly what you want.


That's debatable. The hateful thing about namespaces is that they give you absolutely ZERO clue as to where any particular thing is coming from. If I see "tango.io.device.File", I know exactly where the source for that module is. -- Daniel

the downside to the current system is when you have one class in a file, the full name of it will be SomeClass.SomeClass instead of just SomeClass. (because of the redundancy of the module decl. in this case) Ideally, I'd want at most one public root entity per file. where entity can be a type (class/struct/union/etc..) _or_ a "module". where a module is just a struct with all methods declared static by default (that exactly the same thing as today). that's also the same thing as the object in scala (if you look at this from an OO perspective). i.e object { ... } also, packaging needs to be enhanced to allow easier management of bigger projects. for example, what if i want to have internal APIs to be used by my packages which are not exposed to the end user? the design should restrict the package layout as little as reasonably possible.
May 04 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Yigal Chripun:
 the downside to the current system is when you have one class in a file, 
 the full name of it will be SomeClass.SomeClass instead of just 
 SomeClass. (because of the redundancy of the module decl. in this case)

Generally if classes or functions are small, you put more than one of them (related ones) in the same module.
 Ideally, I'd want at most one public root entity per file.

That's the Java ideal world. Bye, bearophile
May 04 2009
parent Yigal Chripun <yigal100 gmail.com> writes:
bearophile wrote:
 Yigal Chripun:
 the downside to the current system is when you have one class in a file, 
 the full name of it will be SomeClass.SomeClass instead of just 
 SomeClass. (because of the redundancy of the module decl. in this case)

Generally if classes or functions are small, you put more than one of them (related ones) in the same module.

sure. nothing I said contradicts this. you can have however many constructs in one file. Either make only one of them as public, or put all of them inside a "module" declaration like you do now.
 
 
 Ideally, I'd want at most one public root entity per file.

That's the Java ideal world.

well, the trade-off to consider is: on the one hand - if you go for namespaces like solution you get most flexible design. i.e one file with a bunch of small public classes (for example exceptions) will be exactly the same as many small files with one class in each if in both cases you define all those classes to belong to one namespace. on the other hand - this removes the ability to know in which file a class is defined. I think that in such a case it's a reasonable trade off to have: module exceptions { class A {} class B {} ... } where exceptions is the "root" element of the file. so, exceptions.SomeException can be both a file called exceptions that contains a SomeException class and a exception directory with a file called SomeException that contains that specific class. (also, you can mix both ways, and have only some of the exceptions in separate files). currently, if I have a file with a bunch of classes, and over time the file became too big and I decided to split it to several smaller files, such a split will affect the code because package.module.classA will become package.module.classA.classA after such a split.
 Bye,
 bearophile

another idea, is that if you have: package |\ | exceptions | \ | classA.d | classB.d | exceptions.d classA and classB files contain single classes by the same respective names, and exceptions.d contains a bunch of smaller classes in one file. in this case the compiler could "fuse" together the paths so logically in the code you'll have package.exceptions.[class_name] where class_name is one of classA, classB or any of the classes defined in exceptions.d does that sound reasonable? this is as close as possible I can think of to full namespaces without loosing the ability to find where some code is located in the file system. in this case go to 'package' dir, inside you need to check the exceptions.d file. if desired class isn't in this file you know to go check the 'exceptions' dir, and so forth.
May 04 2009
prev sibling parent reply Fractal <d294934 bsnow.net> writes:
 That's debatable.  The hateful thing about namespaces is that they give
 you absolutely ZERO clue as to where any particular thing is coming from.
 
 If I see "tango.io.device.File", I know exactly where the source for
 that module is.
 
   -- Daniel

Yes it is true. But the thing is not "where is it". The thing that i want to remark is "what long". If you use a namespace, you can write many big classes in separate files without problem, and also, with the same namespace. (and also allowing separate a multiplatform class in different files, for each one). With modules you are limited in a single file. And it will grow potentially with multiplatform code, and makes hard to find a error or line... Added to it, the amout of version statements. Also Namespaces can use upper case characters... documentation indicates that package and module names should be written all in lower case. A good point for modules is the permisson to access private or protected members of types declared in the same module or package, without the "friend" keyword anywhere. In namespaces, it can be done by sharing access to all namespace types. Really module, packages, and namespaces are the same thing. The unique thing that i want, is the possibility of use many files as one (for modules)
May 04 2009
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Fractal:
 Really module, packages, and namespaces are the same thing.

Not really :-) There are semantic differences. Bye, bearophile
May 04 2009
prev sibling next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Fractal wrote:
 That's debatable.  The hateful thing about namespaces is that they give
 you absolutely ZERO clue as to where any particular thing is coming from.

 If I see "tango.io.device.File", I know exactly where the source for
 that module is.

   -- Daniel

Yes it is true. But the thing is not "where is it". The thing that i want to remark is "what long". If you use a namespace, you can write many big classes in separate files without problem, and also, with the same namespace. (and also allowing separate a multiplatform class in different files, for each one).

public import and mixin.
 With modules you are limited in a single file. And it will grow potentially
with multiplatform code, and makes hard to find a error or line...
 Added to it, the amout of version statements.

public import and mixin.
 Also Namespaces can use upper case characters... documentation indicates that
package and module names should be written all in lower case.

Oh what rubbish. You can use whatever case you please.
 A good point for modules is the permisson to access private or protected
members of types declared in the same module or package, without the "friend"
keyword anywhere.
 In namespaces, it can be done by sharing access to all namespace types.
 
 Really module, packages, and namespaces are the same thing. The unique thing
that i want, is the possibility of use many files as one (for modules)

But you see, this would break bud, rebuild, etc. I'm pretty sure that if you somehow convinced Walter to do this, you would have a lot of VERY angry people coming after you for completely breaking their build tools. I know I would be. I'm not going back to Make! You can't make me! Viva la laziness! -- Daniel
May 04 2009
parent Robert Fraser <fraserofthenight gmail.com> writes:
Daniel Keep wrote:
 Also Namespaces can use upper case characters... documentation indicates that
package and module names should be written all in lower case.

Oh what rubbish. You can use whatever case you please.

On Windows (actually NTFS, I think), you can't two packages/modules that differ only in case. But if you have namespaces "XML", "Xml" and "xml", you probably have some bigger design issues.
May 04 2009
prev sibling parent reply Christopher Wright <dhasenan gmail.com> writes:
Fractal wrote:
 That's debatable.  The hateful thing about namespaces is that they give
 you absolutely ZERO clue as to where any particular thing is coming from.

 If I see "tango.io.device.File", I know exactly where the source for
 that module is.

   -- Daniel

Yes it is true. But the thing is not "where is it". The thing that i want to remark is "what long". If you use a namespace, you can write many big classes in separate files without problem, and also, with the same namespace. (and also allowing separate a multiplatform class in different files, for each one). With modules you are limited in a single file. And it will grow potentially with multiplatform code, and makes hard to find a error or line... Added to it, the amout of version statements. Also Namespaces can use upper case characters... documentation indicates that package and module names should be written all in lower case. A good point for modules is the permisson to access private or protected members of types declared in the same module or package, without the "friend" keyword anywhere. In namespaces, it can be done by sharing access to all namespace types. Really module, packages, and namespaces are the same thing. The unique thing that i want, is the possibility of use many files as one (for modules)

Modules are compilation units. This makes them different from namespaces. Packages are for the compiler to find source code. Namespaces are for humans to find source code. These have sufficient overlap that they have been unified. For modules to do what you want, a module cannot be the unit of compilation. What then will be the unit of compilation? And why is this feature important enough to merit the change?
May 04 2009
parent reply Yigal Chripun <yigal100 gmail.com> writes:
Christopher Wright wrote:
 Fractal wrote:
 That's debatable.  The hateful thing about namespaces is that they give
 you absolutely ZERO clue as to where any particular thing is coming 
 from.

 If I see "tango.io.device.File", I know exactly where the source for
 that module is.

   -- Daniel

Yes it is true. But the thing is not "where is it". The thing that i want to remark is "what long". If you use a namespace, you can write many big classes in separate files without problem, and also, with the same namespace. (and also allowing separate a multiplatform class in different files, for each one). With modules you are limited in a single file. And it will grow potentially with multiplatform code, and makes hard to find a error or line... Added to it, the amout of version statements. Also Namespaces can use upper case characters... documentation indicates that package and module names should be written all in lower case. A good point for modules is the permisson to access private or protected members of types declared in the same module or package, without the "friend" keyword anywhere. In namespaces, it can be done by sharing access to all namespace types. Really module, packages, and namespaces are the same thing. The unique thing that i want, is the possibility of use many files as one (for modules)

Modules are compilation units. This makes them different from namespaces. Packages are for the compiler to find source code. Namespaces are for humans to find source code. These have sufficient overlap that they have been unified. For modules to do what you want, a module cannot be the unit of compilation. What then will be the unit of compilation? And why is this feature important enough to merit the change?

in my opinion a more flexible design is: namespaces can map both to packages/dirs (as it is now) _and_ files for added flexibility, and compilation units will be files. I don't think splitting one class/struct/etc to several files is good design, there are better ways to acomplish this, like defining platform specific behaviors as mixins: template foo_win32 {} template foo_linux {} and in the class mix-in the appropriate mixin. *but*, I do think that splitting one file that got too big over time or uniting a bunch of small files into one should be possible.
May 04 2009
parent reply Georg Wrede <georg.wrede iki.fi> writes:
Yigal Chripun wrote:
 *but*, I do think that splitting one file that got too big over time or 
 uniting a bunch of small files into one should be possible.

This would be especially good for us. D is mainly developed by individuals, and there projects tend to grow organically -- as opposed to the software industry that uses UML and other modeling tools, where the entire gamut of classes is known before coding starts. So, yes, it should be possible to reorganise code between files without having to touch the code that uses them.
May 05 2009
parent reply Christopher Wright <dhasenan gmail.com> writes:
Georg Wrede wrote:
 Yigal Chripun wrote:
 *but*, I do think that splitting one file that got too big over time 
 or uniting a bunch of small files into one should be possible.

This would be especially good for us. D is mainly developed by individuals, and there projects tend to grow organically -- as opposed to the software industry that uses UML and other modeling tools, where the entire gamut of classes is known before coding starts. So, yes, it should be possible to reorganise code between files without having to touch the code that uses them.

It *is* possible, by use of public imports. Are you splitting one file into many? Public import the other modules. Are you merging many files into one? Leave the other files with just a public import of the merged file.
May 05 2009
parent reply grauzone <none example.net> writes:
Christopher Wright wrote:
 Georg Wrede wrote:
 Yigal Chripun wrote:
 *but*, I do think that splitting one file that got too big over time 
 or uniting a bunch of small files into one should be possible.

This would be especially good for us. D is mainly developed by individuals, and there projects tend to grow organically -- as opposed to the software industry that uses UML and other modeling tools, where the entire gamut of classes is known before coding starts. So, yes, it should be possible to reorganise code between files without having to touch the code that uses them.

It *is* possible, by use of public imports. Are you splitting one file into many? Public import the other modules. Are you merging many files into one? Leave the other files with just a public import of the merged file.

Nice story. In reality you face all kinds of problems: like circular dependency bugs, public/private/package are not fine enough (friend modules or a fixed package attribute would be nice), and you still can't split the implementation of a class across several files. But yes, I guess I could implement a CTFE driven preprocessor using import(), which would solve all problems. And then you switch to another language, because all the bugs and kludges just isn't it worth.
May 05 2009
parent reply Christopher Wright <dhasenan gmail.com> writes:
grauzone wrote:
 Christopher Wright wrote:
 It *is* possible, by use of public imports.

 Are you splitting one file into many? Public import the other modules.

 Are you merging many files into one? Leave the other files with just a 
 public import of the merged file.

Nice story. In reality you face all kinds of problems: like circular dependency bugs, public/private/package are not fine enough (friend modules or a fixed package attribute would be nice), and you still can't split the implementation of a class across several files. But yes, I guess I could implement a CTFE driven preprocessor using import(), which would solve all problems. And then you switch to another language, because all the bugs and kludges just isn't it worth.

Then: it *should* be possible, but compiler bugs sometimes prevent it, and there is an old issue with circular imports with static constructors that you will often run into, and you might want fine-grained access control that you won't always have if you split a file into multiple subpackages as well as multiple files. However, I would like to see use cases for putting one module in multiple files, and for putting one class in multiple files. The only use case that springs to mind for one class in several files is when part of the class is generated by a tool, though you can handle that with inheritance instead. I see no use case for having one module in multiple files, though -- the only benefit would be private access to things defined in other files. I've never been big on making stuff private, though.
May 05 2009
next sibling parent grauzone <none example.net> writes:
I don't want to split a big class into several smaller classes, just to 
be able to distribute it across several source files.

Actually, the D module system makes me to implement several "aspects" of 
something as several classes. Just to be able to put the implementation 
into several files. Of course, you could argue splitting it into smaller 
classes is cleaner (and forces you to do a cleaner design etc.), but in 
reality, this just causes code bloat. You need additional code to 
interface with the other classes, ensure encapsulation, etc. But putting 
it into a single class is so much simpler, and in the end KISS > complexity.

Oh, how much simpler was programming, when you'd just define global 
variables and global functions in several source files? At least that's 
what I think when I look at such "simple" code. (My opinion usually 
changes if I have to fix bugs in it.)

Open types could help to make putting different aspects of a class into 
different files. You know, just adding new member variables or virtual 
functions to a class from "outside". Oh, and you can do this for free in 
dynamic languages. I think they call it "monkey patching", but it has 
the following disadvantage: all the added members live all in the same 
namespace, regardless of what source modules did add them to the object.

By the way, Aspect oriented programming languages won't solve this. 
Usually they are clusterfucks which just add complexity on top of 
already complex languages. A good example is AspectJ.
May 06 2009
prev sibling parent Christopher Wright <dhasenan gmail.com> writes:
Denis Koroskin wrote:
 On Wed, 06 May 2009 02:36:21 +0400, Christopher Wright 
 <dhasenan gmail.com> wrote:
 
 I see no use case for having one module in multiple files, though -- 
 the only benefit would be private access to things defined in other 
 files. I've never been big on making stuff private, though.

There is a use-case. Imagine you want to define a Thread class. It has a common interface, but its implementation is heavily platform-specific, and sometimes involves manual assembly. Putting all the implementation into one file would make it very big, source code a complete mess and following it would be very hard. Instead, you may wish to define its interface in Thread.d(i), yet put its implementation in multiple files: Thread_win32.d, Thread_posix.d etc.

If that's the main concern, public import works fine, along with, optionally, an interface. However, if there's a lot of shared code as well as a lot of platform-specific code, that's not very fun at all. Your options are to define a base class with the common code (yech) or munge all the platform-specific code together.
May 06 2009
prev sibling next sibling parent BCS <none anon.com> writes:
Hello Fractal,

 Templates: i dont use templates or mixins. they really confuses me and
 i think so that they only should be used for "array classes" or
 something similar.

I'm biased (as I love playing with them) but templates can be used for a LOT more than that. Most of the time the end user doesn't need to understand how it works, just how to use it and that generally isn't hard to figure out.
May 04 2009
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Tue, 05 May 2009 09:50:24 +0400, Yigal Chripun <yigal100 gmail.com> wrote:

 bearophile wrote:
 Yigal Chripun:
 the downside to the current system is when you have one class in a  
 file, the full name of it will be SomeClass.SomeClass instead of just  
 SomeClass. (because of the redundancy of the module decl. in this case)

them (related ones) in the same module.

sure. nothing I said contradicts this. you can have however many constructs in one file. Either make only one of them as public, or put all of them inside a "module" declaration like you do now.
 Ideally, I'd want at most one public root entity per file.


well, the trade-off to consider is: on the one hand - if you go for namespaces like solution you get most flexible design. i.e one file with a bunch of small public classes (for example exceptions) will be exactly the same as many small files with one class in each if in both cases you define all those classes to belong to one namespace. on the other hand - this removes the ability to know in which file a class is defined. I think that in such a case it's a reasonable trade off to have: module exceptions { class A {} class B {} ... } where exceptions is the "root" element of the file. so, exceptions.SomeException can be both a file called exceptions that contains a SomeException class and a exception directory with a file called SomeException that contains that specific class. (also, you can mix both ways, and have only some of the exceptions in separate files). currently, if I have a file with a bunch of classes, and over time the file became too big and I decided to split it to several smaller files, such a split will affect the code because package.module.classA will become package.module.classA.classA after such a split.
 Bye,
 bearophile

another idea, is that if you have: package |\ | exceptions | \ | classA.d | classB.d | exceptions.d classA and classB files contain single classes by the same respective names, and exceptions.d contains a bunch of smaller classes in one file. in this case the compiler could "fuse" together the paths so logically in the code you'll have package.exceptions.[class_name] where class_name is one of classA, classB or any of the classes defined in exceptions.d does that sound reasonable? this is as close as possible I can think of to full namespaces without loosing the ability to find where some code is located in the file system. in this case go to 'package' dir, inside you need to check the exceptions.d file. if desired class isn't in this file you know to go check the 'exceptions' dir, and so forth.

I believe this is reasonable, but I don't think we will convince Walter for a change. Either way, this idea needs to be out into bugzilla, or it will be lost.
May 04 2009
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Wed, 06 May 2009 02:36:21 +0400, Christopher Wright <dhasenan gmail.com>
wrote:

 I see no use case for having one module in multiple files, though -- the  
 only benefit would be private access to things defined in other files.  
 I've never been big on making stuff private, though.

There is a use-case. Imagine you want to define a Thread class. It has a common interface, but its implementation is heavily platform-specific, and sometimes involves manual assembly. Putting all the implementation into one file would make it very big, source code a complete mess and following it would be very hard. Instead, you may wish to define its interface in Thread.d(i), yet put its implementation in multiple files: Thread_win32.d, Thread_posix.d etc. I use the same trick to unify socket API. For some reason, every platform introduce small API changes. Some call a function closesocket, others - socketclose etc. That's why I have SocketApi.di which contains the following declarations: SocketDescriptor socketCreate(SocketAddressFamily addressFamily, SocketType type, SocketProtocol protocol); SocketDescriptor socketAccept(SocketDescriptor listenSd); bool socketClose(SocketDescriptor sd); bool socketSetupListen(SocketDescriptor sd, uint maxQueue = 0); bool socketSetupNonBlocking(SocketDescriptor sd, bool nonBlocking); .... Each platform implements these functions a bit differently. Their implementation is stored in SocketApi_win32.d, SocketApi_linux.d etc. And, yes, all of them have "module SocketApi;" on top of the file.
May 05 2009
prev sibling parent Jesse Phillips <jessekphillips gmail.com> writes:
On Mon, 04 May 2009 18:23:50 -0700, Robert Fraser wrote:

 Daniel Keep wrote:
 Also Namespaces can use upper case characters... documentation
 indicates that package and module names should be written all in lower
 case.

Oh what rubbish. You can use whatever case you please.

On Windows (actually NTFS, I think), you can't two packages/modules that differ only in case. But if you have namespaces "XML", "Xml" and "xml", you probably have some bigger design issues.

You can actually, just Windows can not distinguish between the two if you do. The point was that you are not restricted to only using lowercase, it can be uppercase. And in the case of windows, it can't even tell the difference anyway (dmd might enforce it).
May 09 2009