Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
August 28, 2001 initial reaction to D | ||||
---|---|---|---|---|
| ||||
A friend asked me what I thought of D. Here is my initial reaction. It is *not* based on a careful reading of all available material -- I've only read the introduction and FAQ. Many nice refinements to c/c++. I'll concentrate on what I don't like or have concerns about. - in switch, cases fall through. Very inhumane (my term for bad human engineering). - printf exists -- a good type system would not allow it - requiring heap allocation of objects is over-specified -- ought to be an implementation decision. Besides, it is useful to support boxed and unboxed objects. Clearly unboxed objects might have additional restrictions. - C declaration syntax is "inside out" and unnatural -- it should have been ditched - Pascal subranges are powerful and should be supported. Specifying size of integer types any other way is crude. - Some C source files provide more than one interface. This ability is probably lost in D. - There is no single optimal string abstraction. But D must have chosen one. I don't know which one was chosen, but there is a great chance that I'd not like it. - more expressive declarations about parameters would be good. For example, it would be nice to know whether a parameter ever has its address preserved beyond the call. Perhaps this can be derived -- after all, the declaration of the function is automatically computed from the definition. - With no separate .h files, make is likely to do too much recompiling For example consider a file a.d that uses things provided by b.d. The make dependency would be expressed in a way that requires a.d to be recompiled whenever b.d is changed, even if b.d's interface isn't changed. In c, this is handled by separating the .h and .c. If make were smarter, an interface description could be automatically generated for b.d, and only if it differed from the previous one would recompilation of a.d be triggered. I see this as a weakness of make, but d is claimed to be suitable for make. - how do circular dependencies between files get sorted out? If a.d needs b.d and b.d needs a.d, there appears to be a chicken-and-egg problem. In C, this must be sorted out by the programmer when crafting .h and #includes. - How does separate compilation work? In C, .h files are an important part of this. - The concept of "uniform referents" is not reflected in the language design. There is no good reason for function call to use different notation from subscripting and there are good reasons for them to be the same. C followed B where they had to be different because the language was typeless. - the intro seems to imply that for (;;) is gone. Why? - there are a couple of features of Dijkstra's notation from "A discipline of programming" that would be nice + a static way of avoiding/detecting uninitialized variables + (related, interestingly enough) a more general and convenient set of array operations. They only become possible because arrays are now first class types (with bounds). Perhaps these arrays become pleasant for holding strings. In C, arrays are more of a memory allocation technique than a data structure. |
August 28, 2001 Re: initial reaction to D | ||||
---|---|---|---|---|
| ||||
Posted in reply to D. Hugh Redelmeier | Well, you really should read more of the language documentation as some of your assumptions about the language are unfounded. On the other hand you do have a few good points too. > - in switch, cases fall through. Very inhumane (my term for bad human > engineering). The reason switches fall through is because that is the behaviour that switches have in C. The author is concerned that if switch is included in the language with only small changes, it would be difficult to detect bugs from old software related to those changes. Personally, I agree though - not falling through should be the default condition. > > - printf exists -- a good type system would not allow it I wonder if a typesafe printf is feasible??? Like have compile-time checking of types printf("%d - %d",1,3.0) // Runtime detected error - parameter 2 needs casting and perhapse it could be passed objects (instances of classes) whch implement some Printable interface ( have a ToString method). Like: PrintableClass MyObject = new MyObject(); printf("ToString() = %o\n",MyObject); Just some ideas. > - Pascal subranges are powerful and should be supported. Specifying > size of integer types any other way is crude. I sort of agree, but doesn't that incur some sort of performance hit? > - There is no single optimal string abstraction. But D must have > chosen one. I don't know which one was chosen, but there is a > great chance that I'd not like it. The string in D is a character array, just like C. The difference is that static arrays in D have an operator that returns the size of the array. > > - With no separate .h files, make is likely to do too much recompiling > For example consider a file a.d that uses things provided by b.d. > The make dependency would be expressed in a way that requires a.d to > be recompiled whenever b.d is changed, even if b.d's interface isn't > changed. In c, this is handled by separating the .h and .c. If > make were smarter, an interface description could be automatically > generated for b.d, and only if it differed from the previous one > would recompilation of a.d be triggered. I see this as a weakness > of make, but d is claimed to be suitable for make. > - how do circular dependencies between files get sorted out? If a.d > needs b.d and b.d needs a.d, there appears to be a chicken-and-egg > problem. In C, this must be sorted out by the programmer when > crafting .h and #includes. > > - How does separate compilation work? In C, .h files are an important > part of this. Although they don't actually come out and say it in the FAQ or documentation, header files are being supported, although they are not required. The include statement and text-based inclusion are not being used in D. In fact, the preprocessor will not be used at all. To use a file, import it with the import directive. When a D file is first compiled, a symbol table is formed and that is what gets imported rather than having the text from the header file be inserted into the source verbatum. Anyway, that's what I have been able to piece together from the documentation and some conversations here in the newsgroup. Thanks for your opinions though! |
August 28, 2001 Re: initial reaction to D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Erik Rounds | Erik Rounds wrote: > I wonder if a typesafe printf is feasible??? We've been discussing that in the thread "typesafe printf". There are at least two reasonable alternatives out there that don't require runtime type identification of the arguments or using wrappers on fundamental types. > > - There is no single optimal string abstraction. But D must have > > chosen one. I don't know which one was chosen, but there is a > > great chance that I'd not like it. > > The string in D is a character array, just like C. The difference is that static arrays in D have an operator that returns the size of the array. Also remember that they are not null terminated (don't need to be, since they have a size parameter). > > - With no separate .h files, make is likely to do too much recompiling > > For example consider a file a.d that uses things provided by b.d. > > The make dependency would be expressed in a way that requires a.d to > > be recompiled whenever b.d is changed, even if b.d's interface isn't > > changed. In c, this is handled by separating the .h and .c. If > > make were smarter, an interface description could be automatically > > generated for b.d, and only if it differed from the previous one > > would recompilation of a.d be triggered. I see this as a weakness > > of make, but d is claimed to be suitable for make. AS I UNDERSTAND IT: Several D modules (.d files) are processed at once to create a single .o file or executable. If you want to declare an interface to import but you don't want to give the implementation in that object file, create an interface module that only declares the functions, not defines them. foo.d // contains all code for foo library.int.d // contains interface to library library.d // contains code for library. foo.d imports library.int.d; together they are built into foo.o library.d builds into library.o foo.o and library.o are linked together to produce the foo executable. > > - how do circular dependencies between files get sorted out? If a.d > > needs b.d and b.d needs a.d, there appears to be a chicken-and-egg > > problem. In C, this must be sorted out by the programmer when > > crafting .h and #includes. Like in Java, D processes all currently available modules in one pass. Order of declaration is not important, so forward declarations are never used. struct Foo { Bar *bar; // legal...D looks ahead (or into the other module) and sees that Bar will be declared later }; struct Bar { Foo *foo; }; Thus, there are no C-style header dependencies. |
August 29, 2001 Re: initial reaction to D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russ Lewis | Russ Lewis wrote in message <3B8BD2E1.CA1850D9@deming-os.org>... >Also remember that they are not null terminated (don't need to be, since they >have a size parameter). I was initially reluctant to drop the null termination, but I since discovered that so many things just get nicer without the null. >Several D modules (.d files) are processed at once to create a single .o file or >executable. If you want to declare an interface to import but you don't want to >give the implementation in that object file, create an interface module that >only declares the functions, not defines them. > >foo.d // contains all code for foo >library.int.d // contains interface to library >library.d // contains code for library. > >foo.d imports library.int.d; together they are built into foo.o >library.d builds into library.o >foo.o and library.o are linked together to produce the foo executable. I haven't yet decided if interface files should have a different extension. >Like in Java, D processes all currently available modules in one pass. Order of >declaration is not important, so forward declarations are never used. Yes. >Thus, there are no C-style header dependencies. Yes. |
August 30, 2001 Re: initial reaction to D | ||||
---|---|---|---|---|
| ||||
Posted in reply to D. Hugh Redelmeier | > > - Pascal subranges are powerful and should be supported. Specifying > size of integer types any other way is crude. > I have done a lot of pascal (Delphi) and I can't say that I use them at all. Enums (ans sets of enuyms) are nice though. > > - There is no single optimal string abstraction. But D must have > chosen one. I don't know which one was chosen, but there is a > great chance that I'd not like it. > Or go the C/C++ route, don't provide any standard one, and frustrate everyone with incompatibilites? > - how do circular dependencies between files get sorted out? If a.d > needs b.d and b.d needs a.d, there appears to be a chicken-and-egg > problem. In C, this must be sorted out by the programmer when > crafting .h and #includes. > The java compiler handles this with no fuss at all. But then Java allows forward refs as long as they are resolved eventually. Anthony |
Copyright © 1999-2021 by the D Language Foundation