| 1 |
Ddoc |
|---|
| 2 |
|
|---|
| 3 |
$(D_S $(TITLE), |
|---|
| 4 |
|
|---|
| 5 |
$(P The same questions keep cropping up, so the obvious thing to do is |
|---|
| 6 |
prepare a FAQ.) |
|---|
| 7 |
|
|---|
| 8 |
$(P $(LINK2 http://www.digitalmars.com/d/1.0/faq.html, D 1.0 FAQ)) |
|---|
| 9 |
$(P $(LINK2 http://www.digitalmars.com/faq.html, C++ FAQ)) |
|---|
| 10 |
|
|---|
| 11 |
<h2>D 2.0 FAQ</h2> |
|---|
| 12 |
|
|---|
| 13 |
$(UL |
|---|
| 14 |
$(LI $(LINK2 features2.html, What's the difference between D 2.0 and D 1.0?)) |
|---|
| 15 |
|
|---|
| 16 |
$(LI Where is my simple language?) |
|---|
| 17 |
|
|---|
| 18 |
$(LI $(LINK2 cpp0x.html, What's D 2.0's answer to C++0x's proposed new features?)) |
|---|
| 19 |
|
|---|
| 20 |
$(LI What other cool features are in the plans for D 2.0?) |
|---|
| 21 |
|
|---|
| 22 |
$(LI I suggested a great feature. Why was the suggestion ignored?) |
|---|
| 23 |
|
|---|
| 24 |
$(LI Why const and immutable?) |
|---|
| 25 |
|
|---|
| 26 |
$(LI Why the $(I names) const and immutable?) |
|---|
| 27 |
|
|---|
| 28 |
$(LI How exactly is immutable related to multicores?) |
|---|
| 29 |
|
|---|
| 30 |
$(LI Ok, I'm fine with immutable for safe data sharing among threads. But why do we need the uninformative const?) |
|---|
| 31 |
|
|---|
| 32 |
$(LI Why are immutable strings favored in D 2.0?) |
|---|
| 33 |
|
|---|
| 34 |
$(LI I want to contribute to D 2.0. How can I effect that?) |
|---|
| 35 |
|
|---|
| 36 |
$(ITEMR case_range, Why doesn't the case range statement |
|---|
| 37 |
use the $(TT case X..Y:) syntax?) |
|---|
| 38 |
|
|---|
| 39 |
$(ITEMR shared_guarantees, What guarantees is shared supposed to provide?) |
|---|
| 40 |
|
|---|
| 41 |
$(ITEMR shared_synchronized, What does shared have to do with synchronization?) |
|---|
| 42 |
|
|---|
| 43 |
$(ITEMR shared_memory_barriers, What does shared have to do with memory barriers?) |
|---|
| 44 |
|
|---|
| 45 |
$(ITEMR casting_to_shared, What are the semantics of casting FROM unshared TO shared?) |
|---|
| 46 |
|
|---|
| 47 |
$(ITEMR casting_from_shared, What are the semantics of casting FROM shared TO unshared?) |
|---|
| 48 |
|
|---|
| 49 |
) |
|---|
| 50 |
|
|---|
| 51 |
<h2>General D FAQ</h2> |
|---|
| 52 |
|
|---|
| 53 |
$(UL |
|---|
| 54 |
|
|---|
| 55 |
$(LI $(LINK2 http://www.wikiservice.at/wiki4d/wiki.cgi?FaqRoadmap, The D wiki FAQ page) |
|---|
| 56 |
with many more questions answered) |
|---|
| 57 |
$(LI $(LINK2 comparison.html, What does D have that C++ doesn't?)) |
|---|
| 58 |
$(ITEMR q1, Why the name D?) |
|---|
| 59 |
$(LI $(LINK2 http://www.digitalmars.com/d/download.html, Where can I get a D compiler?)) |
|---|
| 60 |
$(ITEMR q1_2, Is there linux port of D?) |
|---|
| 61 |
$(ITEMR gdc, Is there a GNU version of D?) |
|---|
| 62 |
$(ITEMR backend, How do I write my own D compiler for CPU X?) |
|---|
| 63 |
$(ITEMR gui, Where can I get a GUI library for D?) |
|---|
| 64 |
$(ITEMR ide, Where can I get an IDE for D?) |
|---|
| 65 |
$(ITEMR q2, What about templates?) |
|---|
| 66 |
$(ITEMR q3, Why emphasize implementation ease?) |
|---|
| 67 |
$(ITEMR q4, Why is [expletive deleted] printf left in?) |
|---|
| 68 |
$(ITEMR q5, Will D be open source?) |
|---|
| 69 |
$(ITEMR q6, Why fall through on switch statements?) |
|---|
| 70 |
$(ITEMR q7, Why should I use D instead of Java?) |
|---|
| 71 |
$(ITEMR q7_2, Doesn't C++ support strings, etc. with STL?) |
|---|
| 72 |
$(ITEMR q7_3, Can't garbage collection be done in C++ with an add-on library?) |
|---|
| 73 |
$(ITEMR q7_4, Can't unit testing be done in C++ with an add-on library?) |
|---|
| 74 |
$(ITEMR q8, Why have an asm statement in a portable language?) |
|---|
| 75 |
$(ITEMR real, What is the point of 80 bit reals?) |
|---|
| 76 |
$(ITEMR anonymous, How do I do anonymous struct/unions in D?) |
|---|
| 77 |
$(ITEMR printf, How do I get printf() to work with strings?) |
|---|
| 78 |
$(ITEMR nan, Why are floating point values default initialized to NaN rather than 0?) |
|---|
| 79 |
$(ITEMR assignmentoverloading, Why is overloading of the assignment operator not supported?) |
|---|
| 80 |
$(ITEMR keys, The $(SINGLEQUOTE ~) is not on my keyboard?) |
|---|
| 81 |
$(ITEMR omf, Can I link in C object files created with another compiler?) |
|---|
| 82 |
$(ITEMR regexp_literals, Why not support regular expression literals |
|---|
| 83 |
with the /foo/g syntax?) |
|---|
| 84 |
$(ITEMR dogfood, Why is the D front end written in C++ rather than D?) |
|---|
| 85 |
$(ITEMR cpp_to_D, Why aren't all Digital Mars programs translated to D?) |
|---|
| 86 |
$(ITEMR foreach, When should I use a foreach loop rather than a for?) |
|---|
| 87 |
$(ITEMR cpp_interface, Why doesn't D have an interface to C++ as well as C?) |
|---|
| 88 |
$(ITEMR reference-counting, Why doesn't D use reference counting for garbage collection?) |
|---|
| 89 |
$(ITEMR gc_1, Isn't garbage collection slow and non-deterministic?) |
|---|
| 90 |
$(ITEMR pure, Can't a sufficiently smart compiler figure out that a function is pure automatically?) |
|---|
| 91 |
) |
|---|
| 92 |
|
|---|
| 93 |
$(ITEM case_range, Why doesn't the case range statement |
|---|
| 94 |
use the $(TT case X..Y:) syntax?) |
|---|
| 95 |
|
|---|
| 96 |
$(P See the $(LINK2 statement.html#CaseRangeStatement, case range statement).) |
|---|
| 97 |
|
|---|
| 98 |
$(P The usages of .. would then be: |
|---|
| 99 |
$(OL |
|---|
| 100 |
$(LI $(TT case X..Y:)) |
|---|
| 101 |
$(LI $(TT foreach(e; X..Y))) |
|---|
| 102 |
$(LI $(TT array[X..Y])) |
|---|
| 103 |
) |
|---|
| 104 |
Case (1) has a VERY DIFFERENT meaning from (2) and (3). |
|---|
| 105 |
(1) is inclusive of Y, and (2) and (3) are exclusive of Y. |
|---|
| 106 |
Having a very different meaning means it should have a distinctly different syntax. |
|---|
| 107 |
) |
|---|
| 108 |
|
|---|
| 109 |
$(ITEM shared_guarantees, What guarantees is shared supposed to provide?) |
|---|
| 110 |
|
|---|
| 111 |
$(P Shared means that multiple threads can access the data. The guarantee is that if it is |
|---|
| 112 |
not shared, and not immutable, that only the current thread can see it. |
|---|
| 113 |
) |
|---|
| 114 |
|
|---|
| 115 |
$(ITEM shared_synchronized, What does shared have to do with synchronization?) |
|---|
| 116 |
|
|---|
| 117 |
$(P Only shared data can be synchronized. It makes no sense to synchronize thread local |
|---|
| 118 |
data. |
|---|
| 119 |
) |
|---|
| 120 |
|
|---|
| 121 |
$(ITEM shared_memory_barriers, What does shared have to do with memory barriers?) |
|---|
| 122 |
|
|---|
| 123 |
$(P Reading/writing shared data emits memory barriers to ensure sequential consistency (not |
|---|
| 124 |
implemented). |
|---|
| 125 |
) |
|---|
| 126 |
|
|---|
| 127 |
$(ITEM casting_to_shared, What are the semantics of casting FROM unshared TO shared?) |
|---|
| 128 |
|
|---|
| 129 |
$(P Make sure there are no other unshared references to that same data. |
|---|
| 130 |
) |
|---|
| 131 |
|
|---|
| 132 |
$(ITEM casting_from_shared, What are the semantics of casting FROM shared TO unshared?) |
|---|
| 133 |
|
|---|
| 134 |
$(P Make sure there are no other shared references to that same data. |
|---|
| 135 |
) |
|---|
| 136 |
|
|---|
| 137 |
$(ITEM q1, Why the name D?) |
|---|
| 138 |
|
|---|
| 139 |
$(P The original name was the Mars Programming Language. But my friends |
|---|
| 140 |
kept calling it D, and I found myself starting to call it D. |
|---|
| 141 |
The idea of D being a successor to C goes back at least as far as 1988, |
|---|
| 142 |
as in this |
|---|
| 143 |
$(LINK2 http://groups.google.com/groups?q=%22d+programming+language&hl=en&lr=&ie=UTF8&oe=UTF8&selm=12055%40brl-adm.ARPA&rnum=1, thread). |
|---|
| 144 |
) |
|---|
| 145 |
|
|---|
| 146 |
$(ITEM q1_2, Is there a linux port of D?) |
|---|
| 147 |
|
|---|
| 148 |
$(P Yes, the D compiler includes a $(LINK2 dmd-linux.html, linux version). |
|---|
| 149 |
) |
|---|
| 150 |
|
|---|
| 151 |
$(ITEM gdc, Is there a GNU version of D?) |
|---|
| 152 |
|
|---|
| 153 |
$(P Yes, |
|---|
| 154 |
$(LINK2 http://bitbucket.org/goshawk/gdc/wiki/Home, gdc - the D frontend with GCC). |
|---|
| 155 |
) |
|---|
| 156 |
|
|---|
| 157 |
$(ITEM backend, How do I write my own D compiler for CPU X?) |
|---|
| 158 |
|
|---|
| 159 |
$(P Burton Radons has written a |
|---|
| 160 |
$(LINK2 http://www.opend.org/dli/DLinux.html, back end). |
|---|
| 161 |
You can use as a guide. |
|---|
| 162 |
) |
|---|
| 163 |
|
|---|
| 164 |
$(ITEM gui, Where can I get a GUI library for D?) |
|---|
| 165 |
|
|---|
| 166 |
$(P Since D can call C functions, any GUI library with a C interface is |
|---|
| 167 |
accessible from D. Various D GUI libraries and ports can be found at |
|---|
| 168 |
<a href="http://www.prowiki.org/wiki4d/wiki.cgi?AvailableGuiLibraries">AvailableGuiLibraries</a>. |
|---|
| 169 |
) |
|---|
| 170 |
|
|---|
| 171 |
$(ITEM ide, Where can I get an IDE for D?) |
|---|
| 172 |
|
|---|
| 173 |
$(P Try |
|---|
| 174 |
$(LINK2 http://www.dsource.org/projects/elephant/, Elephant), |
|---|
| 175 |
$(LINK2 http://www.dsource.org/projects/poseidon/, Poseidon), |
|---|
| 176 |
or $(LINK2 http://www.dsource.org/projects/leds/, LEDS). |
|---|
| 177 |
) |
|---|
| 178 |
|
|---|
| 179 |
$(ITEM q2, What about templates?) |
|---|
| 180 |
|
|---|
| 181 |
$(P D now supports advanced templates. |
|---|
| 182 |
) |
|---|
| 183 |
|
|---|
| 184 |
$(ITEM q3, Why emphasize implementation ease?) |
|---|
| 185 |
|
|---|
| 186 |
$(P Isn't ease of use for the user of the language more important? Yes, |
|---|
| 187 |
it is. |
|---|
| 188 |
But a vaporware language is useless to everyone. The easier a language |
|---|
| 189 |
is to implement, the more robust implementations there will be. In C's |
|---|
| 190 |
heyday, there were 30 different commercial C compilers for the IBM PC. |
|---|
| 191 |
Not many made the transition to C++. In looking at |
|---|
| 192 |
the C++ compilers on the market today, how many years of development |
|---|
| 193 |
went into each? At least 10 years? Programmers waited years |
|---|
| 194 |
for the various pieces of C++ to get implemented after they were |
|---|
| 195 |
specified. |
|---|
| 196 |
If C++ was not so enormously popular, it's doubtful that very complex |
|---|
| 197 |
features |
|---|
| 198 |
like multiple inheritance, templates, etc., would ever have been |
|---|
| 199 |
implemented. |
|---|
| 200 |
) |
|---|
| 201 |
|
|---|
| 202 |
$(P I suggest that if a language is easier to implement, then it is |
|---|
| 203 |
likely also easier to understand. Isn't it better to spend time learning |
|---|
| 204 |
to write better programs than language arcana? If a language can capture |
|---|
| 205 |
90% of the power of |
|---|
| 206 |
C++ with 10% of its complexity, I argue that is a worthwhile tradeoff. |
|---|
| 207 |
) |
|---|
| 208 |
|
|---|
| 209 |
|
|---|
| 210 |
$(ITEM q4, Why is printf in D?) |
|---|
| 211 |
|
|---|
| 212 |
$(P $(B printf) is not part of D, it is part of C's standard |
|---|
| 213 |
runtime library which is accessible from D. |
|---|
| 214 |
D's standard runtime library has $(B std.stdio.writefln), |
|---|
| 215 |
which is as powerful as $(B printf) but much easier to use. |
|---|
| 216 |
) |
|---|
| 217 |
|
|---|
| 218 |
|
|---|
| 219 |
$(ITEM q5, Will D be open source?) |
|---|
| 220 |
|
|---|
| 221 |
$(P The front end for D is open source, and the source comes with the |
|---|
| 222 |
$(LINK2 http://www.digitalmars.com/d/download.html, compiler). |
|---|
| 223 |
The runtime library is completely open source. |
|---|
| 224 |
David Friedman has integrated the |
|---|
| 225 |
$(LINK2 http://home.earthlink.net/~dvdfrdmn/d, D frontend with GCC) |
|---|
| 226 |
to create $(B gdc), a completely open source implementation of D. |
|---|
| 227 |
) |
|---|
| 228 |
|
|---|
| 229 |
$(ITEM q6, Why fall through on switch statements?) |
|---|
| 230 |
|
|---|
| 231 |
$(P Many people have asked for a requirement that there be a break between |
|---|
| 232 |
cases in a switch statement, that C's behavior of silently falling through |
|---|
| 233 |
is the cause of many bugs. |
|---|
| 234 |
) |
|---|
| 235 |
|
|---|
| 236 |
$(P The reason D doesn't change this is for the same reason that integral |
|---|
| 237 |
promotion rules and operator precedence rules were kept the same - to |
|---|
| 238 |
make code that looks the same as in C operate the same. If it had subtly |
|---|
| 239 |
different semantics, it will cause frustratingly subtle bugs. |
|---|
| 240 |
) |
|---|
| 241 |
|
|---|
| 242 |
|
|---|
| 243 |
$(ITEM q7, Why should I use D instead of Java?) |
|---|
| 244 |
|
|---|
| 245 |
D is distinct from Java in purpose, philosophy and reality. |
|---|
| 246 |
See this <a href="comparison.html">comparison</a>. |
|---|
| 247 |
<p> |
|---|
| 248 |
|
|---|
| 249 |
Java is designed to be write once, run everywhere. D is designed for writing |
|---|
| 250 |
efficient native system apps. Although D and Java share the notion that |
|---|
| 251 |
garbage collection is good and multiple inheritance is bad <g>, their |
|---|
| 252 |
different design goals mean the languages have very different feels. |
|---|
| 253 |
|
|---|
| 254 |
$(ITEM q7_2, Doesn't C++ support strings, etc. with STL?) |
|---|
| 255 |
|
|---|
| 256 |
$(P In the C++ standard library are mechanisms for doing strings, |
|---|
| 257 |
dynamic arrays, associative arrays, bounds checked |
|---|
| 258 |
arrays, and complex numbers. |
|---|
| 259 |
) |
|---|
| 260 |
|
|---|
| 261 |
$(P Sure, all this stuff can be done with libraries, |
|---|
| 262 |
following certain coding disciplines, etc. But you can also do |
|---|
| 263 |
object oriented programming in C (I've seen it done). |
|---|
| 264 |
Isn't it incongruous that something like strings, |
|---|
| 265 |
supported by the simplest BASIC interpreter, requires a very |
|---|
| 266 |
large and complicated infrastructure to support? |
|---|
| 267 |
Just the implementation of a string type in STL is over two |
|---|
| 268 |
thousand lines of code, using every advanced feature of templates. |
|---|
| 269 |
How much confidence can you have that this is all working |
|---|
| 270 |
correctly, how do you fix it if it is not, what do you do with the |
|---|
| 271 |
notoriously inscrutable error messages when there's an error |
|---|
| 272 |
using it, how can you be sure you are using it correctly |
|---|
| 273 |
(so there are no memory leaks, etc.)? |
|---|
| 274 |
) |
|---|
| 275 |
|
|---|
| 276 |
$(P D's implementation of strings is simple and straightforward. |
|---|
| 277 |
There's little doubt about how to use it, no worries about memory leaks, |
|---|
| 278 |
error messages are to the point, and it isn't hard to see if it |
|---|
| 279 |
is working as expected or not. |
|---|
| 280 |
) |
|---|
| 281 |
|
|---|
| 282 |
$(ITEM q7_3, Can't garbage collection be done in C++ with an add-on library?) |
|---|
| 283 |
|
|---|
| 284 |
Yes, I use one myself. It isn't part of the language, though, and |
|---|
| 285 |
requires some subverting of the language to make it work. |
|---|
| 286 |
Using gc with C++ isn't for the standard or casual C++ programmer. |
|---|
| 287 |
Building it into the |
|---|
| 288 |
language, like in D, makes it practical for everyday programming chores. |
|---|
| 289 |
<p> |
|---|
| 290 |
|
|---|
| 291 |
GC isn't that hard to implement, either, unless you're building one |
|---|
| 292 |
of the more advanced ones. But a more advanced one is like building |
|---|
| 293 |
a better optimizer - the language still works 100% correctly even |
|---|
| 294 |
with a simple, basic one. The programming community is better served |
|---|
| 295 |
by multiple implementations competing on quality of code generated |
|---|
| 296 |
rather than by which corners of the spec are implemented at all. |
|---|
| 297 |
|
|---|
| 298 |
$(ITEM q7_4, Can't unit testing be done in C++ with an add-on library?) |
|---|
| 299 |
|
|---|
| 300 |
Sure. Try one out and then compare it with how D does it. |
|---|
| 301 |
It'll be quickly obvious what an improvement building it into |
|---|
| 302 |
the language is. |
|---|
| 303 |
|
|---|
| 304 |
$(ITEM q8, Why have an asm statement in a portable language?) |
|---|
| 305 |
|
|---|
| 306 |
An asm statement allows assembly code to be inserted directly into a D |
|---|
| 307 |
function. Assembler code will obviously be inherently non-portable. D is |
|---|
| 308 |
intended, however, to be a useful language for developing systems apps. |
|---|
| 309 |
Systems apps almost invariably wind up with system dependent code in them |
|---|
| 310 |
anyway, inline asm isn't much different. Inline asm will be useful for |
|---|
| 311 |
things like accessing special CPU instructions, accessing flag bits, special |
|---|
| 312 |
computational situations, and super optimizing a piece of code. |
|---|
| 313 |
<p> |
|---|
| 314 |
|
|---|
| 315 |
Before the C compiler had an inline assembler, I used external assemblers. |
|---|
| 316 |
There was constant grief because many, many different versions of the |
|---|
| 317 |
assembler were out there, the vendors kept changing the syntax of the |
|---|
| 318 |
assemblers, there were many different bugs in different versions, and even |
|---|
| 319 |
the command line syntax kept changing. What it all meant was that users |
|---|
| 320 |
could not reliably rebuild any code that needed assembler. An inline |
|---|
| 321 |
assembler provided reliability and consistency. |
|---|
| 322 |
|
|---|
| 323 |
$(ITEM real, What is the point of 80 bit reals?) |
|---|
| 324 |
|
|---|
| 325 |
More precision enables more accurate floating point computations |
|---|
| 326 |
to be done, especially when adding together large numbers of small |
|---|
| 327 |
real numbers. Prof. Kahan, who designed the Intel floating point |
|---|
| 328 |
unit, has an eloquent |
|---|
| 329 |
<a href="http://http.cs.berkeley.edu/~wkahan/JAVAhurt.pdf">paper</a> |
|---|
| 330 |
on the subject. |
|---|
| 331 |
|
|---|
| 332 |
$(ITEM anonymous, How do I do anonymous struct/unions in D?) |
|---|
| 333 |
|
|---|
| 334 |
----------------------- |
|---|
| 335 |
import std.stdio; |
|---|
| 336 |
|
|---|
| 337 |
struct Foo |
|---|
| 338 |
{ |
|---|
| 339 |
union { int a; int b; } |
|---|
| 340 |
struct { int c; int d; } |
|---|
| 341 |
} |
|---|
| 342 |
|
|---|
| 343 |
void main() |
|---|
| 344 |
{ |
|---|
| 345 |
writefln( |
|---|
| 346 |
"Foo.sizeof = %d, a.offset = %d, b.offset = %d, c.offset = %d, d.offset = %d", |
|---|
| 347 |
Foo.sizeof, |
|---|
| 348 |
Foo.a.offsetof, |
|---|
| 349 |
Foo.b.offsetof, |
|---|
| 350 |
Foo.c.offsetof, |
|---|
| 351 |
Foo.d.offsetof); |
|---|
| 352 |
} |
|---|
| 353 |
----------------------- |
|---|
| 354 |
|
|---|
| 355 |
$(ITEM printf, How do I get printf() to work with strings?) |
|---|
| 356 |
|
|---|
| 357 |
In C, the normal way to printf a string is to use the $(B %s) |
|---|
| 358 |
format: |
|---|
| 359 |
|
|---|
| 360 |
$(CCODE |
|---|
| 361 |
char s[8]; |
|---|
| 362 |
strcpy(s, "foo"); |
|---|
| 363 |
printf("string = '$(B %s)'\n", s); |
|---|
| 364 |
) |
|---|
| 365 |
|
|---|
| 366 |
Attempting this in D, as in: |
|---|
| 367 |
|
|---|
| 368 |
--------------------------------- |
|---|
| 369 |
char[] s; |
|---|
| 370 |
s = "foo"; |
|---|
| 371 |
printf("string = '$(B %s)'\n", s); |
|---|
| 372 |
--------------------------------- |
|---|
| 373 |
|
|---|
| 374 |
usually results in garbage being printed, or an access violation. |
|---|
| 375 |
The cause is that in C, strings are terminated by a 0 character. |
|---|
| 376 |
The $(B %s) format prints until a 0 is encountered. |
|---|
| 377 |
In D, strings are not 0 terminated, the size is determined |
|---|
| 378 |
by a separate length value. So, strings are printf'd using the |
|---|
| 379 |
$(B %.*s) format: |
|---|
| 380 |
|
|---|
| 381 |
--------------------------------- |
|---|
| 382 |
char[] s; |
|---|
| 383 |
s = "foo"; |
|---|
| 384 |
printf("string = '$(B %.*s)'\n", s); |
|---|
| 385 |
--------------------------------- |
|---|
| 386 |
|
|---|
| 387 |
$(P which will behave as expected. |
|---|
| 388 |
Remember, though, that printf's $(B %.*s) will print until the length |
|---|
| 389 |
is reached or a 0 is encountered, so D strings with embedded 0's |
|---|
| 390 |
will only print up to the first 0. |
|---|
| 391 |
) |
|---|
| 392 |
|
|---|
| 393 |
$(P Of course, the easier solution is just use $(B std.stdio.writefln) |
|---|
| 394 |
which works correctly with D strings. |
|---|
| 395 |
) |
|---|
| 396 |
|
|---|
| 397 |
$(ITEM nan, Why are floating point values default initialized to NaN rather than 0?) |
|---|
| 398 |
|
|---|
| 399 |
A floating point value, if no explicit initializer is given, |
|---|
| 400 |
is initialized to NaN (Not A Number): |
|---|
| 401 |
|
|---|
| 402 |
--------------------------------- |
|---|
| 403 |
double d; // d is set to double.nan |
|---|
| 404 |
--------------------------------- |
|---|
| 405 |
|
|---|
| 406 |
NaNs have the interesting property in that whenever a NaN is |
|---|
| 407 |
used as an operand in a computation, the result is a NaN. Therefore, |
|---|
| 408 |
NaNs will propagate and appear in the output whenever a computation |
|---|
| 409 |
made use of one. This implies that a NaN appearing in the output |
|---|
| 410 |
is an unambiguous indication of the use of an uninitialized |
|---|
| 411 |
variable. |
|---|
| 412 |
<p> |
|---|
| 413 |
|
|---|
| 414 |
If 0.0 was used as the default initializer for floating point |
|---|
| 415 |
values, its effect could easily be unnoticed in the output, and so |
|---|
| 416 |
if the default initializer was unintended, the bug may go |
|---|
| 417 |
unrecognized. |
|---|
| 418 |
<p> |
|---|
| 419 |
|
|---|
| 420 |
The default initializer value is not meant to be a useful value, |
|---|
| 421 |
it is meant to expose bugs. Nan fills that role well. |
|---|
| 422 |
<p> |
|---|
| 423 |
|
|---|
| 424 |
But surely the compiler can detect and issue an error message |
|---|
| 425 |
for variables used that are not initialized? Most of the time, |
|---|
| 426 |
it can, but not always, and what it can do is dependent on the |
|---|
| 427 |
sophistication of the compiler's internal data flow analysis. |
|---|
| 428 |
Hence, relying on such is unportable and unreliable. |
|---|
| 429 |
<p> |
|---|
| 430 |
|
|---|
| 431 |
Because of the way CPUs are designed, there is no NaN value for |
|---|
| 432 |
integers, so D uses 0 instead. It doesn't have the advantages of |
|---|
| 433 |
error detection that NaN has, but at least errors resulting from |
|---|
| 434 |
unintended default initializations will be consistent and therefore more |
|---|
| 435 |
debuggable. |
|---|
| 436 |
|
|---|
| 437 |
$(ITEM assignmentoverloading, Why is overloading of the assignment operator not supported?) |
|---|
| 438 |
|
|---|
| 439 |
$(P Overloading of the assignment operator for structs is supported |
|---|
| 440 |
in D 2.0.) |
|---|
| 441 |
|
|---|
| 442 |
$(ITEM keys, The $(SINGLEQUOTE ~) is not on my keyboard?) |
|---|
| 443 |
|
|---|
| 444 |
$(P On PC keyboards, hold down the [Alt] key and press the 1, 2, and 6 |
|---|
| 445 |
keys in sequence on the numeric pad. That will generate a $(SINGLEQUOTE ~) |
|---|
| 446 |
character. |
|---|
| 447 |
) |
|---|
| 448 |
|
|---|
| 449 |
$(ITEM omf, Can I link in C object files created with another compiler?) |
|---|
| 450 |
|
|---|
| 451 |
|
|---|
| 452 |
DMD produces OMF (Microsoft Object Module Format) object |
|---|
| 453 |
files while other compilers such as VC++ produce COFF object |
|---|
| 454 |
files. |
|---|
| 455 |
DMD's output is designed to work with DMC, the Digital Mars C |
|---|
| 456 |
compiler, which also produces object files in OMF format. |
|---|
| 457 |
<p> |
|---|
| 458 |
|
|---|
| 459 |
The OMF format that DMD uses is a Microsoft defined format based on an |
|---|
| 460 |
earlier Intel designed one. Microsoft at one point decided to abandon it |
|---|
| 461 |
in favor of a Microsoft defined variant on COFF. |
|---|
| 462 |
<p> |
|---|
| 463 |
|
|---|
| 464 |
Using the same object format doesn't mean that any C library in that |
|---|
| 465 |
format will successfully link and run. There is a lot more compatibility |
|---|
| 466 |
required - such as calling conventions, name mangling, compiler helper |
|---|
| 467 |
functions, and hidden assumptions about the way things work. If DMD |
|---|
| 468 |
produced Microsoft COFF output files, there is still little chance that |
|---|
| 469 |
they would work successfully with object files designed and tested for |
|---|
| 470 |
use with VC. There were a lot of problems with this back when |
|---|
| 471 |
Microsoft's compilers did generate OMF. |
|---|
| 472 |
<p> |
|---|
| 473 |
|
|---|
| 474 |
Having a different object file format makes it helpful in identifying |
|---|
| 475 |
library files that were not tested to work with DMD. If they are not, |
|---|
| 476 |
weird problems would result even if they successfully managed to link |
|---|
| 477 |
them together. It really takes an expert to get a binary built with a |
|---|
| 478 |
compiler from one vendor to work with the output of another vendor's |
|---|
| 479 |
compiler. |
|---|
| 480 |
<p> |
|---|
| 481 |
|
|---|
| 482 |
That said, the linux version of DMD produces object files in the ELF |
|---|
| 483 |
format which is standard on linux, and it is specifically designed to |
|---|
| 484 |
work with the standard linux C compiler, gcc. |
|---|
| 485 |
<p> |
|---|
| 486 |
|
|---|
| 487 |
There is one case where using existing C libraries does work - when |
|---|
| 488 |
those libraries come in the form of a DLL conforming to the usual C ABI |
|---|
| 489 |
interface. The linkable part of this is called an "import library", and |
|---|
| 490 |
Microsoft COFF format import libraries can be successfully converted to |
|---|
| 491 |
DMD OMF using the |
|---|
| 492 |
<a href="http://www.digitalmars.com/ctg/coff2omf.html">coff2omf</a> |
|---|
| 493 |
tool. |
|---|
| 494 |
|
|---|
| 495 |
$(ITEM regexp_literals, Why not support regular expression literals |
|---|
| 496 |
with the $(TT /foo/g) syntax?) |
|---|
| 497 |
|
|---|
| 498 |
$(P There are two reasons: |
|---|
| 499 |
) |
|---|
| 500 |
|
|---|
| 501 |
$(OL |
|---|
| 502 |
|
|---|
| 503 |
$(LI The $(TT /foo/g) syntax would make it impossible to separate |
|---|
| 504 |
the lexer from the parser, as / is the divide token.) |
|---|
| 505 |
|
|---|
| 506 |
$(LI There are already 3 string types; adding the regex literals |
|---|
| 507 |
would add 3 more. This would proliferate through much of the compiler, |
|---|
| 508 |
debugger info, and library, and is not worth it.) |
|---|
| 509 |
|
|---|
| 510 |
) |
|---|
| 511 |
|
|---|
| 512 |
$(ITEM dogfood, Why is the D front end written in C++ rather than D?) |
|---|
| 513 |
|
|---|
| 514 |
$(P The front end is in C++ in order to interface to the existing gcc |
|---|
| 515 |
and dmd back ends. |
|---|
| 516 |
It's also meant to be easily interfaced to other existing back ends, |
|---|
| 517 |
which are likely written in C++. |
|---|
| 518 |
The D implementation of |
|---|
| 519 |
$(LINK2 http://www.digitalmars.com/dscript/index.html, DMDScript), |
|---|
| 520 |
which performs better than the |
|---|
| 521 |
$(LINK2 http://www.digitalmars.com/dscript/cppscript.html, C++ version), |
|---|
| 522 |
shows that there is no problem |
|---|
| 523 |
writing a professional quality compiler in 100% D. |
|---|
| 524 |
) |
|---|
| 525 |
|
|---|
| 526 |
$(ITEM cpp_to_D, Why aren't all Digital Mars programs translated to D?) |
|---|
| 527 |
|
|---|
| 528 |
$(P There is little benefit to translating a complex, debugged, working |
|---|
| 529 |
application from one language to another. But new Digital Mars apps are |
|---|
| 530 |
implemented in D.) |
|---|
| 531 |
|
|---|
| 532 |
|
|---|
| 533 |
$(ITEM foreach, When should I use a foreach loop rather than a for?) |
|---|
| 534 |
|
|---|
| 535 |
$(P Is it just performance or readability? |
|---|
| 536 |
) |
|---|
| 537 |
|
|---|
| 538 |
$(P By using foreach, you are letting the compiler decide on the |
|---|
| 539 |
optimization rather than worrying about it yourself. For example - are |
|---|
| 540 |
pointers or indices better? |
|---|
| 541 |
Should I cache the termination condition or not? |
|---|
| 542 |
Should I rotate the loop or not? |
|---|
| 543 |
The answers to these questions are not easy, and can vary from machine |
|---|
| 544 |
to machine. Like register assignment, let the compiler do the |
|---|
| 545 |
optimization.) |
|---|
| 546 |
|
|---|
| 547 |
--- |
|---|
| 548 |
for (int i = 0; i < foo.length; i++) |
|---|
| 549 |
--- |
|---|
| 550 |
|
|---|
| 551 |
or: |
|---|
| 552 |
|
|---|
| 553 |
--- |
|---|
| 554 |
for (int i = 0; i < foo.length; ++i) |
|---|
| 555 |
--- |
|---|
| 556 |
|
|---|
| 557 |
or: |
|---|
| 558 |
|
|---|
| 559 |
--- |
|---|
| 560 |
for (T* p = &foo[0]; p < &foo[length]; p++) |
|---|
| 561 |
--- |
|---|
| 562 |
|
|---|
| 563 |
or: |
|---|
| 564 |
|
|---|
| 565 |
--- |
|---|
| 566 |
T* pend = &foo[length]; |
|---|
| 567 |
for (T* p = &foo[0]; p < pend; ++p) |
|---|
| 568 |
--- |
|---|
| 569 |
|
|---|
| 570 |
or: |
|---|
| 571 |
|
|---|
| 572 |
--- |
|---|
| 573 |
T* pend = &foo[length]; |
|---|
| 574 |
T* p = &foo[0]; |
|---|
| 575 |
if (p < pend) |
|---|
| 576 |
{ |
|---|
| 577 |
do |
|---|
| 578 |
{ |
|---|
| 579 |
... |
|---|
| 580 |
} while (++p < pend); |
|---|
| 581 |
} |
|---|
| 582 |
--- |
|---|
| 583 |
|
|---|
| 584 |
and, of course, should I use size_t or int? |
|---|
| 585 |
|
|---|
| 586 |
--- |
|---|
| 587 |
for (size_t i = 0; i < foo.length; i++) |
|---|
| 588 |
--- |
|---|
| 589 |
|
|---|
| 590 |
Let the compiler pick! |
|---|
| 591 |
|
|---|
| 592 |
--- |
|---|
| 593 |
foreach (v; foo) |
|---|
| 594 |
... |
|---|
| 595 |
--- |
|---|
| 596 |
|
|---|
| 597 |
$(P Note that we don't even need to know what the type T needs to be, thus |
|---|
| 598 |
avoiding bugs when T changes. I don't even have to know if foo is an array, or |
|---|
| 599 |
an associative array, or a struct, or a collection class. This will also avoid |
|---|
| 600 |
the common fencepost bug:) |
|---|
| 601 |
|
|---|
| 602 |
--- |
|---|
| 603 |
for (int i = 0; i <= foo.length; i++) |
|---|
| 604 |
--- |
|---|
| 605 |
|
|---|
| 606 |
$(P And it also avoids the need to manually create a temporary if foo is a |
|---|
| 607 |
function call.) |
|---|
| 608 |
|
|---|
| 609 |
$(P The only reason to use a for loop is if your loop does not fit in the |
|---|
| 610 |
conventional form, like if you want to change |
|---|
| 611 |
the termination condition on the fly.) |
|---|
| 612 |
|
|---|
| 613 |
|
|---|
| 614 |
$(ITEM cpp_interface, Why doesn't D have an interface to C++ as well as C?) |
|---|
| 615 |
|
|---|
| 616 |
$(V2 |
|---|
| 617 |
$(P D 2.0 does have a |
|---|
| 618 |
$(LINK2 cpp_interface.html, limited interface to C++ code.) |
|---|
| 619 |
) Here are some reasons why it isn't a full interface: |
|---|
| 620 |
) |
|---|
| 621 |
|
|---|
| 622 |
$(P Attempting to have D interface with C++ is |
|---|
| 623 |
nearly as complicated as writing a C++ compiler, which would destroy the |
|---|
| 624 |
goal of having D be a reasonably easy language to implement. |
|---|
| 625 |
For people with an existing C++ code base that they must work with, they are |
|---|
| 626 |
stuck with C++ (they can't move it to any other language, either).) |
|---|
| 627 |
|
|---|
| 628 |
$(P There are many issues that would have to be resolved in order for D |
|---|
| 629 |
code to call some arbitrary C++ code that is presumed to be unmodifiable. This |
|---|
| 630 |
list certainly isn't complete, it's just to show the scope of the |
|---|
| 631 |
difficulties involved. |
|---|
| 632 |
) |
|---|
| 633 |
|
|---|
| 634 |
$(OL |
|---|
| 635 |
$(LI D source code is unicode, C++'s is ASCII with code pages. Or not. |
|---|
| 636 |
It's unspecified. This impacts the contents of string literals.) |
|---|
| 637 |
|
|---|
| 638 |
$(LI std::string cannot deal with multibyte UTF.) |
|---|
| 639 |
|
|---|
| 640 |
$(LI C++ has a tag name space. D does not. Some sort of renaming would |
|---|
| 641 |
have to happen.) |
|---|
| 642 |
|
|---|
| 643 |
$(LI C++ code often relies on compiler specific extensions.) |
|---|
| 644 |
|
|---|
| 645 |
$(LI C++ has namespaces. D has modules. There is no obvious mapping |
|---|
| 646 |
between the two.) |
|---|
| 647 |
|
|---|
| 648 |
$(LI C++ views source code as one gigantic file (after preprocessing). D |
|---|
| 649 |
sees source code as a hierarchy of modules and packages.) |
|---|
| 650 |
|
|---|
| 651 |
$(LI Enum name scoping rules behave differently.) |
|---|
| 652 |
|
|---|
| 653 |
$(LI C++ code, despite decades of attempts to replace macro features |
|---|
| 654 |
with inbuilt ones, relies more heavily than ever on layer after layer of |
|---|
| 655 |
arbitrary macros. There is no D analog for token pasting or |
|---|
| 656 |
stringizing.) |
|---|
| 657 |
|
|---|
| 658 |
$(LI Macro names have global scope across #include files, but are local |
|---|
| 659 |
to the gigantic source files.) |
|---|
| 660 |
|
|---|
| 661 |
$(LI C++ has arbitrary multiple inheritance and virtual base classes. D |
|---|
| 662 |
does not.) |
|---|
| 663 |
|
|---|
| 664 |
$(LI C++ does not distinguish between in, out and ref (i.e. inout) parameters.) |
|---|
| 665 |
|
|---|
| 666 |
$(LI The C++ name mangling varies from compiler to compiler.) |
|---|
| 667 |
|
|---|
| 668 |
$(LI C++ throws exceptions of arbitrary type, not just descendants of |
|---|
| 669 |
Object.) |
|---|
| 670 |
|
|---|
| 671 |
$(LI C++ overloads based on const and volatile. D overloads |
|---|
| 672 |
based on const and immutable.) |
|---|
| 673 |
|
|---|
| 674 |
$(LI C++ overloads operators in significantly different ways - for |
|---|
| 675 |
example, operator[]() overloading for lvalue and rvalue is based on |
|---|
| 676 |
const overloading and a proxy class.) |
|---|
| 677 |
|
|---|
| 678 |
$(LI C++ overloads operators like < completely independently of |
|---|
| 679 |
>.) |
|---|
| 680 |
|
|---|
| 681 |
$(LI C++ does not distinguish between a class and a struct object.) |
|---|
| 682 |
|
|---|
| 683 |
$(LI The vtbl[] location and layout is different between C++ and D.) |
|---|
| 684 |
|
|---|
| 685 |
$(LI The way RTTI is done is completely different. C++ has no |
|---|
| 686 |
classinfo.) |
|---|
| 687 |
|
|---|
| 688 |
$(LI D does not have two phase lookup, nor does it have Koenig (ADL) |
|---|
| 689 |
lookup.) |
|---|
| 690 |
|
|---|
| 691 |
$(LI C++ relates classes with the 'friend' system, D uses packages and |
|---|
| 692 |
modules.) |
|---|
| 693 |
|
|---|
| 694 |
$(LI C++ class design tends to revolve around explicit memory allocation |
|---|
| 695 |
issues, D's do not.) |
|---|
| 696 |
|
|---|
| 697 |
$(LI D's template system is very different.) |
|---|
| 698 |
|
|---|
| 699 |
$(LI C++ has 'exception specifications'.) |
|---|
| 700 |
|
|---|
| 701 |
$(LI C++ has global operator overloading.) |
|---|
| 702 |
|
|---|
| 703 |
$(LI C++ name mangling depends on const and volatile being type |
|---|
| 704 |
modifiers. |
|---|
| 705 |
D name mangling depends on const and immutable being type modifiers. |
|---|
| 706 |
D's const is also transitive, unlike C++. One cannot have a const |
|---|
| 707 |
pointer to mutable in D. |
|---|
| 708 |
) |
|---|
| 709 |
|
|---|
| 710 |
) |
|---|
| 711 |
|
|---|
| 712 |
$(P The bottom line is the language features affect the design of the code. C++ |
|---|
| 713 |
designs just don't fit with D. Even if you could find a way to automatically |
|---|
| 714 |
adapt between the two, the result will be about as enticing as the left side of |
|---|
| 715 |
a honda welded to the right side of a camaro. |
|---|
| 716 |
) |
|---|
| 717 |
|
|---|
| 718 |
$(ITEM reference-counting, Why doesn't D use reference counting for garbage collection?) |
|---|
| 719 |
|
|---|
| 720 |
$(P Reference counting has its advantages, but some severe |
|---|
| 721 |
disadvantages: |
|---|
| 722 |
) |
|---|
| 723 |
|
|---|
| 724 |
$(UL |
|---|
| 725 |
|
|---|
| 726 |
$(LI Cyclical data structures won't get freed.) |
|---|
| 727 |
|
|---|
| 728 |
$(LI Every pointer copy requires an increment and a corresponding |
|---|
| 729 |
decrement - including when simply passing a reference to a function.) |
|---|
| 730 |
|
|---|
| 731 |
$(LI In a multithreaded app, the incs and decs must be synchronized.) |
|---|
| 732 |
|
|---|
| 733 |
$(LI Exception handlers (finally blocks) must be inserted to handle all the |
|---|
| 734 |
decs so there are no leaks. Contrary to assertions otherwise, there is |
|---|
| 735 |
no such thing as "zero overhead exceptions.") |
|---|
| 736 |
|
|---|
| 737 |
$(LI In order to support slicing and interior pointers, as well as |
|---|
| 738 |
supporting reference counting on arbitrary allocations of non-object |
|---|
| 739 |
data, a separate "wrapper" object must be allocated for each allocation |
|---|
| 740 |
to be ref counted. This essentially doubles the number of allocations |
|---|
| 741 |
needed.) |
|---|
| 742 |
|
|---|
| 743 |
$(LI The wrapper object will mean that all pointers will need to be |
|---|
| 744 |
double-dereferenced to access the data.) |
|---|
| 745 |
|
|---|
| 746 |
$(LI Fixing the compiler to hide all this stuff from the programmer will |
|---|
| 747 |
make it difficult to interface cleanly with C.) |
|---|
| 748 |
|
|---|
| 749 |
$(LI Ref counting can fragment the heap thereby consuming more memory |
|---|
| 750 |
just like the gc can, though the gc typically will consume more memory |
|---|
| 751 |
overall.) |
|---|
| 752 |
|
|---|
| 753 |
$(LI Ref counting does not eliminate latency problems, it just reduces |
|---|
| 754 |
them.) |
|---|
| 755 |
|
|---|
| 756 |
) |
|---|
| 757 |
|
|---|
| 758 |
$(P The proposed C++ shared_ptr<>, which implements ref counting, |
|---|
| 759 |
suffers from all these faults. I haven't seen a heads up benchmark of |
|---|
| 760 |
shared_ptr<> vs mark/sweep, but I wouldn't be surprised if shared_ptr<> |
|---|
| 761 |
turned out to be a significant loser in terms of both performance and |
|---|
| 762 |
memory consumption. |
|---|
| 763 |
) |
|---|
| 764 |
|
|---|
| 765 |
$(P That said, D may in the future optionally support some form of ref |
|---|
| 766 |
counting, as rc is better for managing scarce resources like file |
|---|
| 767 |
handles. |
|---|
| 768 |
) |
|---|
| 769 |
|
|---|
| 770 |
$(ITEM gc_1, Isn't garbage collection slow and non-deterministic?) |
|---|
| 771 |
|
|---|
| 772 |
$(P Yes, but $(B all) dynamic memory management is slow and |
|---|
| 773 |
non-deterministic, including malloc/free. |
|---|
| 774 |
If you talk to the people who actually do real time |
|---|
| 775 |
software, they don't use malloc/free precisely because they are not |
|---|
| 776 |
deterministic. They preallocate all data. |
|---|
| 777 |
However, the use of GC instead of malloc enables advanced language |
|---|
| 778 |
constructs (especially, more powerful array syntax), which greatly |
|---|
| 779 |
reduce the number of memory allocations which need to be made. |
|---|
| 780 |
This can mean that GC is actually faster than explict management. |
|---|
| 781 |
) |
|---|
| 782 |
|
|---|
| 783 |
$(ITEM pure, Can't a sufficiently smart compiler figure out that a function is pure automatically?) |
|---|
| 784 |
|
|---|
| 785 |
$(P The problems with the |
|---|
| 786 |
$(LINK2 http://c2.com/cgi/wiki?SufficientlySmartCompiler, sufficently smart compiler) |
|---|
| 787 |
argument are: |
|---|
| 788 |
) |
|---|
| 789 |
|
|---|
| 790 |
$(OL |
|---|
| 791 |
$(LI most functions call other functions, which call other functions, |
|---|
| 792 |
until one of them calls a library routine whose source is not available |
|---|
| 793 |
to the compiler. So it will have to assume it is not pure. |
|---|
| 794 |
With a pure function attribute, external library functions that are pure |
|---|
| 795 |
can be marked as pure, and then the analysis can work for enough cases |
|---|
| 796 |
to be useful. |
|---|
| 797 |
) |
|---|
| 798 |
|
|---|
| 799 |
$(LI Since virtual functions (and by extension delegates and function |
|---|
| 800 |
pointers) can be extended by the user at times the compiler won't see |
|---|
| 801 |
it, they have to be assumed to be impure. |
|---|
| 802 |
) |
|---|
| 803 |
|
|---|
| 804 |
$(LI If the programmer intends for a particular function to be pure |
|---|
| 805 |
and the compiler detects it is not, this may go unnoticed by the |
|---|
| 806 |
programmer. Even worse, if the programmer does notice it, it may |
|---|
| 807 |
be arbitrarily difficult to determine why the compiler thinks it is |
|---|
| 808 |
impure - is it a programming mistake or a compiler bug? |
|---|
| 809 |
) |
|---|
| 810 |
|
|---|
| 811 |
) |
|---|
| 812 |
|
|---|
| 813 |
$(COMMENT |
|---|
| 814 |
> Single inheritance may be easier to implement, but you are losing |
|---|
| 815 |
>something. It's a little concerning how often folks here take the |
|---|
| 816 |
>opinion that "Feature X has problems and I never use it anyway, so no |
|---|
| 817 |
>body else 'really' needs it." I'm not specificly blaming you, but i've |
|---|
| 818 |
>lost track of how many time if seen that reasoning tonight. I'm afraid |
|---|
| 819 |
>I'll see it a lot in the 275 I still have to read. |
|---|
| 820 |
|
|---|
| 821 |
|
|---|
| 822 |
Your reasoning has merit. The counterargument (and I've discussed |
|---|
| 823 |
this at length with my colleagues) is that C++ gives you a dozen ways |
|---|
| 824 |
and styles to do X. Programmers tend to develop specific styles and do |
|---|
| 825 |
things in certain ways. This leads to one programmer's use of C++ to |
|---|
| 826 |
be radically different than another's, almost to the point where |
|---|
| 827 |
they are different languages. C++ is a huge language, and C++ |
|---|
| 828 |
programmers tend to learn particular "islands" in the language |
|---|
| 829 |
and not be too familiar with the rest of it. |
|---|
| 830 |
|
|---|
| 831 |
Hence one idea behind D is to *reduce* the number of ways X can be |
|---|
| 832 |
accomplished, and reduce the balkanization of programmer expertise. |
|---|
| 833 |
Then, one programmer's coding style will look more like another's, |
|---|
| 834 |
with the intended result that legacy D code will be more maintainable. |
|---|
| 835 |
For example, over the years I've seen dozens of different ways that |
|---|
| 836 |
debug code was inserted into a program, all very different. D has one |
|---|
| 837 |
way - with the debug attribute/statement. C++ has a dozen string |
|---|
| 838 |
classes plus the native C way of doing strings. D has one way of |
|---|
| 839 |
doing strings. |
|---|
| 840 |
|
|---|
| 841 |
I intend to further help this along by writing a D style guide, |
|---|
| 842 |
"The D Way". There's a start on it all ready with the document |
|---|
| 843 |
on how to do error handling: |
|---|
| 844 |
|
|---|
| 845 |
www.digitalmars.com/d/errors.html |
|---|
| 846 |
|
|---|
| 847 |
) |
|---|
| 848 |
|
|---|
| 849 |
) |
|---|
| 850 |
|
|---|
| 851 |
Macros: |
|---|
| 852 |
TITLE=D 2.0 FAQ |
|---|
| 853 |
WIKI=FAQ |
|---|
| 854 |
ITEMR=$(LI $(LINK2 #$1, $+)) |
|---|
| 855 |
ITEM=<hr><h3><a name="$1">$+</a></h3> |
|---|