@@ -214,12 +214,12 @@
A dynamic array is declared as:
-
type array[];
+
type[] array;
whereas a static array is declared as:
-
type array[dimension];
+
type[dimension] array;
Thus, a static array always has the dimension statically available as part of the type, and
@@ -229,7 +229,10 @@
Associative Arrays
- TBD
+
Associative arrays consist of a pointer to an opaque, implementation
+ defined type.
+ The current implementation is contained in phobos/internal/aaA.d.
+
@@ -229,7 +229,7 @@
// pointer to dynamic array of ints
int[]* e;
-int (*e[]);
+int (*e)[];
Rationale: The postfix form matches the way arrays are
@@ -401,7 +401,7 @@
void dibb(int* array)
{
array[2]; // means same thing as *(array + 2)
- *(array + 2); // get 2nd element
+ *(array + 2); // get 3rd element
}
void diss(int[] array)
@@ -591,7 +591,7 @@
b.length = 15; // always resized in place because it is sliced
// from a[] which has enough memory for 15 chars
-b[11] = 'x'; // a[15] and c[5] are also affected
+b[11] = 'x'; // a[11] and c[1] are also affected
a.length = 1;
a.length = 20; // no net change to memory layout
@@ -647,6 +647,19 @@
For example, when gathering user
input from the console - it's unlikely to be longer than 80.
+
Functions as Array Properties
+
+
If the first parameter to a function is an array, the
+ function can be called as if it were a property of the array:
+
+
+
int[] array;
+void foo(int[] a, int x);
+
+foo(array, 3);
+array.foo(3); // means the same thing
+
It is an error to index an array with an index that is less than
@@ -711,37 +724,36 @@
Static Initialization of Static Arrays
+
Static initalizations are supplied by a list of array
+ element values enclosed in [ ]. The values can be optionally
+ preceded by an index and a :.
+ If an index is not supplied, it is set to the previous index
+ plus 1, or 0 if it is the first value.
+
- This is most handy when the array indices are given by enums:
+
This is most handy when the array indices are given by enums:
enum Color { red, blue, green };
int value[Color.max + 1] = [ Color.blue:6, Color.green:2, Color.red:5 ];
- If any members of an array are initialized, they all must be.
- This is to catch
- common errors where another element is added to an enum,
- but one of the static instances
- of arrays of that enum was overlooked in updating the
- initializer list.
+
These arrays are static when they appear in global scope.
+ Otherwise, they need to be marked with const or static
+ storage classes to make them static arrays.
- Languages should be good at handling strings. C and C++ are not
- good at it. The primary difficulties are memory management,
- handling of temporaries, constantly rescanning the string looking
- for the terminating 0, and the fixed arrays.
-
-
- Dynamic arrays in D suggest the obvious solution - a string is
- just a dynamic array of characters. String literals become just
+
A string is
+ an array of characters. String literals are just
an easy way to write character arrays.
+
- The type of a string is determined by the semantic phase of
+
or use the function std.string.toStringz.
+
+
The type of a string is determined by the semantic phase of
compilation. The type is
one of: char[], wchar[], dchar[], and is determined by
implicit conversion rules.
If there are two equally applicable implicit conversions,
the result is an error. To
- disambiguate these cases, a cast is appropriate:
+ disambiguate these cases, a cast or a postfix of c,
+ w or d can be used:
+
cast(wchar [])"abc"// this is an array of wchar characters
+"abc"w// so is this
- String literals are implicitly converted between chars,
- wchars, and dchars as necessary.
-
-
- Strings a single character in length can also be exactly
- converted to a char, wchar or dchar constant:
+
String literals that do not have a postfix character and that
+ have not been cast can be implicitly converted between char[],
+ wchar[], and dchar[] as necessary.
+
char c;
wchar w;
@@ -805,63 +820,74 @@
w = 'b'; // w is assigned the wchar character 'b'
w = 'bc'; // error - only one wchar character at a time
w = "b"[0]; // w is assigned the wchar character 'b'
-w = \r; // w is assigned the carriage return wchar character
+w = \r[0]; // w is assigned the carriage return wchar character
d = 'd'; // d is assigned the character 'd'
-
printf() and Strings
+
C's printf() and Strings
- printf() is a C function and is not part of D. printf()
+
printf() is a C function and is not part of D. printf()
will print C strings, which are 0 terminated. There are two ways
to use printf() with D strings. The first is to add a
terminating 0, and cast the result to a char*:
+
str ~= "\0";
printf("the string is '%s'\n", (char*)str);
- The second way is to use the precision specifier. The way D arrays
- are laid out, the length comes first, so the following works:
+
or:
-
printf("the string is '%.*s'\n", str);
+
import std.string;
+printf("the string is '%s'\n", std.string.toStringz(str));
- In the future, it may be necessary to just add a new format
- specifier to printf() instead of relying on an implementation
- dependent detail.
+
String literals already have a 0 appended to them, so
+ can be used directly:
-
Implicit Conversions
+
printf("the string is '%s'\n", "string literal");
+
- A pointer T* can be implicitly converted to
- one of the following:
+
which is, of course, why the format string to printf was
+ working.
-
-
U* where U is a base class of T.
-
void*
-
+
The second way is to use the precision specifier. The way D arrays
+ are laid out, the length comes first, so the following works:
+
+
printf("the string is '%.*s'\n", str);
+
+
The best way is to use std.stdio.writefln, which can handle
+ D strings:
+
+
import std.stdio;
+writefln("the string is '%s'", str);
+
+
+
Implicit Conversions
+
+
A pointer T* can be implicitly converted to
+ a void*.
A static array T[dim] can be implicitly
converted to
one of the following:
+
T*
T[]
-
U[dim] where U is a base class of T.
-
U[] where U is a base class of T.
-
U* where U is a base class of T.
void*
void[]
- A dynamic array T[] can be implicitly converted to
+
A dynamic array T[] can be implicitly converted to
one of the following:
+
T*
-
U[] where U is a base class of T.
-
U* where U is a base class of T.
void*
+
void[]
@@ -1046,8 +1072,9 @@
Associative Array Example: word count
-
import std.file; // D file I/O
-
+
import std.file; // D file I/O
+import std.stdio;
+
int main (char[][] args)
{
int word_total;
@@ -1055,25 +1082,26 @@
int char_total;
int[char[]] dictionary;
- printf(" lines words bytes file\n");
- for (int i = 1; i < args.length; ++i) // program arguments
+ writefln(" lines words bytes file");
+ for (int i = 1; i < args.length; ++i) // program arguments
{
- char[] input; // input buffer
-int w_cnt, l_cnt, c_cnt; // word, line, char counts
+ char[] input; // input buffer
+int w_cnt, l_cnt, c_cnt; // word, line, char counts
int inword;
int wstart;
- input = std.file.read(args[i]); // read file into input[]
-
- foreach (char c; input)
+ // read file into input[]
+ input = cast(char[])std.file.read(args[i]);
+
+ foreach (j, char c; input)
{
if (c == '\n')
- ++l_cnt;
+ ++l_cnt;
if (c >= '0' && c <= '9')
{
}
elseif (c >= 'a' && c <= 'z' ||
- c >= 'A' && c <= 'Z')
+ c >= 'A' && c <= 'Z')
{
if (!inword)
{
@@ -1083,18 +1111,19 @@
}
}
elseif (inword)
- { char[] word = input[wstart .. j];
-
- dictionary[word]++; // increment count for word
+ {
+ char[] word = input[wstart .. j];
+ dictionary[word]++; // increment count for word
inword = 0;
}
++c_cnt;
}
if (inword)
- { char[] word = input[wstart .. input.length];
+ {
+ char[] word = input[wstart .. input.length];
dictionary[word]++;
}
- printf("%8ld%8ld%8ld %.*s\n", l_cnt, w_cnt, c_cnt, args[i]);
+ writefln("%8d%8d%8d %s", l_cnt, w_cnt, c_cnt, args[i]);
line_total += l_cnt;
word_total += w_cnt;
char_total += c_cnt;
@@ -1102,17 +1131,14 @@
if (args.length > 2)
{
- printf("-------------------------------------\n%8ld%8ld%8ld total",
- line_total, word_total, char_total);
+ writef("-------------------------------------\n%8ld%8ld%8ld total",
+ line_total, word_total, char_total);
}
- printf("-------------------------------------\n");
- char[][] keys = dictionary.keys; // find all words in dictionary[]
-for (int i = 0; i < keys.length; i++)
- { char[] word;
-
- word = keys[i];
- printf("%3d %.*s\n", dictionary[word], word);
+ writefln("-------------------------------------");
+ foreach (word; dictionary.keys.sort)
+ {
+ writefln("%3d %s", dictionary[word], word);
}
return 0;
}
diff -uNr dmd-0.175/dmd/html/d/ascii-table.html dmd-0.176/dmd/html/d/ascii-table.html
--- dmd-0.175/dmd/html/d/ascii-table.html 2006-11-15 02:42:26.000000000 +0100
+++ dmd-0.176/dmd/html/d/ascii-table.html 2006-11-27 18:15:58.000000000 +0100
@@ -32,7 +32,7 @@
-
this() { a || super(); } // illegal
-this() { this(1) || super(); } // ok
+this() { if (a) ? this(1) : super(); } // ok
this()
{
@@ -443,10 +443,11 @@
The raw data is statically initialized using the values provided
in the class definition.
- The pointer to the vtbl is assigned.
+ The pointer to the vtbl[] (the array of pointers to virtual functions)
+ is assigned.
This ensures that constructors are
- passed fully formed objects.
- This operation is equivalent to doing a memcpy() of a static
+ passed fully formed objects for which virtual functions can be called.
+ This operation is equivalent to doing a memory copy of a static
version of the object onto the newly allocated one,
although more advanced compilers
may be able to optimize much of this away.
@@ -657,8 +658,6 @@
class representing a date might have an invariant that the day must be 1..31
and the hour must be 0..23:
-
-
class Date
{
int day;
@@ -707,9 +706,11 @@
assert(mydate); // check that class Date invariant holds
- If the invariant fails, it throws an InvariantException.
+ Invariants contain assert expressions, and so when they fail,
+ they throw a AssertErrors.
Class invariants are inherited, that is,
- any class invariant is implicitly anded with the invariants of its base classes.
+ any class invariant is implicitly anded with the invariants of its base
+ classes.
There can be only one ClassInvariant per class.
@@ -1037,7 +1038,7 @@
class Nested : Base
{ int m_;
- this() { m_ = m;
+ this() { m_ = m; }
int foo() { return m_; }
}
diff -uNr dmd-0.175/dmd/html/d/code_coverage.html dmd-0.176/dmd/html/d/code_coverage.html
--- dmd-0.175/dmd/html/d/code_coverage.html 2006-11-15 02:42:24.000000000 +0100
+++ dmd-0.176/dmd/html/d/code_coverage.html 2006-11-27 18:15:58.000000000 +0100
@@ -31,7 +31,7 @@
-
D takes advantage of knowing that str is a string, and
+
D takes advantage of knowing that str is an array, and
so resizing it is just changing the length property:
@@ -425,7 +425,7 @@
and
wccpp2.
The input file
- alice30.txt
+ alice30.txt
is the text of "Alice in Wonderland."
The D compiler,
dmd,
diff -uNr dmd-0.175/dmd/html/d/cpptod.html dmd-0.176/dmd/html/d/cpptod.html
--- dmd-0.175/dmd/html/d/cpptod.html 2006-11-15 02:42:22.000000000 +0100
+++ dmd-0.176/dmd/html/d/cpptod.html 2006-11-27 18:15:52.000000000 +0100
@@ -32,7 +32,7 @@
-
@@ -503,10 +503,10 @@
declarations and statements.
- The few RAII issues left are handled by auto classes.
- Auto classes get their destructors run when they go out of scope.
+ The few RAII issues left are handled by scope classes.
+ Scope classes get their destructors run when they go out of scope.
-
autoclass File
+
scopeclass File
{ Handle h;
~this()
@@ -518,7 +518,7 @@
void test()
{
if (...)
- { auto File f = new File();
+ { scope f = new File();
...
} // f.~this() gets run at closing brace, even if
// scope was exited via a thrown exception
@@ -836,9 +836,9 @@
There are several difficulties to be resolved, like
- when can storage be free'd, dealing with null pointers,
+ when can storage be freed, dealing with null pointers,
finding the length of the strings, and memory allocation:
- Break's and continue's only apply to the innermost nested loop or
+ Break and continue statements only apply to the innermost nested loop or
switch, so a multilevel break must use a goto:
- The much maligned goto statement is a staple for professional C coders. It's
+ The much maligned goto statement is a staple for professional C coders.
+ It's
necessary to make up for sometimes inadequate control flow statements.
The D Way
- Many C-way goto statements can be eliminated with the D feature of labelled
- break and continue statements. But D is a practical language for practical
- programmers who know when the rules need to be broken. So of course D supports
- the goto!
+ Many C-way goto statements can be eliminated with the D feature of
+ labelled
+ break and continue statements. But D is a practical language for
+ practical
+ programmers who know when the rules need to be broken. So of course D
+ supports goto statements.
It's done through a command line switch which affects the entire
program, and woe results if any modules or libraries didn't get
- recompiled. To address this, #pragma's are used:
+ recompiled. To address this, #pragmas are used:
- D does it by positional dependence too, but an index can be used as well:
+ D does it by positional dependence too, but an index can be used as well.
The following all produce the same result:
- Typedef's in C are weak, that is, they really do not introduce
+ Typedefs in C are weak, that is, they really do not introduce
a new type. The compiler doesn't distinguish between a typedef
and its underlying type.
@@ -1126,8 +1103,7 @@
There's only one name to remember: Handle.
-
-
@@ -1422,7 +1398,7 @@
If i is an int, this works fine. But if i is
- of a typedef'd type,
+ of a type created with typedef,
myint i, j;
...
@@ -1464,8 +1440,8 @@
A generic context pointer is also needed, represented here by
void *p. The example here is of a trivial container
- class that holds an array of int's, and a user of that container
- that computes the maximum of those int's.
+ class that holds an array of ints, and a user of that container
+ that computes the maximum of those ints.
C programmers will find it familiar. Unlike C, however, an assert
in function bodies
- works by throwing an AssertException,
+ works by throwing an AssertError,
which can be caught and handled. Catching the contract violation is useful
when the code must deal with errant uses by other code, when it must be
failure proof, and as a useful tool for debugging.
@@ -194,9 +194,10 @@
...code...
}
- By definition, if a pre contract fails, then the body received bad parameters.
- An InException is thrown. If a post contract fails,
- then there is a bug in the body. An OutException is thrown.
+ By definition, if a pre contract fails, then the body received bad
+ parameters.
+ An AssertError is thrown. If a post contract fails,
+ then there is a bug in the body. An AssertError is thrown.
Either the in or the out clause can be omitted.
If the out clause is for a function
@@ -210,11 +211,11 @@
}
out (result)
{
- assert((result * result) == x);
+ assert((result * result) <= x && (result+1) * (result+1) >= x);
}
body
{
- return math.sqrt(x);
+ returncast(long)std.math.sqrt(cast(real)x);
}
The assert's in the in and out bodies are called contracts.
@@ -269,7 +270,7 @@
If a function in a derived class overrides a function in its
super class, then only one of
the in contracts of the function and its base functions
- must be satisified.
+ must be satisfied.
Overriding
functions then becomes a process of loosening the in
contracts.
diff -uNr dmd-0.175/dmd/html/d/dcompiler.html dmd-0.176/dmd/html/d/dcompiler.html
--- dmd-0.175/dmd/html/d/dcompiler.html 2006-11-15 02:42:24.000000000 +0100
+++ dmd-0.176/dmd/html/d/dcompiler.html 2006-11-27 18:15:56.000000000 +0100
@@ -32,7 +32,7 @@
-
-g is only implemented for line numbers, not local
- symbols, because I haven't figured out how to
- do it yet. gdb still works, though, at the global symbol level.
-
-
The code generator output has not been tuned yet, so it
- can be bloated.
-
-
Shared libraries cannot be generated.
-
-
The exception handling is not compatible with the way g++
- does it. I don't know if this is an issue or not.
-
SynSoft's D Page
+ provides
a number of free D libraries. SynSoft is an imprint of
Synesis Software,
which provides free D,
@@ -312,7 +293,7 @@
Simple URL loading
library by Burton Radons.
- Requires the DIG library
+ Requires the DIG library
to be installed, although it doesn't use it, just digc.
Comes with documentation.
It has the functions:
@@ -327,14 +308,13 @@
+
@@ -786,17 +788,17 @@
The import library mydll.lib is not needed.
The DLL is loaded with a call to
- LoadLibraryA(),
+ LoadLibraryA(),
and each exported function has to be retrieved via
a call to
- GetProcAddress().
+ GetProcAddress().
An easy way to get the decorated name to pass to GetProcAddress()
is to copy and paste it from the generated mydll.map file
under the Export heading.
Once this is done, we can use the member functions of the
DLL classes as if they were part of test.exe.
When done, release the DLL with
- FreeLibrary().
+ FreeLibrary().
+.init First enum member value
.min Smallest value of enum
.max Largest value of enum
.sizeof Size of storage for an enumerated value
diff -uNr dmd-0.175/dmd/html/d/errors.html dmd-0.176/dmd/html/d/errors.html
--- dmd-0.175/dmd/html/d/errors.html 2006-11-15 02:42:24.000000000 +0100
+++ dmd-0.176/dmd/html/d/errors.html 2006-11-27 18:15:56.000000000 +0100
@@ -32,7 +32,7 @@
-
Last update Wed Nov 15 02:42:22 2006
+
Last update Mon Nov 27 18:15:54 2006
@@ -228,7 +228,9 @@
If code detects an error like "out of memory," then an Error is thrown
with a message saying "Out of memory". The function call stack is unwound,
-looking for a handler for the Error. Finally blocks are executed as the
+looking for a handler for the Error.
+Finally blocks
+are executed as the
stack is unwound. If an error handler is found, execution resumes there. If
not, the default Error handler is run, which displays the message and
terminates the program.
diff -uNr dmd-0.175/dmd/html/d/exception-safe.html dmd-0.176/dmd/html/d/exception-safe.html
--- dmd-0.175/dmd/html/d/exception-safe.html 2006-11-15 02:42:26.000000000 +0100
+++ dmd-0.176/dmd/html/d/exception-safe.html 2006-11-27 18:15:58.000000000 +0100
@@ -32,7 +32,7 @@
-
+
@@ -246,7 +248,7 @@
void abc()
{
Mutex m = new Mutex;
- auto Lock L = new Lock(m);
+ scope L = new Lock(m);
foo(); // do processing
}
@@ -351,7 +353,7 @@
Transaction abc()
{
- auto FooX f = new FooX();
+ scope f = new FooX();
Bar b = dobar();
f.commit = true;
return Transaction(f.f, b);
@@ -382,7 +384,7 @@
These work too, but have the same problems.
The RAII approach involves the creation of dummy classes, and the obtuseness
of moving some of the logic out of the abc() function.
-The try-finally approach is wordy even with this simple example, try
+The try-finally approach is wordy even with this simple example; try
writing it if there are more than two components of the transaction that
must succeed. It scales poorly.
@@ -543,7 +545,7 @@
Rewriting it with RAII would require two extra silly classes,
MessageTitleSaver and MessageRemover.
Rewriting the example with try-finally would require nested try-finally
-statements or use an extra variable to track state evolution.
+statements or use of an extra variable to track state evolution.
Example
@@ -578,7 +580,7 @@
When to use RAII, try-catch-finally, and Scope
RAII is for managing resources, which is different from managing state
-or transactions. try-catch is still needed, as on_scope doesn't catch
+or transactions. try-catch is still needed, as scope doesn't catch
exceptions. It's try-finally that becomes redundant.
Acknowledgements
@@ -597,7 +599,7 @@
especially Dawid Ciezarkiewicz and Chris Miller.
-
I am idebted to Scott Meyers for teaching
+
I am indebted to Scott Meyers for teaching
me about exception safe programming.
If one or both operands are floating point, then a floating
point comparison is performed.
@@ -606,33 +606,48 @@
MulExpressionAddExpression+MulExpressionAddExpression-MulExpression
- AddExpression~MulExpression
+ CatExpression
- If the operands are of integral types, they undergo integral
+
If the operands are of integral types, they undergo integral
promotions, and then are brought to a common type using the
usual arithmetic conversions.
-
+
- If either operand is a floating point type, the other is implicitly
+
If either operand is a floating point type, the other is implicitly
converted to floating point and they are brought to a common type
via the usual arithmetic conversions.
-
+
- If the operator is + or -, and
+
If the operator is + or -, and
the first operand is a pointer, and the second is an integral type,
the resulting type is the type of the first operand, and the resulting
value is the pointer plus (or minus) the second operand multiplied by
the size of the type pointed to by the first operand.
-
+
- If the second operand is a pointer, and the first is an integral type,
+
If the second operand is a pointer, and the first is an integral type,
and the operator is +,
the operands are reversed and the pointer arithmetic just described
is applied.
-
+
+
+
Add expressions for floating point operands are not associative.
+
- Add expressions for floating point operands are not associative.
+
A CatExpression concatenates arrays, producing
+ a dynmaic array with the result. The arrays must be
+ arrays of the same element type. If one operand is an array
+ and the other is of that array's element type, that element
+ is converted to an array of length 1 of that element,
+ and then the concatenation is performed.
+
Mul Expressions
@@ -652,7 +667,7 @@
correspond to multiply, divide, and modulus operations.
For multiply, overflows are ignored and simply chopped to fit
into the integral type. If the right operand of divide or modulus
- operators is 0, a DivideByZeroException is thrown.
+ operators is 0, an Exception is thrown.
For integral operands of the % operator, the sign of the
@@ -887,11 +902,12 @@
static array or dynamic array, the variable length
is declared and set to be the length of the array.
if PostfixExpression is an ExpressionTuple,
- the variable length
+ the variable length (and the special variable $)
is declared and set to be the the number of elements
in the tuple.
A new declaration scope is created for the evaluation of the
- ArgumentList and length appears in that scope only.
+ ArgumentList and length (and $)
+ appears in that scope only.
If PostfixExpression is an ExpressionTuple,
@@ -913,10 +929,11 @@
PostfixExpression is evaluated.
if PostfixExpression is an expression of type
static array or dynamic array, the variable length
+ (and the special variable $)
is declared and set to be the length of the array.
A new declaration scope is created for the evaluation of the
AssignExpression..AssignExpression
- and length appears in that scope only.
+ and length (and $) appears in that scope only.
The first AssignExpression is taken to be the inclusive
@@ -1005,6 +1022,7 @@
Within a non-static member function, super resolves to
a reference to the object that called the function, cast to
its base class. It is an error if there is no base class.
+ (Only class Object has no base class.)
super is not allowed in struct member
functions.
If a member function is called with an explicit reference
@@ -1226,7 +1244,9 @@
typeid (Type)
- Returns an instance of class TypeInfo corresponding
+ Returns an instance of class
+ TypeInfo
+ corresponding
to Type.
@@ -1249,6 +1269,7 @@
enumfunctiondelegate
+ superIsExpressions are evaluated at compile time and are
@@ -1331,7 +1352,7 @@
aliasshort bar;
typedefchar foo;
-void foo(bar x)
+void test(bar x)
{
if ( is(bar == int) ) // not satisfied because short is not
// the same type as int
@@ -1456,14 +1477,14 @@
aliasshort bar;
enum E : byte { Emember }
-void foo(bar x, abc a)
+void foo(bar x)
{
staticif ( is(bar T == int) ) // not satisfied, short is not int
alias T S;
alias T U; // error, T is not defined
staticif ( is(E V == enum) ) // satisified, E is an enum
- V x; // x is declared to be a byte
+ V v; // x is declared to be a byte
}
- In the C++ standard library are mechanisms for doing strings,
+
In the C++ standard library are mechanisms for doing strings,
bit arrays, dynamic arrays, associative arrays, bounds checked
arrays, and complex numbers.
-
+
- Sure, all this stuff can be done with libraries,
+
Sure, all this stuff can be done with libraries,
following certain coding disciplines, etc. But you can also do
object oriented programming in C (I've seen it done).
Isn't it incongruous that something like strings,
@@ -371,12 +375,13 @@
notoriously inscrutable error messages when there's an error
using it, how can you be sure you are using it correctly
(so there are no memory leaks, etc.)?
-
+
- D's implementation of strings is simple and straightforward.
- There's little doubt how to use it, no worries about memory leaks,
+
D's implementation of strings is simple and straightforward.
+ There's little doubt about how to use it, no worries about memory leaks,
error messages are to the point, and it isn't hard to see if it
is working as expected or not.
+
A floating point value, if no explicit initializer is given,
- is initialized to nan (Not A Number):
+ is initialized to NaN (Not A Number):
double d; // d is set to double.nan
- Nan's have the interesting property in that whenever a nan is
- used as an operand in a computation, the result is a nan. Therefore,
- nan's will propagate and appear in the output whenever a computation
- made use of one. This implies that a nan appearing in the output
+ NaN's have the interesting property in that whenever a NaN is
+ used as an operand in a computation, the result is a NaN. Therefore,
+ NaN's will propagate and appear in the output whenever a computation
+ made use of one. This implies that a NaN appearing in the output
is an unambiguous indication of the use of an uninitialized
variable.
If 0.0 was used as the default initializer for floating point
- values, its effect can easily be unnoticed in the output, and so
+ values, its effect could easily be unnoticed in the output, and so
if the default initializer was unintended, the bug may go
unrecognized.
@@ -521,9 +527,9 @@
Hence, relying on such is unportable and unreliable.
- Because of the way CPUs are designed, there is no nan value for
+ Because of the way CPUs are designed, there is no NaN value for
integers, so D uses 0 instead. It doesn't have the advantages of
- error detection that nan has, but at least errors resulting from
+ error detection that NaN has, but at least errors resulting from
unintended default initializations will be consistent and therefore more
debuggable.
@@ -719,7 +725,7 @@
function call.
The only reason to use a for loop is if your loop does not fit in the
-conventional form, like if you want to go through the array backwards, or change
+conventional form, like if you want to change
the termination condition on the fly.
@@ -731,7 +737,7 @@
difficulties involved.
-
D source code is unicode, C++'s is ascii with code pages. Or not.
+
D source code is unicode, C++'s is ASCII with code pages. Or not.
It's unspecified. This impacts the contents of string literals.
Reference counting has its advantages, but some severe disadvantages:
+
Reference counting has its advantages, but some severe
+ disadvantages:
-
cyclical data structures won't get free'd
+
Cyclical data structures won't get freed.
-
every pointer copy requires an increment and a corresponding
- decrement - including when simply passing a reference to a function
+
Every pointer copy requires an increment and a corresponding
+ decrement - including when simply passing a reference to a function.
-
in a multithreaded app, the incs and decs must be synchronized
+
In a multithreaded app, the incs and decs must be synchronized.
-
exception handlers (finally's) must be inserted to handle all the
+
Exception handlers (finally blocks) must be inserted to handle all the
decs so there are no leaks. Contrary to assertions otherwise, there is
no such thing as "zero overhead exceptions."
-
in order to support slicing and interior pointers, as well as
+
In order to support slicing and interior pointers, as well as
supporting reference counting on arbitrary allocations of non-object
data, a separate "wrapper" object must be allocated for each allocation
to be ref counted. This essentially doubles the number of allocations
@@ -851,7 +858,7 @@
just like the gc can, though the gc typically will consume more memory
overall.
-
Ref counting does not eliminated latency problems, it just reduces
+
Ref counting does not eliminate latency problems, it just reduces
them.
@@ -160,7 +160,7 @@
Algorithms should be written to work based on the minimum
precision of the calculation. They should not degrade or
fail if the actual precision is greater. Float or double types,
- as opposed to the extended type, should only be used for:
+ as opposed to the real (extended) type, should only be used for:
reducing memory consumption for large arrays
when speed is more important than accuracy
@@ -243,11 +243,11 @@
creal c = 4.5 + 2i;
- Complex numbers have two properties:
+ Complex, real and imaginary numbers have two properties:
-.re get real part
-.im get imaginary part as a real
+.re get real part (0 for imaginary numbers)
+.im get imaginary part as a real (0 for real numbers)
For example:
@@ -257,6 +257,8 @@
cd.im is 2 double
c.re is 4.5 real
c.im is 2 real
+j.im is 1.3 real
+j.re is 0 real
Rounding Control
@@ -266,9 +268,19 @@
Exception Flags
- IEEE 754 floating point arithmetic can set several flags based on what happened with a
- computation: [blah, blah, blah].
- These flags can be set/reset via the functions in std.c.fenv.
+
IEEE 754 floating point arithmetic can set several flags based on what
+ happened with a
+ computation:
+
+
FE_INVALID
+
FE_DENORMAL
+
FE_DIVBYZERO
+
FE_OVERFLOW
+
FE_UNDERFLOW
+
FE_INEXACT
+
+
+
These flags can be set/reset via the functions in std.c.fenv.
Floating Point Comparisons
@@ -285,29 +297,7 @@
!<>
and match the semantics for the
NCEG extensions to C.
-
-
-Floating point comparison operators
-
-Operator Relations Invalid? Description
-
- > < = ?
-
-< F T F F yes less than
-> T F F F yes greater than
-<= F T T F yes less than or equal to
->= T F T F yes greater than or equal to
-== F F T F no equal to
-!= T T F T no unordered, less than, or greater than
-!<>= F F F T no unordered
-<> T T F F yes less than or greater than
-<>= T T T F yes less than, equal to, or greater than
-!<= T F F T no unordered or greater than
-!< T F T T no unordered, greater than, or equal to
-!>= F T F T no unordered or less than
-!> F T T T no unordered, less than, or equal to
-!<> F F T T no unordered or equal to
-
+ Virtual functions are functions that are called indirectly
+ through a function
+ pointer table, called a vtbl[], rather than directly.
All non-static non-private non-template member functions are virtual.
This may sound
inefficient, but since the D compiler knows all of the class
@@ -159,8 +162,8 @@
In fact, since
C++ programmers tend to "when in doubt, make it virtual", the D way of
"make it
- virtual unless we can prove it can be made non-virtual" results on
- average much
+ virtual unless we can prove it can be made non-virtual" results, on
+ average, in many
more direct function calls. It also results in fewer bugs caused by
not declaring
a function virtual that gets overridden.
@@ -250,7 +253,7 @@
void bar(A a)
{
- a.foo(); // calls B.foo(int)
+ a.foo(1); // calls B.foo(int)
}
@@ -397,15 +400,41 @@
out parameters are set to the default initializer for the
type of it. For example:
-
void foo(outint bar)
+
void foo(outint x)
{
+ // x is set to 0 at start of foo()
+}
+
+int a = 3;
+foo(a);
+// a is now 0
+
+
+void abc(outint x)
+{
+ x = 2;
+}
+
+int y = 3;
+abc(y);
+// y is now 2
+
+
+void def(inoutint x)
+{
+ x += 1;
}
-int bar = 3;
-foo(bar);
-// bar is now 0
+int z = 3;
+def(z);
+// z is now 4
+
For dynamic array and object parameters, which are passed
+ by reference, in/out/inout
+ apply only to the reference and not the contents.
+
+
Lazy arguments are evaluated not when the function is called,
but when the parameter is evaluated within the function. Hence,
a lazy argument can be executed 0 or more times. A lazy parameter
@@ -459,15 +488,14 @@
foo(2); // error, y is a required argument
- There must have at least one non-variadic parameter declared.
+ There must be at least one non-variadic parameter declared.
extern (C) int def(...); // error, must have at least one parameter
- This kind of function matches the C calling convention for
+ C-style variadic functions match the C calling convention for
variadic functions, and is most useful for calling C library
functions like printf.
-
The implementiations of these variadic functions have a special
local variable declared for them,
_argptr, which is a void* pointer to the first of the
@@ -491,7 +519,7 @@
importstd.c.stdarg;
-
Variadic Functions With Type Info
+
D-style Variadic Functions
Variadic functions with argument and type info are declared as taking
a parameter of ... after the required function parameters.
@@ -648,7 +676,7 @@
int func()
{
- staticint[3] ii = [4, 5, 6];
+ int[3] ii = [4, 5, 6];
return sum(ii); // returns 15
}
@@ -671,7 +699,7 @@
int func()
{
- staticint[3] ii = [4, 5, 6];
+ int[3] ii = [4, 5, 6];
int[] jj = ii;
return sum(ii); // returns 15
return sum(jj); // error, type mismatch
@@ -688,7 +716,17 @@
For class objects:
-
It is an error to declare a local variable that is never referred to.
- Dead variables, like anachronistic dead code, is just a source of
+ Dead variables, like anachronistic dead code, are just a source of
confusion for maintenance programmers.
@@ -792,7 +830,7 @@
It is an error to have a local variable and a label with the same name.
-
Garbage collectors reclaim unused memory, therefore they do not suffer
from "memory leaks" which can cause long running applications to gradually
- consume more and more memory until they bring down the system. GC'd programs
+ consume more and more memory until they bring down the system. GC programs
have longer term stability.
Garbage collected programs have fewer hard-to-find pointer bugs. This
- is because there are no dangling references to free'd memory. There is no
+ is because there are no dangling references to freed memory. There is no
code to explicitly manage memory, hence no bugs in such code.
Garbage collected programs are faster to develop and debug, because
@@ -300,7 +300,7 @@
Do not xor pointers with other values, like the
- xor'd pointer linked list trick used in C.
+ xor pointer linked list trick used in C.
Do not use the xor trick to swap two pointer values.
@@ -414,7 +414,7 @@
rendering most explicit pointer uses obsolete, such as reference
objects,
dynamic arrays, and garbage collection. Pointers
- are provided in order to interface successfully with C API's and for
+ are provided in order to interface successfully with C APIs and for
some low level work.
When the garbage collector does a collection pass, it must
pause all running threads in order to scan their stacks and register
diff -uNr dmd-0.175/dmd/html/d/mixin.html dmd-0.176/dmd/html/d/mixin.html
--- dmd-0.175/dmd/html/d/mixin.html 2006-11-15 02:42:24.000000000 +0100
+++ dmd-0.176/dmd/html/d/mixin.html 2006-11-27 18:15:56.000000000 +0100
@@ -32,7 +32,7 @@
-
@@ -554,6 +554,18 @@
determine equality or inequality.
+ Note: Comparing a reference to a class object against null
+ should be done as:
+
if (a isnull)
+
+ and not as:
+
if (a == null)
+
+ The latter is converted to:
+
if (a.opCmp(null))
+
+ which will fail if opCmp() is a virtual function.
+
Overloading <, <=, > and >=
These comparison operators all use the opCmp() function.
@@ -575,18 +587,6 @@
to compare two structs is an error.
- Note: Comparing a reference to a class object against null
- should be done as:
-
if (a isnull)
-
- and not as:
-
if (a == null)
-
- The latter is converted to:
-
if (a.opCmp(null))
-
- which will fail if opCmp() is a virtual function.
-
Rationale
The reason for having both opEquals() and opCmp() is that:
@@ -630,7 +630,7 @@
int i;
i = f(); // same as i = f.opCall();
- i = f(3,4,5); // same as i = a.opCall(3,4,5);
+ i = f(3,4,5); // same as i = f.opCall(3,4,5);
}
diff -uNr dmd-0.175/dmd/html/d/overview.html dmd-0.176/dmd/html/d/overview.html
--- dmd-0.175/dmd/html/d/overview.html 2006-11-15 02:42:22.000000000 +0100
+++ dmd-0.176/dmd/html/d/overview.html 2006-11-27 18:15:54.000000000 +0100
@@ -31,7 +31,7 @@
-
When passed to the 'bind' function, they will mark dynamic params - ones that aren't statically bound
+ In boost, they're called _1, _2, _3, etc.. here _0, _1, _2, ...
+
+
+
+
struct Tuple(T...);
+
+
A simple tuple struct with some basic operations
+
+
+
template appendT(X)
+
Statically yields a tuple type with an extra element added at its end
+
+
+
+
+
+
template append(X)
+
Yields a tuple with an extra element added at its end
+
+
+
+
appendT!(X) append(X x);
+
+
Yields a tuple with an extra element added at its end
+
+
+
+
+
+
+
template prependT(X)
+
Statically yields a tuple type with an extra element added at its beginning
+
+
+
+
+
+
template prepend(X)
+
Yields a tuple with an extra element added at its beginning
+
+
+
+
prependT!(X) prepend(X x);
+
+
Yields a tuple with an extra element added at its beginning
+
+
+
+
+
+
+
template concatT(T...)
+
Statically concatenates this tuple type with another tuple type
+
+
+
+
+
+
+
+
struct Tuple();
+
+
An empty tuple struct
+
+
+
alias type;
+
+
an empty built-in tuple
+
+
+
+
alias value;
+
+
an empty built-in tuple
+
+
+
+
+
+
Tuple!(T) tuple(T...)(T t);
+
+
Dynamically create a tuple from the given items
+
+
+
+
template isTypeTuple(T)
+
Checks whether a given type is the Tuple struct of any length
+
+
+
+
+
template minNumArgs(alias fn,fnT = typeof(&fn))
+
Finds the minimal number of arguments a given function needs to be provided
+
+
+
+
+
class BoundFunc(FT,alias FAlias_,AllBoundArgs_);
+
bind() can curry or "bind" arguments of a function, producing a different function which requires less parameters,
+ or a different order of parameters. It also allows function composition.
+
dynamic argument, of the form _[0-9], e.g. _0, _3 or _9
+
+
+
+ The result is a function object, which can be called using call(), func() or opCall().
+ There also exists a convenience function, ptr() which returns a delegate to call/func/opCall
+
+
+ The resulting delegate accepts exactly as many parameters as many distinct dynamic arguments were used.
+
- bind(&foo, _0, _1) // will yield a delegate accepting two parameters
+- bind(&foo, _1, _0) // will yield a delegate accepting two parameters
+- bind(&bar, _0, _1, _2, _0) // will yield a delegate accepting three parameters
+
+
+
+
+ The types of dynamic parameters are extracted from the bound function itself and when necessary, type negotiation
+ is performed. For example, binding a function
+
void foo(int a, long b)
+
+// with:
+bind(&foo, _0, _0)
+
+ will result in a delegate accepting a single, optimal parameter type. The best type is computed
+ using std.typetuple.DerivedToFront, so in case of an int and a long, long will be selected. Generally, bind will try to find
+ a type that can be implicitly converted to all the other types a given dynamic parameter uses.
+
+Note:
+in case of numeric types, an explicit, but transparent (to the user) cast will be performed
+
+
+
+ Function composition works intuitively:
+
bind(&f1, bind(&f2, _0))
+
+
+ which will yield a delegate, that takes the argument, calls f2, then uses the return value of f2 to call f1. Mathematically
+ speaking, it will yield a function composition:
+
f1(f2(_0))
+
+
+ When one function is composed multiple times, it will be called multiple times - Bind does no lazy evaluation, so
+
bind(&f3, bind(&f4, _0), bind(&f4, _0))
+
+ will produce a delegate, which, upon calling, will invoke f4 two times to evaluate the arguments for f3 and then call f3
+
+
+
+
+ One another feature that bind() supports is automatic tuple expansion. It means that having functions:
+
void foo(int a, int b)
+Tuple!(int, int) bar()
+
+
+ Allows them to be bound by writing:
+
bind(&foo, bind(&bar))
+// or
+bind(&foo, tuple(23, 45))
+
+
+
+
+
template bindAlias(alias FT)
+
bindAlias() is similar to bind(), but it's more powerful. Use bindAlias() rather than bind() where possible.
+
+
+ bindAlias takes advantage of using aliases directly, thus being able to extract default values from functions and not forcing the user
+ to bind them. It doesn't, however mean that the resulting delegate can be called, omitting some of its parameters. It only means that these
+ arguments that have default values in the function provided to bindAlias don't have to be bound explicitly.
+
+
+ Additionally, bindAlias takes care of functions with out/inout parameters, by converting them to pointers internally. A function like:
+
void foo(inout a)
+
+ can be bound using:
+
int x;
+bindAlias!(foo)(&x);
+
+
+
+Note:
+there is no bind-time check for reference nullness, there is however a call-time check on all references which can be disabled
+ by using version=BindNoNullCheck or compiling in release mode.
+
@@ -469,15 +469,15 @@
alias TFoo!(int) Foo1; // (1) T is deduced to be int
alias TFoo!(char*) Foo2; // (1) T is deduced to be char*
-template TFoo(T : T*) { }
-alias TFoo!(char*) Foo3; // (2) T is deduced to be char
+template TBar(T : T*) { }
+alias TBar!(char*) Foo3; // (2) T is deduced to be char
-template TBar(D, U : D[]) { }
-alias TBar!(int, int[]) Bar1; // (2) D is deduced to be int, U is int[]
-alias TBar!(char, int[]) Bar2; // (4) error, D is both char and int
+template TAbc(D, U : D[]) { }
+alias TAbc!(int, int[]) Bar1; // (2) D is deduced to be int, U is int[]
+alias TAbc!(char, int[]) Bar2; // (4) error, D is both char and int
-template TBar(D : E*, E) { }
-alias TBar!(int*, int) Bar3; // (1) E is int
+template TDef(D : E*, E) { }
+alias TDef!(int*, int) Bar3; // (1) E is int
// (3) D is int*
@@ -559,7 +559,7 @@
{
alias Foo!(x) bar;
*bar.p = 3; // set x to 3
-int y;
+ staticint y;
alias Foo!(y) abc;
*abc.p = 3; // set y to 3
}
@@ -776,7 +776,7 @@
return x + y + z;
}
- auto plus_two = Curry(&minus, 2);
+ auto plus_two = Curry(&plus, 2);
printf("%d\n", plus_two(6, 8)); // prints 16
}
@@ -858,7 +858,7 @@
voidFoo(T : T*)(T t) { ... }
int x,y;
-Foo!(int*)(&x); // ok, T is not deduced from function argument
+Foo!(int*)(x); // ok, T is not deduced from function argument
Foo(&y); // error, T has specialization
largest hardware implemented floating
- point size (Implementation Note: 80 bits for Intel CPU's)
+ point size (Implementation Note: 80 bits for Intel CPUs)
+
@@ -459,7 +461,8 @@
The potential for bugs with that is high, as it is a common error
to accidentally omit a case, or to add a new value in one part of
the program and overlook adding a case for it in another part.
- Although D will catch this error at runtime, some prefer at least
+ Although D will catch this error at runtime by throwing
+ an instance of std.switcherr.SwitchError, some prefer at least
a warning so such errors can be caught at compile time.