int[3] s; | Static arrays
@@ -170,7 +138,7 @@
Pointers
-int* p;
+int* p;
These are simple pointers to data, analogous to C pointers.
@@ -185,7 +153,7 @@
Static Arrays
-int[3] s;
+int[3] s;
These are analogous to C arrays. Static arrays are distinguished
@@ -203,7 +171,7 @@
Dynamic Arrays
-int[] a;
+int[] a;
Dynamic arrays consist of a length and a pointer to the array data.
@@ -220,11 +188,11 @@
Prefix declarations appear before the identifier being
declared and read right to left, so:
-int[] a; // dynamic array of ints
-int[4][3] b; // array of 3 arrays of 4 ints each
-int[][5] c; // array of 5 dynamic arrays of ints.
-int*[]*[3] d; // array of 3 pointers to dynamic arrays of pointers to ints
-int[]* e; // pointer to dynamic array of ints
+int[] a; int[4][3] b; int[][5] c; int*[]*[3] d; int[]* e;
@@ -234,28 +202,28 @@
declared and read left to right.
Each group lists equivalent declarations:
-// dynamic array of ints
-int[] a;
-int a[];
-
-// array of 3 arrays of 4 ints each
-int[4][3] b;
-int[4] b[3];
-int b[3][4];
-
-// array of 5 dynamic arrays of ints.
-int[][5] c;
-int[] c[5];
-int c[5][];
-
-// array of 3 pointers to dynamic arrays of pointers to ints
-int*[]*[3] d;
-int*[]* d[3];
-int* (*d[3])[];
-
-// pointer to dynamic array of ints
-int[]* e;
-int (*e[]);
+int[] a;
+int a[];
+
+int[4][3] b;
+int[4] b[3];
+int b[3][4];
+
+int[][5] c;
+int[] c[5];
+int c[5][];
+
+int*[]*[3] d;
+int*[]* d[3];
+int* (*d[3])[];
+
+int[]* e;
+int (*e[]);
Rationale: The postfix form matches the way arrays are
@@ -274,25 +242,25 @@
The handle to an array is specified by naming the array, as
in p, s or a:
-int* p;
-int[3] s;
-int[] a;
-
-int* q;
-int[3] t;
-int[] b;
-
-p = q; // p points to the same thing q does.
-p = s; // p points to the first element of the array s.
-p = a; // p points to the first element of the array a.
+int* p;
+int[3] s;
+int[] a;
+
+int* q;
+int[3] t;
+int[] b;
+
+p = q; p = s; p = a;
-s = ...; // error, since s is a compiled in static
- // reference to an array.
+s = ...;
-a = p; // error, since the length of the array pointed
- // to by p is unknown
-a = s; // a is initialized to point to the s array
-a = b; // a points to the same array as b does
+a = p; a = s; a = b;
@@ -302,21 +270,21 @@
reference to it.
For example:
-int[10] a; // declare array of 10 ints
-int[] b;
+int[10] a; int[] b;
-b = a[1..3]; // a[1..3] is a 2 element array consisting of
- // a[1] and a[2]
-foo(b[1]); // equivalent to foo(0)
+b = a[1..3]; foo(b[1]); a[2] = 3;
-foo(b[1]); // equivalent to foo(3)
+foo(b[1]);
The [] is shorthand for a slice of the entire array.
For example, the assignments to b:
-int[10] a;
-int[] b;
+int[10] a;
+int[] b;
b = a;
b = a[];
@@ -330,8 +298,8 @@
is not only handy for referring to parts of other arrays,
but for converting pointers into bounds-checked arrays:
-int* p;
-int[] b = p[0..8];
+int* p;
+int[] b = p[0..8];
Array Copying
@@ -342,21 +310,21 @@
Array copying happens when the lvalue is a slice, and the rvalue
is an array of or pointer to the same type.
-int[3] s;
-int[3] t;
+int[3] s;
+int[3] t;
-s[] = t; // the 3 elements of t[3] are copied into s[3]
-s[] = t[]; // the 3 elements of t[3] are copied into s[3]
-s[1..2] = t[0..1]; // same as s[1] = t[0]
-s[0..2] = t[1..3]; // same as s[0] = t[1], s[1] = t[2]
-s[0..4] = t[0..4]; // error, only 3 elements in s
-s[0..2] = t; // error, different lengths for lvalue and rvalue
+s[] = t; s[] = t[]; s[1..2] = t[0..1]; s[0..2] = t[1..3]; s[0..4] = t[0..4]; s[0..2] = t;
Overlapping copies are an error:
-s[0..2] = s[1..3]; // error, overlapping copy
-s[1..3] = s[0..2]; // error, overlapping copy
+s[0..2] = s[1..3]; s[1..3] = s[0..2];
Disallowing overlapping makes it possible for more aggressive
@@ -370,11 +338,11 @@
type of the lvalue, then the lvalue's array contents
are set to the rvalue.
-int[3] s;
-int* p;
+int[3] s;
+int* p;
-s[] = 3; // same as s[0] = 3, s[1] = 3, s[2] = 3
-p[0..2] = 3; // same as p[0] = 3, p[1] = 3
+s[] = 3; p[0..2] = 3;
Array Concatenation
@@ -382,18 +350,18 @@
The binary operator ~ is the cat operator. It is used
to concatenate arrays:
-int[] a;
-int[] b;
-int[] c;
+int[] a;
+int[] b;
+int[] c;
-a = b ~ c; // Create an array from the concatenation of the
- // b and c arrays
+a = b ~ c;
Many languages overload the + operator to mean concatenation.
This confusingly leads to, does:
-"10" + 3
+"10" + 3
produce the number 13 or the string "103" as the result? It isn't
@@ -405,14 +373,14 @@
Similarly, the ~= operator means append, as in:
-a ~= b; // a becomes the concatenation of a and b
+a ~= b;
Concatenation always creates a copy of its operands, even
if one of the operands is a 0 length array, so:
-a = b; // a refers to b
-a = b ~ c[0..0]; // a refers to a copy of b
+a = b; a = b ~ c[0..0];
@@ -422,30 +390,30 @@
When more than one [] operator appears in an expression, the range
represented by all must match.
-a[1..3] = b[] + 3; // error, 2 elements not same as 3 elements
+a[1..3] = b[] + 3;
Examples:
-int[3] abc; // static array of 3 ints
-int[] def = [ 1, 2, 3 ]; // dynamic array of 3 ints
+int[3] abc; int[] def = [ 1, 2, 3 ];
-void dibb(int *array)
+void dibb(int *array)
{
- array[2]; // means same thing as *(array + 2)
- *(array + 2); // get 2nd element
+ array[2]; *(array + 2); }
-void diss(int[] array)
+void diss(int[] array)
{
- array[2]; // ok
- *(array + 2); // error, array is not a pointer
+ array[2]; *(array + 2); }
-void ditt(int[3] array)
+void ditt(int[3] array)
{
- array[2]; // ok
- *(array + 2); // error, array is not a pointer
+ array[2]; *(array + 2); }
@@ -456,7 +424,7 @@
access them via pointers to pointers resulting from "array of pointers to array" semantics.
For example, the D syntax:
-double[][] matrix;
+double[][] matrix;
declares matrix as an array of pointers to arrays. (Dynamic arrays are implemented as
@@ -465,13 +433,13 @@
array rows can sometimes point to each other! Fortunately, D static arrays, while using
the same syntax, are implemented as a fixed rectangular layout:
-double[3][3] matrix;
+double[3][3] matrix;
declares a rectangular matrix with 3 rows and 3 columns, all contiguously in memory. In
other languages, this would be called a multidimensional array and be declared as:
-double matrix[3,3];
+double matrix[3,3];
Array Length
@@ -480,27 +448,26 @@
the variable length
is implicitly declared and set to the length of the array.
-int[4] foo;
-int[] bar = foo;
-int* p = &foo[0];
+int[4] foo;
+int[] bar = foo;
+int* p = &foo[0];
-// These expressions are equivalent:
+bar[]
bar[0 .. 4]
bar[0 .. length]
bar[0 .. bar.length]
-p[0 .. length] // 'length' is not defined, since p is not an array
-bar[0]+length // 'length' is not defined, out of scope of [ ]
+p[0 .. length] bar[0]+length
-bar[length-1] // retrieves last element of the array
+bar[length-1]
Array Properties
Static array properties are:
-
-
+
.sizeof
| Returns the array length multiplied by the number of
bytes per array element.
@@ -534,8 +501,7 @@
Dynamic array properties are:
-
-
+
.sizeof
| Returns the size of the dynamic array reference,
which is 8 on 32 bit machines.
@@ -568,15 +534,15 @@
Examples:
-p.length // error, length not known for pointer
-s.length // compile time constant 3
-a.length // runtime value
+p.length s.length a.length
-p.dup // error, length not known
-s.dup // creates an array of 3 elements, copies
- // elements s into it
-a.dup // creates an array of a.length elements, copies
- // elements of a into it
+p.dup s.dup a.dup
@@ -604,24 +570,24 @@
This means that if there is an array slice immediately following the
array being resized, the resized array could overlap the slice; i.e.:
-char[] a = new char[20];
-char[] b = a[0..10];
-char[] c = a[10..20];
-
-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
+char[] a = new char[20];
+char[] b = a[0..10];
+char[] c = a[10..20];
+
+b.length = 15; b[11] = 'x';
a.length = 1;
-a.length = 20; // no net change to memory layout
+a.length = 20;
-c.length = 12; // always does a copy because c[] is not at the
- // start of a gc allocation block
-c[5] = 'y'; // does not affect contents of a[] or b[]
+c.length = 12; c[5] = 'y';
-a.length = 25; // may or may not do a copy
-a[3] = 'z'; // may or may not affect b[3] which still overlaps
- // the old a[3]
+a.length = 25; a[3] = 'z';
To guarantee copying behavior, use the .dup property to ensure
@@ -635,11 +601,11 @@
Resizing a dynamic array is a relatively expensive operation.
So, while the following method of filling an array:
-int[] array;
-while (1)
+int[] array;
+while (1)
{ c = getinput();
- if (!c)
- break;
+ if (!c)
+ break;
array.length = array.length + 1;
array[array.length - 1] = c;
}
@@ -648,13 +614,13 @@
will work, it will be inefficient. A more practical
approach would be to minimize the number of resizes:
-int[] array;
-array.length = 100; // guess
-for (i = 0; 1; i++)
+int[] array;
+array.length = 100; for (i = 0; 1; i++)
{ c = getinput();
- if (!c)
- break;
- if (i == array.length)
+ if (!c)
+ break;
+ if (i == array.length)
array.length = array.length * 2;
array[i] = c;
}
@@ -675,22 +641,22 @@
A program may not rely on array bounds checking happening, for
example, the following program is incorrect:
-try
+try
{
- for (i = 0; ; i++)
+ for (i = 0; ; i++)
{
array[i] = 5;
}
}
-catch (ArrayBoundsError)
+catch (ArrayBoundsError)
{
- // terminate loop
+ }
The loop is correctly written:
-for (i = 0; i < array.length; i++)
+for (i = 0; i < array.length; i++)
{
array[i] = 5;
}
@@ -699,8 +665,8 @@
Implementation Note: Compilers should attempt to detect
array bounds errors at compile time, for example:
-int[3] foo;
-int x = foo[3]; // error, out of bounds
+int[3] foo;
+int x = foo[3];
Insertion of array bounds checking code at runtime should be
@@ -730,14 +696,14 @@
Static Initialization of Static Arrays
-int[3] a = [ 1:2, 3 ]; // a[0] = 0, a[1] = 2, a[2] = 3
+int[3] a = [ 1:2, 3 ];
This is most handy when the array indices are given by enums:
-enum Color { red, blue, green };
+enum Color { red, blue, green };
-int value[Color.max + 1] = [ Color.blue:6, Color.green:2, Color.red:5 ];
+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.
@@ -762,8 +728,8 @@
just a dynamic array of characters. String literals become just
an easy way to write character arrays.
-char[] str;
-char[] str1 = "abc";
+char[] str;
+char[] str1 = "abc";
char[] strings are in UTF-8 format.
@@ -774,7 +740,7 @@
Strings can be copied, compared, concatenated, and appended:
str1 = str2;
-if (str1 < str3) ...
+if (str1 < str3) ...
func(str3 ~ str4);
str4 ~= str1;
@@ -787,15 +753,15 @@
A pointer to a char can be generated:
-char *p = &str[3]; // pointer to 4th element
-char *p = str; // pointer to 1st element
+char *p = &str[3]; char *p = str;
Since strings, however, are not 0 terminated in D,
when transferring a pointer
to a string to C, add a terminating 0:
-str ~= "\0";
+str ~= "\0";
The type of a string is determined by the semantic phase of
@@ -806,7 +772,7 @@
the result is an error. To
disambiguate these cases, a cast is appropriate:
-cast(wchar [])"abc" // this is an array of wchar characters
+cast(wchar [])"abc"
String literals are implicitly converted between chars,
@@ -816,16 +782,16 @@
Strings a single character in length can also be exactly
converted to a char, wchar or dchar constant:
-char c;
-wchar w;
-dchar d;
-
-c = 'b'; // c is assigned the character 'b'
-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
-d = 'd'; // d is assigned the character 'd'
+char c;
+wchar w;
+dchar d;
+
+c = 'b'; w = 'b'; w = 'bc'; w = "b"[0]; w = \r; d = 'd';
printf() and Strings
@@ -835,14 +801,14 @@
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);
+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:
-printf("the string is '%.*s'\n", str);
+printf("the string is '%.*s'\n", str);
In the future, it may be necessary to just add a new format
@@ -897,25 +863,25 @@
Associative arrays are declared by placing the KeyType
within the [] of an array declaration:
-int[char[]] b; // associative array b of ints that are
- // indexed by an array of characters.
- // The KeyType is char[]
-b["hello"] = 3; // set value associated with key "hello" to 3
-func(b["hello"]); // pass 3 as parameter to func()
+int[char[]] b; b["hello"] = 3; func(b["hello"]);
Particular keys in an associative array can be removed with the
remove function:
-b.remove("hello");
+b.remove("hello");
The InExpression yields a pointer to the value
if the key is in the associative array, or null if not:
-int* p;
-p = ("hello" in b);
-if (p != null)
+int* p;
+p = ("hello" in b);
+if (p != null)
...
@@ -927,28 +893,28 @@
data within the struct value. A custom mechanism can be used
by providing the following functions as struct members:
-uint toHash();
-int opCmp(KeyType* s);
+uint toHash();
+int opCmp(KeyType* s);
For example:
-import std.string;
+import std.string;
-struct MyString
+struct MyString
{
- char[] str;
+ char[] str;
- uint toHash()
- { uint hash;
- foreach (char c; s)
+ uint toHash()
+ { uint hash;
+ foreach (char c; s)
hash = (hash * 9) + c;
- return hash;
+ return hash;
}
- int opCmp(MyString* s)
+ int opCmp(MyString* s)
{
- return std.string.cmp(this.str, s.str);
+ return std.string.cmp(this.str, s.str);
}
}
@@ -958,7 +924,6 @@
Properties for associative arrays are:
-
.sizeof
| Returns the size of the reference to the associative
@@ -992,75 +957,75 @@
Associative Array Example: word count
-import std.file; // D file I/O
+import std.file;
-int main (char[][] args)
+int main (char[][] args)
{
- int word_total;
- int line_total;
- int char_total;
- int[char[]] dictionary;
+ int word_total;
+ int line_total;
+ int char_total;
+ int[char[]] dictionary;
- printf(" lines words bytes file\n");
- for (int i = 1; i < args.length; ++i) // program arguments
+ printf(" lines words bytes file\n");
+ for (int i = 1; i < args.length; ++i) {
- char[] input; // input buffer
- int w_cnt, l_cnt, c_cnt; // word, line, char counts
- int inword;
- int wstart;
+ char[] input; int w_cnt, l_cnt, c_cnt; int inword;
+ int wstart;
- input = std.file.read(args[i]); // read file into input[]
+ input = std.file.read(args[i]);
- foreach (char c; input)
+ foreach (char c; input)
{
- if (c == '\n')
+ if (c == '\n')
++l_cnt;
- if (c >= '0' && c <= '9')
+ if (c >= '0' && c <= '9')
{
}
- else if (c >= 'a' && c <= 'z' ||
+ else if (c >= 'a' && c <= 'z' ||
c >= 'A' && c <= 'Z')
{
- if (!inword)
+ if (!inword)
{
wstart = j;
inword = 1;
++w_cnt;
}
}
- else if (inword)
- { char[] word = input[wstart .. j];
+ else if (inword)
+ { char[] word = input[wstart .. j];
- dictionary[word]++; // increment count for word
+ dictionary[word]++; inword = 0;
}
++c_cnt;
}
- if (inword)
- { char[] word = input[wstart .. input.length];
+ if (inword)
+ { char[] word = input[wstart .. input.length];
dictionary[word]++;
}
- printf("%8ld%8ld%8ld %.*s\n", l_cnt, w_cnt, c_cnt, args[i]);
+ printf("%8ld%8ld%8ld %.*s\n", l_cnt, w_cnt, c_cnt, args[i]);
line_total += l_cnt;
word_total += w_cnt;
char_total += c_cnt;
}
- if (args.length > 2)
+ if (args.length > 2)
{
- printf("-------------------------------------\n%8ld%8ld%8ld total",
+ printf("-------------------------------------\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;
+ printf("-------------------------------------\n");
+ char[][] keys = dictionary.keys; for (int i = 0; i < keys.length; i++)
+ { char[] word;
word = keys[i];
- printf("%3d %.*s\n", dictionary[word], word);
+ printf("%3d %.*s\n", dictionary[word], word);
}
- return 0;
+ return 0;
}
diff -uNr dmd-0.156/dmd/html/d/ascii-table.html dmd-0.157/dmd/html/d/ascii-table.html
--- dmd-0.156/dmd/html/d/ascii-table.html 2006-04-26 22:34:32.000000000 +0200
+++ dmd-0.157/dmd/html/d/ascii-table.html 2006-05-08 15:25:44.000000000 +0200
@@ -25,7 +25,7 @@
| Comments
- Last update Wed Apr 26 22:34:31 2006
+ Last update Mon May 8 15:25:43 2006
@@ -57,131 +57,94 @@
· Overview
-
· D for Win32
-
· Win32 DLLs in D
-
· C .h to D Modules
-
· FAQ
-
· Style Guide
-
· Example: wc
-
· Future
-
· D Change Log
-
· Tech Tips
-
· Rationale
-
· Warnings
-
Articles
· Exception Safety
-
· Templates Revisited
-
Tools
· DMD D Compiler
-
· GDC D Compiler
-
· Linker
-
· Profiler
-
· Code Coverage
-
· DMD Script Shell
-
· Windows Debugger
-
Community
· News
-
· Forum
-
· Announcements
-
· Learn
-
· D links
-
Archives
· digitalmars.D
-
· digitalmars.D.dtl
-
· digitalmars.D.announce
-
· digitalmars.D.dwt
-
· digitalmars.D.learn
-
· digitalmars.D.bugs
-
· D.gnu
-
· Old D
-
Appendices
· Glossary
-
· Ascii Table
-
· Acknowledgements
-
|
diff -uNr dmd-0.156/dmd/html/d/attribute.html dmd-0.157/dmd/html/d/attribute.html
--- dmd-0.156/dmd/html/d/attribute.html 2006-04-26 22:34:30.000000000 +0200
+++ dmd-0.157/dmd/html/d/attribute.html 2006-05-08 15:25:42.000000000 +0200
@@ -25,7 +25,7 @@
| Comments
- Last update Wed Apr 26 22:34:29 2006
+ Last update Mon May 8 15:25:41 2006
@@ -57,105 +57,73 @@
· Lexical
-
· Modules
-
· Declarations
-
· Types
-
· Properties
-
· Attributes
-
· Pragmas
-
· Expressions
-
· Statements
-
· Arrays
-
· Structs & Unions
-
· Classes
-
· Interfaces
-
· Enums
-
· Functions
-
· Operator Overloading
-
· Templates
-
· Mixins
-
· Contracts
-
· Conditional Compilation
-
· Handling errors
-
· Garbage Collection
-
· Memory Management
-
· Floating Point
-
· Inline Assembler
-
· Documentation Comments
-
· Interfacing To C
-
· Portability Guide
-
· Embedding D in HTML
-
· Named Character Entities
-
· Application Binary Interface
-
Attributes
-
-AttributeSpecifier:
+AttributeSpecifier:
Attribute :
Attribute DeclarationBlock
@@ -182,7 +150,6 @@
{ DeclDefs }
-
Attributes are a way to modify one or more declarations.
The general forms are:
@@ -226,8 +193,7 @@
-
-LinkageAttribute:
+LinkageAttribute:
extern
extern ( LinkageType )
@@ -239,7 +205,6 @@
Pascal
-
D provides an easy way to call C functions and operating
system API functions, as compatibility with both is essential.
The LinkageType is case sensitive, and is meant to be
@@ -254,41 +219,39 @@
C function calling conventions are
specified by:
-extern (C):
- int foo(); // call foo() with C conventions
+extern (C):
+ int foo();
D conventions are:
-extern (D):
+extern (D):
or:
-extern:
+extern:
Windows API conventions are:
-extern (Windows):
- void *VirtualAlloc(
- void *lpAddress,
- uint dwSize,
- uint flAllocationType,
- uint flProtect
+extern (Windows):
+ void *VirtualAlloc(
+ void *lpAddress,
+ uint dwSize,
+ uint flAllocationType,
+ uint flProtect
);
-
-AlignAttribute:
+AlignAttribute:
align
align ( Integer )
-
Specifies the alignment of struct members. align by itself
sets it to the default, which matches the default member alignment
of the companion C compiler. Integer specifies the alignment
@@ -299,9 +262,9 @@
Matching the behavior of the companion C compiler can have some
surprising results, such as the following for Digital Mars C++:
-struct S
-{ align(4) byte a; // placed at offset 0
- align(4) byte b; // placed at offset 1
+struct S
+{ align(4) byte a; align(4) byte b; }
@@ -309,11 +272,11 @@
the same thing as binary compatibility across diverse platforms.
For that, use packed structs:
-align (1) struct S
-{ byte a; // placed at offset 0
- byte[3] filler1;
- byte b; // placed at offset 4
- byte[3] filler2;
+align (1) struct S
+{ byte a; byte[3] filler1;
+ byte b; byte[3] filler2;
}
@@ -341,9 +304,9 @@
if any code refers to deprecated
declarations:
-deprecated
+deprecated
{
- void oldFoo();
+ void oldFoo();
}
@@ -393,19 +356,17 @@
-
-const
+const
-
The const attribute declares constants that can be
evaluated at compile time. For example:
-const int foo = 7;
+const int foo = 7;
-const
+const
{
- double bar = foo + 6;
+ double bar = foo + 6;
}
@@ -413,45 +374,45 @@
in a constructor (for class fields) or in a static constructor
(for static class members, or module variable declarations).
-const int x;
-const int y;
+const int x;
+const int y;
-static this()
+static this()
{
- x = 3; // ok
- // error: y not initialized
+ x = 3; }
-void foo()
+void foo()
{
- x = 4; // error, x is const and not in static constructor
+ x = 4; }
-class C
+class C
{
- const int a;
- const int b;
- static const int c;
- static const int d;
-
- this()
- { a = 3; // ok
- a = 4; // ok, multiple initialization allowed
- C p = this;
- p.a = 4; // error, only members of this instance
- c = 5; // error, should initialize in static constructor
- // error, b is not initialized
+ const int a;
+ const int b;
+ static const int c;
+ static const int d;
+
+ this()
+ { a = 3; a = 4; C p = this;
+ p.a = 4; c = 5; }
- this(int x);
+ this(int x);
{
- this(); // ok, forwarding constructor
+ this(); }
- static this()
+ static this()
{
- c = 3; // ok
- // error, d is not initialized
+ c = 3; }
}
@@ -464,11 +425,9 @@
-
-override
+override
-
The override attribute applies to virtual functions.
It means that the function must override a function with the
same name and parameters in a base class. The override attribute
@@ -476,75 +435,70 @@
gets its parameters changed, and all derived classes need to have
their overriding functions updated.
-class Foo
+class Foo
{
- int bar();
- int abc(int x);
+ int bar();
+ int abc(int x);
}
-class Foo2 : Foo
+class Foo2 : Foo
{
- override
+ override
{
- int bar(char c); // error, no bar(char) in Foo
- int abc(int x); // ok
+ int bar(char c); int abc(int x); }
}
Static Attribute
-
-static
+static
-
The static attribute applies to functions and data.
It means that the declaration does not apply to a particular
instance of an object, but to the type of the object. In
other words, it means there is no this reference.
static is ignored when applied to other declarations.
-class Foo
+class Foo
{
- static int bar() { return 6; }
- int foobar() { return 7; }
+ static int bar() { return 6; }
+ int foobar() { return 7; }
}
...
-Foo f = new Foo;
-Foo.bar(); // produces 6
-Foo.foobar(); // error, no instance of Foo
-f.bar(); // produces 6;
-f.foobar(); // produces 7;
+Foo f = new Foo;
+Foo.bar(); Foo.foobar(); f.bar(); f.foobar();
- Static functions are never virtual.
-
-
- Static data has only one instance for the entire program,
+ Static functions are never virtual.
+
+ Static data has only one instance for the entire program,
not once per object.
-
-
- Static does not have the additional C meaning of being local
+
+ Static does not have the additional C meaning of being local
to a file. Use the private attribute in D to achieve that.
For example:
+
-module foo;
-int x = 3; // x is global
-private int y = 4; // y is local to module foo
+module foo;
+int x = 3; private int y = 4;
-
-auto
+auto
-
- The auto attribute is used for local variables and for class
+ The auto attribute is used for local variables and for class
declarations. For class declarations, the auto attribute creates
an auto class.
For local declarations, auto implements the RAII (Resource
@@ -553,40 +507,35 @@
reference to it goes out of scope. The destructor is called even
if the scope is exited via a thrown exception, thus auto
is used to guarantee cleanup.
-
-
- If there is more than one auto variable going out of scope
+
+ If there is more than one auto variable going out of scope
at the same point, then the destructors are called in the reverse
order that the variables were constructed.
-
-
- Auto cannot be applied to globals, statics, data members, inout
+
+ Auto cannot be applied to globals, statics, data members, inout
or out parameters. Arrays of autos are not allowed, and auto
function return values are not allowed. Assignment to an auto,
other than initialization, is not allowed.
Rationale: These restrictions may get relaxed in the future
if a compelling reason to appears.
-
+
- If a class is abstract, it cannot be instantiated
+ If a class is abstract, it cannot be instantiated
directly. It can only be instantiated as a base class of
another, non-abstract, class.
-
-
- Classes become abstract if they are defined within an
+
+ Classes become abstract if they are defined within an
abstract attribute, or if any of the virtual member functions
within it are declared as abstract.
-
-
- Non-virtual functions cannot be declared as abstract.
-
-
- Functions declared as abstract can still have function
+
+ Non-virtual functions cannot be declared as abstract.
+
+ Functions declared as abstract can still have function
bodies. This is so that even though they must be overridden,
they can still provide 'base class functionality.'
-
+
diff -uNr dmd-0.156/dmd/html/d/builtin.html dmd-0.157/dmd/html/d/builtin.html
--- dmd-0.156/dmd/html/d/builtin.html 2006-04-26 22:34:32.000000000 +0200
+++ dmd-0.157/dmd/html/d/builtin.html 2006-05-08 15:25:44.000000000 +0200
@@ -25,7 +25,7 @@
| Comments
- Last update Wed Apr 26 22:34:31 2006
+ Last update Mon May 8 15:25:43 2006
@@ -57,28 +57,20 @@
· D vs C/C++/C#/Java
-
· Rationale for Builtins
-
· Converting C to D
-
· Converting C++ to D
-
· The C Preprocessor vs D
-
· D strings vs C++ std::string
-
· D complex vs C++ std::complex
-
· D Contract Programming vs C++
-
|
@@ -209,14 +201,14 @@
int value is naturally written
as:
-int[T] foo;
+int[T] foo;
rather than:
-import std.associativeArray;
+import std.associativeArray;
...
-std.associativeArray.AA!(T, int) foo;
+std.associativeArray.AA!(T, int) foo;
Builtin associative arrays also offer the possibility of having
@@ -238,7 +230,7 @@
far preferable than writing:
-c = (complex!(double)(6,2) + complex!(double)(-1,3)) / complex!(double)(0,3);
+c = (complex!(double)(6,2) + complex!(double)(-1,3)) / complex!(double)(0,3);
? It's no contest.
diff -uNr dmd-0.156/dmd/html/d/changelog.html dmd-0.157/dmd/html/d/changelog.html
--- dmd-0.156/dmd/html/d/changelog.html 2006-04-28 00:12:32.000000000 +0200
+++ dmd-0.157/dmd/html/d/changelog.html 2006-05-10 11:39:36.000000000 +0200
@@ -25,7 +25,7 @@
| Comments
- Last update Fri Apr 28 00:12:31 2006
+ Last update Wed May 10 11:39:33 2006
@@ -57,131 +57,94 @@
· Overview
-
· D for Win32
-
· Win32 DLLs in D
-
· C .h to D Modules
-
· FAQ
-
· Style Guide
-
· Example: wc
-
· Future
-
· D Change Log
-
· Tech Tips
-
· Rationale
-
· Warnings
-
Articles
· Exception Safety
-
· Templates Revisited
-
Tools
· DMD D Compiler
-
· GDC D Compiler
-
· Linker
-
· Profiler
-
· Code Coverage
-
· DMD Script Shell
-
· Windows Debugger
-
Community
· News
-
· Forum
-
· Announcements
-
· Learn
-
· D links
-
Archives
· digitalmars.D
-
· digitalmars.D.dtl
-
· digitalmars.D.announce
-
· digitalmars.D.dwt
-
· digitalmars.D.learn
-
· digitalmars.D.bugs
-
· D.gnu
-
· Old D
-
Appendices
· Glossary
-
· Ascii Table
-
· Acknowledgements
-
|
@@ -192,6 +155,10 @@
+ - What's new for D 0.157
+
+ - What's new for D 0.156
+
- What's new for D 0.155
- What's new for D 0.154
@@ -413,6 +380,46 @@
+
+
+
+May 10, 2006
+
+New/Changed Features
+
+ - Partial Dwarf symbol debug info now generated for Linux.
+ - Improved
+ dumpobj's
+ handling of Dwarf symbolic debug info.
+
+
+Bugs Fixed
+
+ - Applied Dave Fladebo's fix to gc internal sorting problem.
+
+
+
+
+
+
+
+Apr 28, 2006
+
+
+ Bugs Fixed
+
+
+
+
+
What's New for
D 0.155
@@ -664,9 +671,9 @@
New/Changed Features
- - Changed on_scope_exit to scope(exit)
- - Changed on_scope_success to scope(success)
- - Changed on_scope_failure to scope(failure)
+ - Changed on_scope_exit to scope(exit)
+ - Changed on_scope_success to scope(success)
+ - Changed on_scope_failure to scope(failure)
- Changed IfStatement to allow: (auto v = expression),
and (type v = expression) forms.
- & | ^ &= |= ^= ! && || ?: are now only
@@ -1736,6 +1743,7 @@
- fix File.open() error message to say "Cannot open or create file"
+
Bugs Fixed
@@ -1965,6 +1973,7 @@
Fixed major bug in the linux version.
+
- Improved error message for overloaded function mismatches.
- Added man pages to \dmd\man\man1 (thanks to Anders F Bjorklund)
@@ -2076,6 +2085,7 @@
uncommented MmFileStream and cleaned it up to use MmFile's mode property.
+
Bugs Fixed
diff -uNr dmd-0.156/dmd/html/d/class.html dmd-0.157/dmd/html/d/class.html
--- dmd-0.156/dmd/html/d/class.html 2006-04-26 22:34:32.000000000 +0200
+++ dmd-0.157/dmd/html/d/class.html 2006-05-08 15:25:44.000000000 +0200
@@ -25,7 +25,7 @@
| Comments
- Last update Wed Apr 26 22:34:30 2006
+ Last update Mon May 8 15:25:42 2006
@@ -57,97 +57,66 @@
· Lexical
-
· Modules
-
· Declarations
-
· Types
-
· Properties
-
· Attributes
-
· Pragmas
-
· Expressions
-
· Statements
-
· Arrays
-
· Structs & Unions
-
· Classes
-
· Interfaces
-
· Enums
-
· Functions
-
· Operator Overloading
-
· Templates
-
· Mixins
-
· Contracts
-
· Conditional Compilation
-
· Handling errors
-
· Garbage Collection
-
· Memory Management
-
· Floating Point
-
· Inline Assembler
-
· Documentation Comments
-
· Interfacing To C
-
· Portability Guide
-
· Embedding D in HTML
-
· Named Character Entities
-
· Application Binary Interface
-
@@ -173,8 +142,7 @@
A class declaration is defined:
-
-ClassDeclaration:
+ClassDeclaration:
class Identifier BaseClassListopt ClassBody
BaseClassList:
@@ -221,7 +189,6 @@
ClassDeallocator
-
Classes consist of:
@@ -249,7 +216,7 @@
A class is defined:
-class Foo
+class Foo
{
... members ...
}
@@ -259,12 +226,12 @@
definition.
It is also not possible to declare a variable var like:
-class Foo { } var;
+class Foo { } var;
Instead:
-class Foo { }
+class Foo { }
Foo var;
@@ -296,17 +263,17 @@
type of the class, not expressions which produce the type of
the field itself:
-class Foo
+class Foo
{
- int x;
+ int x;
}
...
-void test(Foo foo)
+void test(Foo foo)
{
size_t o;
- o = Foo.x.offsetof; // yields 8
- o = foo.x.offsetof; // error, .offsetof an int type
+ o = Foo.x.offsetof; o = foo.x.offsetof; }
@@ -318,12 +285,10 @@
-
-Constructor:
+Constructor:
this Parameters FunctionBody
-
Members are always initialized to the default initializer
for their type, which is usually 0 for integer types and
NAN for floating point types.
@@ -334,11 +299,11 @@
there can be a static initializer to be
used instead of the default:
-class Abc
+class Abc
{
- int a; // default initializer for a is 0
- long b = 7; // default initializer for b is 7
- float f; // default initializer for f is NAN
+ int a; long b = 7; float f; }
@@ -349,12 +314,12 @@
Constructors are defined with a function name of this
and having no return value:
-class Foo
+class Foo
{
- this(int x) // declare constructor for Foo
+ this(int x) { ...
}
- this()
+ this()
{ ...
}
}
@@ -363,15 +328,15 @@
Base class construction is done by calling the base class
constructor by the name super:
-class A { this(int y) { } }
+class A { this(int y) { } }
-class B : A
+class B : A
{
- int j;
- this()
+ int j;
+ this()
{
...
- super(3); // call base constructor A.this(3)
+ super(3); ...
}
}
@@ -380,16 +345,16 @@
Constructors can also call other constructors for the same class
in order to share common initializations:
-class C
+class C
{
- int j;
- this()
+ int j;
+ this()
{
...
}
- this(int i)
+ this(int i)
{
- this();
+ this();
j = i;
}
}
@@ -403,7 +368,7 @@
If there is no constructor for a class, but there is a constructor
for the base class, a default constructor of the form:
-this() { }
+this() { }
is implicitly generated.
@@ -414,23 +379,23 @@
- It is illegal for constructors to mutually call each other:
-
this() { this(1); }
-this(int i) { this(); } // illegal, cyclic constructor calls
+this() { this(1); }
+this(int i) { this(); }
- If any constructor call appears inside a constructor, any
path through the constructor must make exactly one constructor
call:
-
this() { a || super(); } // illegal
+this() { a || super(); }
-this() { this(1) || super(); } // ok
+this() { this(1) || super(); }
-this()
+this()
{
- for (...)
+ for (...)
{
- super(); // illegal, inside loop
+ super(); }
}
@@ -443,7 +408,7 @@
Instances of class objects are created with NewExpressions:
-A a = new A(3);
+A a = new A(3);
The following steps happen:
@@ -474,19 +439,17 @@
-
-Destructor:
+Destructor:
~this() FunctionBody
-
The garbage collector calls the destructor function when the object
is deleted. The syntax
is:
-class Foo
+class Foo
{
- ~this() // destructor for Foo
+ ~this() {
}
}
@@ -532,12 +495,10 @@
-
-StaticConstructor:
+StaticConstructor:
static this() FunctionBody
-
A static constructor is defined as a function that performs
initializations before the
main() function gets control. Static constructors are used to
@@ -552,10 +513,10 @@
this stems from not
having good control over exactly when the code is executed, for example:
-class Foo
+class Foo
{
- static int a = b + 1;
- static int b = a * 2;
+ static int a = b + 1;
+ static int b = a * 2;
}
@@ -577,16 +538,16 @@
initialization is performed by a static constructor, defined with
a special syntax static this().
-class Foo
+class Foo
{
- static int a; // default initialized to 0
- static int b = 1;
- static int c = b + a; // error, not a constant initializer
+ static int a; static int b = 1;
+ static int c = b + a;
- static this() // static constructor
+ static this() {
- a = b + 1; // a is set to 2
- b = a * 2; // b is set to 4
+ a = b + 1; b = a * 2; }
}
@@ -609,33 +570,31 @@
The static in the static constructor declaration is not
an attribute, it must appear immediately before the this:
-class Foo
+class Foo
{
- static this() { ... } // a static constructor
- static private this() { ... } // not a static constructor
- static
+ static this() { ... } static private this() { ... } static
{
- this() { ... } // not a static constructor
+ this() { ... } }
- static:
- this() { ... } // not a static constructor
+ static:
+ this() { ... } }
-
-StaticDestructor:
+StaticDestructor:
static ~this() FunctionBody
-
A static destructor is defined as a special static function with the
syntax static ~this().
-class Foo
+class Foo
{
- static ~this() // static destructor
+ static ~this() {
}
}
@@ -652,27 +611,25 @@
The static in the static denstructor declaration is not
an attribute, it must appear immediately before the ~this:
-class Foo
+class Foo
{
- static ~this() { ... } // a static destructor
- static private ~this() { ... } // not a static destructor
- static
+ static ~this() { ... } static private ~this() { ... } static
{
- ~this() { ... } // not a static destructor
+ ~this() { ... } }
- static:
- ~this() { ... } // not a static destructor
+ static:
+ ~this() { ... } }
-
-ClassInvariant:
+ClassInvariant:
invariant FunctionBody
-
Class invariants are used to specify characteristics of a class that always
must be true (except while executing a member function). For example, a
class representing a date might have an invariant that the day must be 1..31
@@ -680,15 +637,15 @@
-class Date
+class Date
{
- int day;
- int hour;
+ int day;
+ int hour;
- invariant
+ invariant
{
- assert(1 <= day && day <= 31);
- assert(0 <= hour && hour < 24);
+ assert(1 <= day && day <= 31);
+ assert(0 <= hour && hour < 24);
}
}
@@ -706,15 +663,15 @@
Doing so will result in a stack overflow, as the invariant will wind
up being called in an infinitely recursive manner.
-class Foo
+class Foo
{
- public void f() { }
- private void g() { }
+ public void f() { }
+ private void g() { }
- invariant
+ invariant
{
- f(); // error, cannot call public member function from invariant
- g(); // ok, g() is not public
+ f(); g(); }
}
@@ -725,7 +682,7 @@
Date mydate;
...
-assert(mydate); // check that class Date invariant holds
+assert(mydate);
If the invariant fails, it throws an InvariantException .
@@ -741,12 +698,10 @@
-
-UnitTest:
+UnitTest:
unittest FunctionBody
-
Unit tests are a series of test cases applied to a class to determine
if it is working properly. Ideally, unit tests should be run every
time a program is compiled. The best way to make sure that unit
@@ -757,7 +712,7 @@
Classes can have a special member function called:
-unittest
+unittest
{
...test code...
}
@@ -772,30 +727,28 @@
For example, given a class Sum that is used to add two values:
-class Sum
+class Sum
{
- int add(int x, int y) { return x + y; }
+ int add(int x, int y) { return x + y; }
- unittest
+ unittest
{
- Sum sum = new Sum;
- assert(sum.add(3,4) == 7);
- assert(sum.add(-2,0) == -2);
+ Sum sum = new Sum;
+ assert(sum.add(3,4) == 7);
+ assert(sum.add(-2,0) == -2);
}
}
-
-ClassAllocator:
+ClassAllocator:
new Parameters FunctionBody
-
A class member function of the form:
-new(uint size)
+new(uint size)
{
...
}
@@ -808,7 +761,7 @@
determined by the usual function overloading rules.
When a new expression:
-new Foo;
+new Foo;
is executed, and Foo is a class that has
@@ -823,11 +776,11 @@
additional arguments are specified within parentheses after
the new in the NewExpression:
-class Foo
+class Foo
{
- this(char[] a) { ... }
+ this(char[] a) { ... }
- new(uint size, int x, int y)
+ new(uint size, int x, int y)
{
...
}
@@ -835,7 +788,7 @@
...
-new(1,2) Foo(a); // calls new(Foo.sizeof,1,2)
+new(1,2) Foo(a);
Derived classes inherit any allocator from their base class,
@@ -846,15 +799,13 @@
-
-ClassDeallocator:
+ClassDeallocator:
delete Parameters FunctionBody
-
A class member function of the form:
-delete(void *p)
+delete(void *p)
{
...
}
@@ -865,7 +816,7 @@
Only one can be specified for a class.
When a delete expression:
-delete f;
+delete f;
is executed, and f is a reference to a class instance that has
@@ -885,7 +836,7 @@
An auto class is a class with the auto attribute, as in:
-auto class Foo { ... }
+auto class Foo { ... }
The auto characteristic is inherited, so if any classes derived
@@ -895,12 +846,12 @@
An auto class reference can only appear as a function local variable.
It must be declared as being auto:
-auto class Foo { ... }
+auto class Foo { ... }
-void func()
+void func()
{
- Foo f; // error, reference to auto class must be auto
- auto Foo g = new Foo(); // correct
+ Foo f; auto Foo g = new Foo(); }
@@ -915,27 +866,27 @@
A nested class has access to the variables and other symbols
of the classes and functions it is nested inside:
-class Outer
+class Outer
{
- int m;
+ int m;
- class Inner
+ class Inner
{
- int foo()
+ int foo()
{
- return m; // Ok to access member of Outer
+ return m; }
}
}
-void func()
-{ int m;
+void func()
+{ int m;
- class Inner
+ class Inner
{
- int foo()
+ int foo()
{
- return m; // Ok to access local variable m of func()
+ return m; }
}
}
@@ -945,31 +896,31 @@
not access variables of the enclosing scope that are local to the
stack or need a this:
-class Outer
+class Outer
{
- int m;
- static int n;
+ int m;
+ static int n;
- static class Inner
+ static class Inner
{
- int foo()
+ int foo()
{
- return m; // Error, Inner is static and m needs a this
- return n; // Ok, n is static
+ return m; return n; }
}
}
-void func()
-{ int m;
- static int n;
+void func()
+{ int m;
+ static int n;
- static class Inner
+ static class Inner
{
- int foo()
+ int foo()
{
- return m; // Error, Inner is static and m is local to the stack
- return n; // Ok, n is static
+ return m; return n; }
}
}
@@ -988,22 +939,22 @@
A non-static nested class can only be instantiated when the necessary
context pointer information is available:
-class Outer
+class Outer
{
- class Inner { }
+ class Inner { }
- static class SInner { }
+ static class SInner { }
}
-void func()
+void func()
{
- class Nested { }
+ class Nested { }
- Outer o = new Outer; // Ok
- Outer.Inner oi = new Outer.Inner; // Error, no 'this' for Outer
- Outer.SInner os = new Outer.SInner; // Ok
+ Outer o = new Outer; Outer.Inner oi = new Outer.Inner; Outer.SInner os = new Outer.SInner;
- Nested n = new Nested; // Ok
+ Nested n = new Nested; }
@@ -1011,29 +962,29 @@
of its enclosing function, that access becomes invalid once
the enclosing function exits:
-class Base
+class Base
{
- int foo() { return 1; }
+ int foo() { return 1; }
}
Base func()
-{ int m = 3;
+{ int m = 3;
- class Nested : Base
+ class Nested : Base
{
- int foo() { return m; }
+ int foo() { return m; }
}
- Base b = new Nested;
+ Base b = new Nested;
- assert(b.foo() == 3); // Ok, func() is still active
- return b;
+ assert(b.foo() == 3); return b;
}
-int test()
+int test()
{
Base b = func();
- return b.foo(); // Error, func().m is undefined
+ return b.foo(); }
@@ -1041,31 +992,31 @@
is to make copies of the needed variables within the nested class's
constructor:
-class Base
+class Base
{
- int foo() { return 1; }
+ int foo() { return 1; }
}
Base func()
-{ int m = 3;
+{ int m = 3;
- class Nested : Base
- { int m_;
+ class Nested : Base
+ { int m_;
- this() { m_ = m;
- int foo() { return m_; }
+ this() { m_ = m;
+ int foo() { return m_; }
}
- Base b = new Nested;
+ Base b = new Nested;
- assert(b.foo() == 3); // Ok, func() is still active
- return b;
+ assert(b.foo() == 3); return b;
}
-int test()
+int test()
{
Base b = func();
- return b.foo(); // Ok, using cached copy of func().m
+ return b.foo(); }
@@ -1074,18 +1025,16 @@
An anonymous nested class is both defined and instantiated with
a NewAnonClassExpression:
-
-NewAnonClassExpression:
+NewAnonClassExpression:
new ()ArgumentListopt class ()ArgumentListopt SuperClassopt InterfaceClassesopt ClassBody
-
which is equivalent to:
-class Identifier : SuperClass InterfaceClasses
+class Identifier : SuperClass InterfaceClasses
ClassBody
-new (ArgumentList) Identifier (ArgumentList);
+new (ArgumentList) Identifier (ArgumentList);
where Identifier is the name generated for the anonymous
diff -uNr dmd-0.156/dmd/html/d/code_coverage.html dmd-0.157/dmd/html/d/code_coverage.html
--- dmd-0.156/dmd/html/d/code_coverage.html 2006-04-26 22:34:32.000000000 +0200
+++ dmd-0.157/dmd/html/d/code_coverage.html 2006-05-08 15:25:44.000000000 +0200
@@ -24,7 +24,7 @@
| D
| Comments
- Last update Wed Apr 26 22:34:31 2006
+ Last update Mon May 8 15:25:43 2006
@@ -56,131 +56,94 @@
· Overview
-
· D for Win32
-
· Win32 DLLs in D
-
· C .h to D Modules
-
· FAQ
-
· Style Guide
-
· Example: wc
-
· Future
-
· D Change Log
-
· Tech Tips
-
· Rationale
-
· Warnings
-
Articles
· Exception Safety
-
· Templates Revisited
-
Tools
· DMD D Compiler
-
· GDC D Compiler
-
· Linker
-
· Profiler
-
· Code Coverage
-
· DMD Script Shell
-
· Windows Debugger
-
Community
· News
-
· Forum
-
· Announcements
-
· Learn
-
· D links
-
Archives
· digitalmars.D
-
· digitalmars.D.dtl
-
· digitalmars.D.announce
-
· digitalmars.D.dwt
-
· digitalmars.D.learn
-
· digitalmars.D.bugs
-
· D.gnu
-
· Old D
-
Appendices
· Glossary
-
· Ascii Table
-
· Acknowledgements
-
|
@@ -255,32 +218,32 @@
to listing (.lst) files.
For example, consider the Sieve program:
-/* Eratosthenes Sieve prime number calculation. */
+
bit flags[8191];
-int main()
-{ int i, prime, k, count, iter;
+int main()
+{ int i, prime, k, count, iter;
- printf("10 iterations\n");
- for (iter = 1; iter <= 10; iter++)
+ printf("10 iterations\n");
+ for (iter = 1; iter <= 10; iter++)
{ count = 0;
- flags[] = true;
- for (i = 0; i < flags.length; i++)
- { if (flags[i])
+ flags[] = true;
+ for (i = 0; i < flags.length; i++)
+ { if (flags[i])
{ prime = i + i + 3;
k = i + prime;
- while (k < flags.length)
+ while (k < flags.length)
{
- flags[k] = false;
+ flags[k] = false;
k += prime;
}
count += 1;
}
}
}
- printf ("\n%d primes\n", count);
- return 0;
+ printf ("\n%d primes\n", count);
+ return 0;
}
diff -uNr dmd-0.156/dmd/html/d/comparison.html dmd-0.157/dmd/html/d/comparison.html
--- dmd-0.156/dmd/html/d/comparison.html 2006-04-26 22:34:32.000000000 +0200
+++ dmd-0.157/dmd/html/d/comparison.html 2006-05-08 15:25:44.000000000 +0200
@@ -24,7 +24,7 @@
| D
| Comments
- Last update Wed Apr 26 22:34:31 2006
+ Last update Mon May 8 15:25:43 2006
@@ -56,42 +56,36 @@
· D vs C/C++/C#/Java
-
· Rationale for Builtins
-
· Converting C to D
-
· Converting C++ to D
-
· The C Preprocessor vs D
-
· D strings vs C++ std::string
-
· D complex vs C++ std::complex
-
· D Contract Programming vs C++
-
D
+
vs Other Languages
-
- To D, or not to D. -- Willeam NerdSpeare
+ To D, or not to D. -- Willeam NerdSpeare
+
This table is a quick and rough comparison of various features of
D
+
with other languages it is frequently compared with.
While many capabilities are available with standard libraries, this
table is for features built in to the core language itself.
@@ -108,6 +102,7 @@
Feature
| D
+
| C
| C++
diff -uNr dmd-0.156/dmd/html/d/cppcomplex.html dmd-0.157/dmd/html/d/cppcomplex.html
--- dmd-0.156/dmd/html/d/cppcomplex.html 2006-04-26 22:34:30.000000000 +0200
+++ dmd-0.157/dmd/html/d/cppcomplex.html 2006-05-08 15:25:42.000000000 +0200
@@ -25,7 +25,7 @@
| Comments
- Last update Wed Apr 26 22:34:29 2006
+ Last update Mon May 8 15:25:41 2006
@@ -57,28 +57,20 @@
· D vs C/C++/C#/Java
-
· Rationale for Builtins
-
· Converting C to D
-
· Converting C++ to D
-
· The C Preprocessor vs D
-
· D strings vs C++ std::string
-
· D complex vs C++ std::complex
-
· D Contract Programming vs C++
-
|
@@ -99,12 +91,12 @@
C++ has no distinct imaginary type. D has 3 complex types and 3
imaginary types:
-cfloat
-cdouble
-creal
-ifloat
-idouble
-ireal
+cfloat
+cdouble
+creal
+ifloat
+idouble
+ireal
A C++ complex number can interact with an arithmetic literal, but
@@ -119,9 +111,9 @@
In D, an imaginary numeric literal has the 'i' suffix.
The corresponding code would be the more natural:
-creal a = 5; // a = 5 + 0i
-ireal b = 7i; // b = 7i
-c = a + b + 7i; // c = 5 + 14i
+creal a = 5; ireal b = 7i; c = a + b + 7i;
For more involved expressions involving constants:
@@ -150,7 +142,7 @@
on the 0 real part. For example, adding two imaginary numbers
in D is one add:
-ireal a, b, c;
+ireal a, b, c;
c = a + b;
@@ -190,8 +182,8 @@
To avoid these efficiency concerns in C++, one could simulate
an imaginary number using a double. For example, given the D:
-cdouble c;
-idouble im;
+cdouble c;
+idouble im;
c *= im;
@@ -226,6 +218,7 @@
Arithmetic; it needs the Imaginary type."
+
The semantic problems are:
|
@@ -162,19 +154,19 @@
Consider a class invariant in D:
-class A
+class A
{
- invariant() { ...contracts... }
+ invariant() { ...contracts... }
- this() { ... } // constructor
- ~this() { ... } // destructor
+ this() { ... } ~this() { ... }
- void foo() { ... } // public member function
+ void foo() { ... } }
-class B : A
+class B : A
{
- invariant() { ...contracts... }
+ invariant() { ...contracts... }
...
}
@@ -292,10 +284,10 @@
Consider the following in D:
-void foo()
- in { ...preconditions... }
- out { ...postconditions... }
- body
+void foo()
+ in { ...preconditions... }
+ out { ...postconditions... }
+ body
{
...implementation...
}
@@ -344,15 +336,15 @@
Let's add a return value to foo() that needs to be checked in
the postconditions. In D:
-int foo()
- in { ...preconditions... }
- out (result) { ...postconditions... }
- body
+int foo()
+ in { ...preconditions... }
+ out (result) { ...postconditions... }
+ body
{
...implementation...
- if (...)
- return bar();
- return 3;
+ if (...)
+ return bar();
+ return 3;
}
@@ -384,15 +376,15 @@
Now add a couple parameters to foo(). In D:
-int foo(int a, int b)
- in { ...preconditions... }
- out (result) { ...postconditions... }
- body
+int foo(int a, int b)
+ in { ...preconditions... }
+ out (result) { ...postconditions... }
+ body
{
...implementation...
- if (...)
- return bar();
- return 3;
+ if (...)
+ return bar();
+ return 3;
}
@@ -432,23 +424,23 @@
Consider the use of preconditions and postconditions for a
polymorphic function in D:
-class A
+class A
{
- void foo()
- in { ...Apreconditions... }
- out { ...Apostconditions... }
- body
+ void foo()
+ in { ...Apreconditions... }
+ out { ...Apostconditions... }
+ body
{
...implementation...
}
}
-class B : A
+class B : A
{
- void foo()
- in { ...Bpreconditions... }
- out { ...Bpostconditions... }
- body
+ void foo()
+ in { ...Bpreconditions... }
+ out { ...Bpostconditions... }
+ body
{
...implementation...
}
diff -uNr dmd-0.156/dmd/html/d/cppstrings.html dmd-0.157/dmd/html/d/cppstrings.html
--- dmd-0.156/dmd/html/d/cppstrings.html 2006-04-26 22:34:30.000000000 +0200
+++ dmd-0.157/dmd/html/d/cppstrings.html 2006-05-08 17:32:04.000000000 +0200
@@ -26,7 +26,7 @@
" title="Read/write comments and feedback">Comments
- Last update Wed Apr 26 22:34:29 2006
+ Last update Mon May 8 17:32:03 2006
@@ -58,28 +58,20 @@
· D vs C/C++/C#/Java
-
· Rationale for Builtins
-
· Converting C to D
-
· Converting C++ to D
-
· The C Preprocessor vs D
-
· D strings vs C++ std::string
-
· D complex vs C++ std::complex
-
· D Contract Programming vs C++
-
|
@@ -92,19 +84,17 @@
Concatenation Operator
- C++ Strings are stuck with overloading existing operators. The
+C++ Strings are stuck with overloading existing operators. The
obvious choice for concatenation is += and +.
But someone just looking at the code will see + and think "addition".
He'll have to look up the types (and types are frequently buried
behind multiple typedef's) to see that it's a string type, and
it's not adding strings but concatenating them.
-
-
- Additionally, if one has an array of floats, is '+' overloaded to
+
+Additionally, if one has an array of floats, is '+' overloaded to
be the same as a vector addition, or an array concatenation?
-
-
- In D, these problems are avoided by introducing a new binary
+
+In D, these problems are avoided by introducing a new binary
operator ~ as the concatenation operator. It works with
arrays (of which strings are a subset). ~= is the corresponding
append operator. ~ on arrays of floats would concatenate them,
@@ -112,166 +102,188 @@
for orthogonality and consistency in the treatment of arrays.
(In D, strings are simply arrays of characters, not a special
type.)
+
Interoperability With C String Syntax
- Overloading of operators only really works if one of the operands
+Overloading of operators only really works if one of the operands
is overloadable. So the C++ string class cannot consistently
handle arbitrary expressions containing strings. Consider:
+
- const char abc[5] = "world";
- string str = "hello" + abc;
+const char abc[5] = "world";
+string str = "hello" + abc;
- That isn't going to work. But it does work when the core language
+That isn't going to work. But it does work when the core language
knows about strings:
+
- const char[5] abc = "world";
- char[] str = "hello" ~ abc;
+const char[5] abc = "world";
+char[] str = "hello" ~ abc;
Consistency With C String Syntax
- There are three ways to find the length of a string in C++:
+ There are three ways to find the length of a string in C++:
+
- const char abc[] = "world"; : sizeof(abc)/sizeof(abc[0])-1
- : strlen(abc)
- string str : str.length()
+const char abc[] = "world"; : sizeof(abc)/sizeof(abc[0])-1
+ : strlen(abc)
+string str : str.length()
- That kind of inconsistency makes it hard to write generic templates.
+ That kind of inconsistency makes it hard to write generic templates.
Consider D:
+
- char[5] abc = "world"; : abc.length
- char[] str : str.length
+char[5] abc = "world"; : abc.length
+char[] str : str.length
Checking For Empty Strings
- C++ strings use a function to determine if a string is empty:
+ C++ strings use a function to determine if a string is empty:
+
- string str;
- if (str.empty())
- // string is empty
+string str;
+if (str.empty())
+ // string is empty
- In D, an empty string has zero length:
+ In D, an empty string has zero length:
+
- char[] str;
- if (!str.length)
- // string is empty
+char[] str;
+if (!str.length)
+
Resizing Existing String
- C++ handles this with the resize() member function:
+ C++ handles this with the resize() member function:
+
- string str;
- str.resize(newsize);
+string str;
+str.resize(newsize);
- D takes advantage of knowing that str is a string, and
+ D takes advantage of knowing that str is a string, and
so resizing it is just changing the length property:
+
- char[] str;
- str.length = newsize;
+char[] str;
+str.length = newsize;
Slicing a String
- C++ slices an existing string using a special constructor:
+ C++ slices an existing string using a special constructor:
+
- string s1 = "hello world";
- string s2(s1, 6, 5); // s2 is "world"
+string s1 = "hello world";
+string s2(s1, 6, 5); // s2 is "world"
- D has the array slice syntax, not possible with C++:
+ D has the array slice syntax, not possible with C++:
+
- char[] s1 = "hello world";
- char[] s2 = s1[6 .. 11]; // s2 is "world"
+char[] s1 = "hello world";
+char[] s2 = s1[6 .. 11];
- Slicing, of course, works with any array in D, not just strings.
+ Slicing, of course, works with any array in D, not just strings.
+
Copying a String
- C++ copies strings with the replace function:
+ C++ copies strings with the replace function:
+
- string s1 = "hello world";
- string s2 = "goodbye ";
- s2.replace(8, 5, s1, 6, 5); // s2 is "goodbye world"
+string s1 = "hello world";
+string s2 = "goodbye ";
+s2.replace(8, 5, s1, 6, 5); // s2 is "goodbye world"
- D uses the slice syntax as an lvalue:
+ D uses the slice syntax as an lvalue:
+
- char[] s1 = "hello world";
- char[] s2 = "goodbye ";
- s2[8..13] = s1[6..11]; // s2 is "goodbye world"
+char[] s1 = "hello world";
+char[] s2 = "goodbye ";
+s2[8..13] = s1[6..11];
Conversions to C Strings
- This is needed for compatibility with C API's. In C++, this
+ This is needed for compatibility with C API's. In C++, this
uses the c_str() member function:
+
- void foo(const char *);
- string s1;
- foo(s1.c_str());
+void foo(const char *);
+string s1;
+foo(s1.c_str());
- In D, strings can be implicitly converted to char*:
+ In D, strings can be implicitly converted to char*:
+
- void foo(char *);
- char[] s1;
- foo(s1);
+void foo(char *);
+char[] s1;
+foo(s1);
- Note: some will argue that it is a mistake in D to have an implicit
+ Note: some will argue that it is a mistake in D to have an implicit
conversion from char[] to char*.
+
Array Bounds Checking
- In C++, string array bounds checking for [] is not done.
+ In C++, string array bounds checking for [] is not done.
In D, array bounds checking is on by default and it can be turned off
with a compiler switch after the program is debugged.
+
String Switch Statements
- Are not possible in C++, nor is there any way to add them
+ Are not possible in C++, nor is there any way to add them
by adding more to the library. In D, they take the obvious
syntactical forms:
+
- switch (str)
- {
- case "hello":
- case "world":
- ...
- }
+switch (str)
+{
+ case "hello":
+ case "world":
+ ...
+}
- where str can be any of literal "string"s, fixed string arrays
+ where str can be any of literal "string"s, fixed string arrays
like char[10], or dynamic strings like char[]. A quality implementation
can, of course, explore many strategies of efficiently implementing
this based on the contents of the case strings.
+
Filling a String
- In C++, this is done with the replace() member function:
+ In C++, this is done with the replace() member function:
+
- string str = "hello";
- str.replace(1,2,2,'?'); // str is "h??lo"
+string str = "hello";
+str.replace(1,2,2,'?'); // str is "h??lo"
- In D, use the array slicing syntax in the natural manner:
+ In D, use the array slicing syntax in the natural manner:
+
- char[] str = "hello";
- str[1..3] = '?'; // str is "h??lo"
+char[] str = "hello";
+str[1..3] = '?';
Value vs Reference
- C++ strings, as implemented by STLport, are by value and are
+ C++ strings, as implemented by STLport, are by value and are
0-terminated. [The latter is an implementation choice, but
STLport seems to be the most popular implementation.]
This, coupled with no garbage collection, has
@@ -285,107 +297,112 @@
implies that strings cannot refer to other strings. String
data in the data segment, stack, etc., cannot
be referred to.
-
+
- D strings are reference types, and the memory is garbage collected.
+ D strings are reference types, and the memory is garbage collected.
This means that only references need to be copied, not the
string data. D strings can refer to data in the static data
segment, data on the stack, data inside other strings, objects,
file buffers, etc. There's no need to keep track of the 'owner'
of the string data.
-
+
- The obvious question is if multiple D strings refer to the same
+ The obvious question is if multiple D strings refer to the same
string data, what happens if the data is modified? All the
references will now point to the modified data. This can have
its own consequences, which can be avoided if the copy-on-write
convention is followed. All copy-on-write is is that if
a string is written to, an actual copy of the string data is made
first.
-
+
- The result of D strings being reference only and garbage collected
+ The result of D strings being reference only and garbage collected
is that code that does a lot of string manipulating, such as
an lzw compressor, can be a lot more efficient in terms of both
memory consumption and speed.
+
Benchmark
- Let's take a look at a small utility, wordcount, that counts up
+ Let's take a look at a small utility, wordcount, that counts up
the frequency of each word in a text file. In D, it looks like this:
+
-import file;
+import file;
-int main (char[][] args)
+int main (char[][] args)
{
- int w_total;
- int l_total;
- int c_total;
- int[char[]] dictionary;
+ int w_total;
+ int l_total;
+ int c_total;
+ int[char[]] dictionary;
- printf(" lines words bytes file\n");
- for (int i = 1; i < args.length; ++i)
+ printf(" lines words bytes file\n");
+ for (int i = 1; i < args.length; ++i)
{
- char[] input;
- int w_cnt, l_cnt, c_cnt;
- int inword;
- int wstart;
+ char[] input;
+ int w_cnt, l_cnt, c_cnt;
+ int inword;
+ int wstart;
- input = cast(char[])file.read(args[i]);
+ input = cast(char[])file.read(args[i]);
- for (int j = 0; j < input.length; j++)
- { char c;
+ for (int j = 0; j < input.length; j++)
+ { char c;
c = input[j];
- if (c == '\n')
+ if (c == '\n')
++l_cnt;
- if (c >= '0' && c <= '9')
+ if (c >= '0' && c <= '9')
{
}
- else if (c >= 'a' && c <= 'z' ||
+ else if (c >= 'a' && c <= 'z' ||
c >= 'A' && c <= 'Z')
{
- if (!inword)
+ if (!inword)
{
wstart = j;
inword = 1;
++w_cnt;
}
}
- else if (inword)
- { char[] word = input[wstart .. j];
+ else if (inword)
+ { char[] word = input[wstart .. j];
dictionary[word]++;
inword = 0;
}
++c_cnt;
}
- if (inword)
- { char[] w = input[wstart .. input.length];
+ if (inword)
+ { char[] w = input[wstart .. input.length];
dictionary[w]++;
}
- printf("%8lu%8lu%8lu %.*s\n", l_cnt, w_cnt, c_cnt, args[i]);
+ printf("%8lu%8lu%8lu %.*s\n", l_cnt, w_cnt, c_cnt, args[i]);
l_total += l_cnt;
w_total += w_cnt;
c_total += c_cnt;
}
- if (args.length > 2)
+ if (args.length > 2)
{
- printf("--------------------------------------\n%8lu%8lu%8lu total",
+ printf("--------------------------------------\n%8lu%8lu%8lu total",
l_total, w_total, c_total);
}
- printf("--------------------------------------\n");
+ printf("--------------------------------------\n");
- foreach (char[] word1; dictionary.keys.sort)
+ foreach (char[] word1; dictionary.keys.sort)
{
- printf("%3d %.*s\n", dictionary[word1], word1);
+ printf("%3d %.*s\n", dictionary[word1], word1);
}
- return 0;
+ return 0;
}
+ (An alternate implementation that
+ uses buffered file I/O to handle larger files.)
+
Two people have written C++ implementations using the C++ standard
template library,
wccpp1
@@ -406,31 +423,30 @@
implementation.
-
-
- Program
- | Compile
- | Compile Time
- | Run
- | Run Time
- |
- D wc
- | dmd wc -O -release
- | 0.0719
- | wc alice30.txt >log
- | 0.0326
- |
- C++ wccpp1
- | dmc wccpp1 -o -I\dm\stlport\stlport
- | 2.1917
- | wccpp1 alice30.txt >log
- | 0.0944
- |
- C++ wccpp2
- | dmc wccpp2 -o -I\dm\stlport\stlport
- | 2.0463
- | wccpp2 alice30.txt >log
- | 0.1012
+ Program |
+ Compile |
+ Compile Time |
+ Run |
+ Run Time |
+
+ D wc |
+ dmd wc -O -release |
+ 0.0719 |
+ wc alice30.txt >log |
+ 0.0326 |
+
+ C++ wccpp1 |
+ dmc wccpp1 -o -I\dm\stlport\stlport |
+ 2.1917 |
+ wccpp1 alice30.txt >log |
+ 0.0944 |
+
+ C++ wccpp2 |
+ dmc wccpp2 -o -I\dm\stlport\stlport |
+ 2.0463 |
+ wccpp2 alice30.txt >log |
+ 0.1012 |
+
The following tests were run on linux, again comparing a D compiler
@@ -443,37 +459,36 @@
-
-
- Program
- | Compile
- | Compile Time
- | Run
- | Run Time
- |
- D wc
- | gdc -O2 -frelease -o wc wc.d
- | 0.326
- | wc alice30.txt > /dev/null
- | 0.041
- |
- D wc
- | dmd wc -O -release
- | 0.235
- | wc alice30.txt > /dev/null
- | 0.041
- |
- C++ wccpp1
- | g++ -O2 -o wccpp1 wccpp1.cc
- | 2.874
- | wccpp1 alice30.txt > /dev/null
- | 0.086
- |
- C++ wccpp2
- | g++ -O2 -o wccpp2 wccpp2.cc
- | 2.886
- | wccpp2 alice30.txt > /dev/null
- | 0.095
+ Program |
+ Compile |
+ Compile Time |
+ Run |
+ Run Time |
+
+ D wc |
+ gdc -O2 -frelease -o wc wc.d |
+ 0.326 |
+ wc alice30.txt > /dev/null |
+ 0.041 |
+
+ D wc |
+ dmd wc -O -release |
+ 0.235 |
+ wc alice30.txt > /dev/null |
+ 0.041 |
+
+ C++ wccpp1 |
+ g++ -O2 -o wccpp1 wccpp1.cc |
+ 2.874 |
+ wccpp1 alice30.txt > /dev/null |
+ 0.086 |
+
+ C++ wccpp2 |
+ g++ -O2 -o wccpp2 wccpp2.cc |
+ 2.886 |
+ wccpp2 alice30.txt > /dev/null |
+ 0.095 |
+
These tests compare gdc with g++ on a PowerMac G5 2x2.0GHz
@@ -481,31 +496,30 @@
less accurate.)
-
-
- Program
- | Compile
- | Compile Time
- | Run
- | Run Time
- |
- D wc
- | gdc -O2 -frelease -o wc wc.d
- | 0.28
- | wc alice30.txt > /dev/null
- | 0.03
- |
- C++ wccpp1
- | g++ -O2 -o wccpp1 wccpp1.cc
- | 1.90
- | wccpp1 alice30.txt > /dev/null
- | 0.07
- |
- C++ wccpp2
- | g++ -O2 -o wccpp2 wccpp2.cc
- | 1.88
- | wccpp2 alice30.txt > /dev/null
- | 0.08
+ Program |
+ Compile |
+ Compile Time |
+ Run |
+ Run Time |
+
+ D wc |
+ gdc -O2 -frelease -o wc wc.d |
+ 0.28 |
+ wc alice30.txt > /dev/null |
+ 0.03 |
+
+ C++ wccpp1 |
+ g++ -O2 -o wccpp1 wccpp1.cc |
+ 1.90 |
+ wccpp1 alice30.txt > /dev/null |
+ 0.07 |
+
+ C++ wccpp2 |
+ g++ -O2 -o wccpp2 wccpp2.cc |
+ 1.88 |
+ wccpp2 alice30.txt > /dev/null |
+ 0.08 |
+
diff -uNr dmd-0.156/dmd/html/d/cpptod.html dmd-0.157/dmd/html/d/cpptod.html
--- dmd-0.156/dmd/html/d/cpptod.html 2006-04-26 22:34:30.000000000 +0200
+++ dmd-0.157/dmd/html/d/cpptod.html 2006-05-08 15:25:42.000000000 +0200
@@ -25,7 +25,7 @@
| Comments
- Last update Wed Apr 26 22:34:29 2006
+ Last update Mon May 8 15:25:41 2006
@@ -57,28 +57,20 @@
· D vs C/C++/C#/Java
-
· Rationale for Builtins
-
· Converting C to D
-
· Converting C++ to D
-
· The C Preprocessor vs D
-
· D strings vs C++ std::string
-
· D complex vs C++ std::complex
-
· D Contract Programming vs C++
-
|
@@ -133,9 +125,9 @@
Constructors are defined with the this keyword:
-class Foo
+class Foo
{
- this(int x) { }
+ this(int x) { }
}
@@ -161,12 +153,12 @@
The base class constructor is called with the super syntax:
-class A { this() { ... } }
-class B : A
+class A { this() { ... } }
+class B : A
{
- this(int x)
+ this(int x)
{ ...
- super(); // call base constructor
+ super(); ...
}
}
@@ -175,13 +167,13 @@
It's superior to C++ in that the base constructor call can be flexibly placed anywhere in the derived
constructor. D can also have one constructor call another one:
-class A
-{ int a;
- int b;
- this() { a = 7; b = foo(); }
- this(int x)
+class A
+{ int a;
+ int b;
+ this() { a = 7; b = foo(); }
+ this(int x)
{
- this();
+ this();
a = x;
}
}
@@ -190,13 +182,13 @@
Members can also be initialized to constants before the constructor is ever called, so the above example is
equivalently written as:
-class A
-{ int a = 7;
- int b;
- this() { b = foo(); }
- this(int x)
+class A
+{ int a = 7;
+ int b;
+ this() { b = foo(); }
+ this(int x)
{
- this();
+ this();
a = x;
}
}
@@ -261,7 +253,7 @@
A x, y;
...
-if (x == y)
+if (x == y)
...
@@ -312,13 +304,13 @@
No need for idiomatic constructions like the above. Just write:
-typedef void *Handle = cast(void *)-1;
-void bar(Handle);
+typedef void *Handle = cast(void *)-1;
+void bar(Handle);
Handle h;
bar(h);
h = func();
-if (h != Handle.init)
+if (h != Handle.init)
...
@@ -368,27 +360,27 @@
in the same module, so implicitly granting friend access to
other module members solves the problem neatly:
-module X;
+module X;
-class A
+class A
{
- private:
- static int a;
+ private:
+ static int a;
- public:
- int foo(B j) { return j.b; }
+ public:
+ int foo(B j) { return j.b; }
}
-class B
+class B
{
- private:
- static int b;
+ private:
+ static int b;
- public:
- int bar(A j) { return j.a; }
+ public:
+ int bar(A j) { return j.a; }
}
-int abc(A p) { return p.a; }
+int abc(A p) { return p.a; }
The private attribute prevents other modules from
@@ -424,9 +416,9 @@
D recognizes that the comparison operators are all fundamentally
related to each other. So only one function is necessary:
-struct A
+struct A
{
- int opCmp(int i);
+ int opCmp(int i);
}
@@ -462,13 +454,13 @@
D uses modules instead of namespaces and #include files, and
alias declarations take the place of using declarations:
-/** Module Foo.d **/
-module Foo;
-int x;
-
-/** Another module **/
-import Foo;
-alias Foo.x x;
+
+module Foo;
+int x;
+
+
+import Foo;
+alias Foo.x x;
Alias is a much more flexible than the single purpose using
@@ -507,22 +499,22 @@
The few RAII issues left are handled by auto classes.
Auto classes get their destructors run when they go out of scope.
-auto class File
+auto class File
{ Handle h;
- ~this()
+ ~this()
{
h.release();
}
}
-void test()
+void test()
{
- if (...)
- { auto File f = new File();
+ if (...)
+ { auto File f = new File();
...
- } // f.~this() gets run at closing brace, even if
- // scope was exited via a thrown exception
+ } }
@@ -559,24 +551,24 @@
Properties can be get and set using the normal field syntax,
yet the get and set will invoke methods instead.
-class Abc
+class Abc
{
- // set
- void property(int newproperty) { myprop = newproperty; }
+ void property(int newproperty) { myprop = newproperty; }
- // get
- int property() { return myprop; }
+ int property() { return myprop; }
- private:
- int myprop;
+ private:
+ int myprop;
}
which is used as:
Abc a;
-a.property = 3; // equivalent to a.property(3)
-int x = a.property; // equivalent to int x = a.property()
+a.property = 3; int x = a.property;
Thus, in D a property can be treated like it was a simple field name.
@@ -623,19 +615,19 @@
advantage of promotion of single template members to the
enclosing name space:
-template factorial(int n)
+template factorial(int n)
{
- enum { factorial = n * .factorial!(n-1) }
+ enum { factorial = n * .factorial!(n-1) }
}
-template factorial(int n : 1)
+template factorial(int n : 1)
{
- enum { factorial = 1 }
+ enum { factorial = 1 }
}
-void test()
+void test()
{
- printf("%d\n", factorial!(4)); // prints 24
+ printf("%d\n", factorial!(4)); }
@@ -764,29 +756,29 @@
It compiles quickly, and gives a sensible compile time message
if it fails.
-template Integer(int nbits)
+template Integer(int nbits)
{
- static if (nbits <= 8)
- alias byte Integer;
- else static if (nbits <= 16)
- alias short Integer;
- else static if (nbits <= 32)
- alias int Integer;
- else static if (nbits <= 64)
- alias long Integer;
- else
- static assert(0);
+ static if (nbits <= 8)
+ alias byte Integer;
+ else static if (nbits <= 16)
+ alias short Integer;
+ else static if (nbits <= 32)
+ alias int Integer;
+ else static if (nbits <= 64)
+ alias long Integer;
+ else
+ static assert(0);
}
-int main()
+int main()
{
Integer!(8) i ;
Integer!(16) j ;
Integer!(29) k ;
Integer!(64) l ;
- printf("%d %d %d %d\n",
+ printf("%d %d %d %d\n",
i.sizeof, j.sizeof, k.sizeof, l.sizeof);
- return 0;
+ return 0;
}
@@ -834,19 +826,19 @@
SFINAE can be done in D without resorting to template argument
pattern matching:
-template IsFunctionT(T)
+template IsFunctionT(T)
{
- static if ( is(T[]) )
- const int IsFunctionT = 1;
- else
- const int IsFunctionT = 0;
+ static if ( is(T[]) )
+ const int IsFunctionT = 1;
+ else
+ const int IsFunctionT = 0;
}
-void test()
+void test()
{
- typedef int fp(int);
+ typedef int fp(int);
- assert(IsFunctionT!(fp) == 1);
+ assert(IsFunctionT!(fp) == 1);
}
@@ -856,11 +848,11 @@
The is
expression can test it directly:
-void test()
+void test()
{
- typedef int fp(int);
+ typedef int fp(int);
- assert( is(fp == function) );
+ assert( is(fp == function) );
}
diff -uNr dmd-0.156/dmd/html/d/ctod.html dmd-0.157/dmd/html/d/ctod.html
--- dmd-0.156/dmd/html/d/ctod.html 2006-04-26 22:34:30.000000000 +0200
+++ dmd-0.157/dmd/html/d/ctod.html 2006-05-08 15:25:42.000000000 +0200
@@ -26,7 +26,7 @@
" title="Read/write comments and feedback">Comments
- Last update Wed Apr 26 22:34:29 2006
+ Last update Mon May 8 15:25:41 2006
@@ -58,28 +58,20 @@
· D vs C/C++/C#/Java
-
· Rationale for Builtins
-
· Converting C to D
-
· Converting C++ to D
-
· The C Preprocessor vs D
-
· D strings vs C++ std::string
-
· D complex vs C++ std::complex
-
· D Contract Programming vs C++
-
|
@@ -90,6 +82,7 @@
Et tu, D? Then fall, C! -- William Nerdspeare
+
Every experienced C programmer accumulates a series of idioms and techniques
@@ -157,20 +150,20 @@
The C Way
- sizeof(int)
- sizeof(char *)
- sizeof(double)
- sizeof(struct Foo)
+sizeof(int)
+sizeof(char *)
+sizeof(double)
+sizeof(struct Foo)
The D Way
Use the size property:
- int.sizeof
- (char *).sizeof
- double.sizeof
- Foo.sizeof
+int.sizeof
+(char *).sizeof
+double.sizeof
+Foo.sizeof
@@ -179,22 +172,21 @@
The C Way
- #include <limits.h>
- #include <math.h>
+#include <limits.h>
+#include <math.h>
- CHAR_MAX
- CHAR_MIN
- ULONG_MAX
- DBL_MIN
+CHAR_MAX
+CHAR_MIN
+ULONG_MAX
+DBL_MIN
-
The D Way
- char.max
- char.min
- ulong.max
- double.min
+char.max
+char.min
+ulong.max
+double.min
@@ -203,27 +195,25 @@
C to D types
- bool => bit
- char => char
- signed char => byte
- unsigned char => ubyte
- short => short
- unsigned short => ushort
- wchar_t => wchar
- int => int
- unsigned => uint
- long => int
- unsigned long => uint
- long long => long
- unsigned long long => ulong
- float => float
- double => double
- long double => real
- _Imaginary long double => imaginary
- _Complex long double => complex
-
+bool => bit
+char => char
+signed char => byte
+unsigned char => ubyte
+short => short
+unsigned short => ushort
+wchar_t => wchar
+int => int
+unsigned => uint
+long => int
+unsigned long => uint
+long long => long
+unsigned long long => ulong
+float => float
+double => double
+long double => real
+_Imaginary long double => imaginary
+_Complex long double => complex
-
Although char is an unsigned 8 bit type, and
wchar is an unsigned 16 bit type, they have their own separate types
@@ -237,34 +227,33 @@
The C Way
- #include <fp.h>
+#include <fp.h>
- NAN
- INFINITY
+NAN
+INFINITY
- #include <float.h>
+#include <float.h>
- DBL_DIG
- DBL_EPSILON
- DBL_MANT_DIG
- DBL_MAX_10_EXP
- DBL_MAX_EXP
- DBL_MIN_10_EXP
- DBL_MIN_EXP
+DBL_DIG
+DBL_EPSILON
+DBL_MANT_DIG
+DBL_MAX_10_EXP
+DBL_MAX_EXP
+DBL_MIN_10_EXP
+DBL_MIN_EXP
-
The D Way
- double.nan
- double.infinity
- double.dig
- double.epsilon
- double.mant_dig
- double.max_10_exp
- double.max_exp
- double.min_10_exp
- double.min_exp
+double.nan
+double.infinity
+double.dig
+double.epsilon
+double.mant_dig
+double.max_10_exp
+double.max_exp
+double.min_10_exp
+double.min_exp
@@ -272,22 +261,20 @@
The C Way
-
- #include <math.h>
+#include <math.h>
- float f = fmodf(x,y);
- double d = fmod(x,y);
- long double r = fmodl(x,y);
+float f = fmodf(x,y);
+double d = fmod(x,y);
+long double r = fmodl(x,y);
-
The D Way
D supports the remainder ('%') operator on floating point operands:
- float f = x % y;
- double d = x % y;
- real r = x % y;
+float f = x % y;
+double d = x % y;
+real r = x % y;
@@ -300,22 +287,20 @@
is NAN, and few C compilers check for it (the Digital Mars
C compiler is an exception, DM's compilers do check for NAN operands).
-
- #include <math.h>
+#include <math.h>
- if (isnan(x) || isnan(y))
- result = FALSE;
- else
- result = (x < y);
+if (isnan(x) || isnan(y))
+ result = FALSE;
+else
+ result = (x < y);
-
The D Way
-
+
D offers a full complement of comparisons and operators
that work with NAN arguments.
- result = (x < y); // false if x or y is nan
+result = (x < y);
@@ -337,7 +322,7 @@
D simply builds assert into the language:
-assert(e == 0);
+assert(e == 0);
@@ -346,18 +331,16 @@
The C Way
-
- #define ARRAY_LENGTH 17
- int array[ARRAY_LENGTH];
- for (i = 0; i < ARRAY_LENGTH; i++)
- array[i] = value;
+#define ARRAY_LENGTH 17
+int array[ARRAY_LENGTH];
+for (i = 0; i < ARRAY_LENGTH; i++)
+ array[i] = value;
-
The D Way
- int array[17];
- array[] = value;
+int array[17];
+array[] = value;
@@ -369,37 +352,33 @@
The array length is defined separately, or a clumsy
sizeof() expression is used to get the length.
-
- #define ARRAY_LENGTH 17
- int array[ARRAY_LENGTH];
- for (i = 0; i < ARRAY_LENGTH; i++)
- func(array[i]);
+#define ARRAY_LENGTH 17
+int array[ARRAY_LENGTH];
+for (i = 0; i < ARRAY_LENGTH; i++)
+ func(array[i]);
-
or:
-
- int array[17];
- for (i = 0; i < sizeof(array) / sizeof(array[0]); i++)
- func(array[i]);
+int array[17];
+for (i = 0; i < sizeof(array) / sizeof(array[0]); i++)
+ func(array[i]);
-
The D Way
The length of an array is accessible the property "length".
- int array[17];
- for (i = 0; i < array.length; i++)
- func(array[i]);
+int array[17];
+for (i = 0; i < array.length; i++)
+ func(array[i]);
or even better:
- int array[17];
- foreach (int value; array)
- func(value);
+int array[17];
+foreach (int value; array)
+ func(value);
@@ -413,31 +392,29 @@
variable for the length, and then explicitly manage the size of
the array:
-
- #include <stdlib.h>
+#include <stdlib.h>
- int array_length;
- int *array;
- int *newarray;
-
- newarray = (int *)
- realloc(array, (array_length + 1) * sizeof(int));
- if (!newarray)
- error("out of memory");
- array = newarray;
- array[array_length++] = x;
+int array_length;
+int *array;
+int *newarray;
+
+newarray = (int *)
+ realloc(array, (array_length + 1) * sizeof(int));
+if (!newarray)
+ error("out of memory");
+array = newarray;
+array[array_length++] = x;
-
The D Way
D supports dynamic arrays, which can be easily resized. D supports
all the requisite memory management.
- int[] array;
+int[] array;
- array.length = array.length + 1;
- array[array.length - 1] = x;
+array.length = array.length + 1;
+array[array.length - 1] = x;
@@ -450,50 +427,48 @@
when can storage be free'd, dealing with null pointers,
finding the length of the strings, and memory allocation:
-
- #include <string.h>
+#include <string.h>
- char *s1;
- char *s2;
- char *s;
-
- // Concatenate s1 and s2, and put result in s
- free(s);
- s = (char *)malloc((s1 ? strlen(s1) : 0) +
- (s2 ? strlen(s2) : 0) + 1);
- if (!s)
- error("out of memory");
- if (s1)
- strcpy(s, s1);
- else
- *s = 0;
- if (s2)
- strcpy(s + strlen(s), s2);
-
- // Append "hello" to s
- char hello[] = "hello";
- char *news;
- size_t lens = s ? strlen(s) : 0;
- news = (char *)
- realloc(s, (lens + sizeof(hello) + 1) * sizeof(char));
- if (!news)
- error("out of memory");
- s = news;
- memcpy(s + lens, hello, sizeof(hello));
+char *s1;
+char *s2;
+char *s;
+
+// Concatenate s1 and s2, and put result in s
+free(s);
+s = (char *)malloc((s1 ? strlen(s1) : 0) +
+ (s2 ? strlen(s2) : 0) + 1);
+if (!s)
+ error("out of memory");
+if (s1)
+ strcpy(s, s1);
+else
+ *s = 0;
+if (s2)
+ strcpy(s + strlen(s), s2);
+
+// Append "hello" to s
+char hello[] = "hello";
+char *news;
+size_t lens = s ? strlen(s) : 0;
+news = (char *)
+ realloc(s, (lens + sizeof(hello) + 1) * sizeof(char));
+if (!news)
+ error("out of memory");
+s = news;
+memcpy(s + lens, hello, sizeof(hello));
-
The D Way
D overloads the operators ~ and ~= for char and wchar arrays to mean
concatenate and append, respectively:
- char[] s1;
- char[] s2;
- char[] s;
+char[] s1;
+char[] s2;
+char[] s;
- s = s1 ~ s2;
- s ~= "hello";
+s = s1 ~ s2;
+s ~= "hello";
@@ -504,20 +479,18 @@
printf() is the general purpose formatted print routine:
-
- #include <stdio.h>
+#include <stdio.h>
- printf("Calling all cars %d times!\n", ntimes);
+printf("Calling all cars %d times!\n", ntimes);
-
The D Way
What can we say? printf() rules:
- import stdio;
+import stdio;
- printf("Calling all cars %d times!\n", ntimes);
+printf("Calling all cars %d times!\n", ntimes);
@@ -530,21 +503,19 @@
not yet encountered in the source file, it is necessary to insert
a function declaration lexically preceding the call.
-
- void forwardfunc();
+void forwardfunc();
- void myfunc()
- {
- forwardfunc();
- }
+void myfunc()
+{
+ forwardfunc();
+}
- void forwardfunc()
- {
- ...
- }
+void forwardfunc()
+{
+ ...
+}
-
The D Way
The program is looked at as a whole, and so not only is it not
@@ -553,15 +524,15 @@
referenced function declarations twice.
Functions can be defined in any order.
- void myfunc()
- {
- forwardfunc();
- }
-
- void forwardfunc()
- {
- ...
- }
+void myfunc()
+{
+ forwardfunc();
+}
+
+void forwardfunc()
+{
+ ...
+}
@@ -570,21 +541,19 @@
The C Way
-
- void function(void);
+void function(void);
-
The D Way
D is a strongly typed language, so there is no need to explicitly
say a function takes no arguments, just don't declare it has having
arguments.
- void function()
- {
- ...
- }
+void function()
+{
+ ...
+}
@@ -596,42 +565,40 @@
Break's and continue's only apply to the innermost nested loop or
switch, so a multilevel break must use a goto:
-
- for (i = 0; i < 10; i++)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
{
- for (j = 0; j < 10; j++)
- {
- if (j == 3)
- goto Louter;
- if (j == 4)
- goto L2;
- }
- L2:
- ;
+ if (j == 3)
+ goto Louter;
+ if (j == 4)
+ goto L2;
}
- Louter:
+ L2:
;
+ }
+Louter:
+ ;
-
The D Way
Break and continue statements can be followed by a label. The label
is the label for an enclosing loop or switch, and the break applies
to that loop.
- Louter:
- for (i = 0; i < 10; i++)
+Louter:
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
{
- for (j = 0; j < 10; j++)
- {
- if (j == 3)
- break Louter;
- if (j == 4)
- continue Louter;
- }
+ if (j == 3)
+ break Louter;
+ if (j == 4)
+ continue Louter;
}
- // break Louter goes here
+ }
+
@@ -658,17 +625,15 @@
It's annoying to have to put the struct keyword every time a type is specified,
so a common idiom is to use:
-
- typedef struct ABC { ... } ABC;
+typedef struct ABC { ... } ABC;
-
The D Way
Struct tag names are not in a separate name space, they are in the same name
space as ordinary names. Hence:
- struct ABC { ... };
+struct ABC { ... };
@@ -681,30 +646,28 @@
values and take action based on which one it is. A typical use
for this might be command line argument processing.
-
- #include <string.h>
- void dostring(char *s)
- {
- enum Strings { Hello, Goodbye, Maybe, Max };
- static char *table[] = { "hello", "goodbye", "maybe" };
- int i;
-
- for (i = 0; i < Max; i++)
- {
- if (strcmp(s, table[i]) == 0)
- break;
- }
- switch (i)
- {
- case Hello: ...
- case Goodbye: ...
- case Maybe: ...
- default: ...
- }
- }
+#include <string.h>
+void dostring(char *s)
+{
+ enum Strings { Hello, Goodbye, Maybe, Max };
+ static char *table[] = { "hello", "goodbye", "maybe" };
+ int i;
+
+ for (i = 0; i < Max; i++)
+ {
+ if (strcmp(s, table[i]) == 0)
+ break;
+ }
+ switch (i)
+ {
+ case Hello: ...
+ case Goodbye: ...
+ case Maybe: ...
+ default: ...
+ }
+}
-
The problem with this is trying to maintain 3 parallel data
structures, the enum, the table, and the switch cases. If there
are a lot of values, the connection between the 3 may not be so
@@ -723,16 +686,16 @@
strings as well as numbers. Then, the way to code the string
lookup becomes straightforward:
- void dostring(char[] s)
- {
- switch (s)
- {
- case "hello": ...
- case "goodbye": ...
- case "maybe": ...
- default: ...
- }
- }
+void dostring(char[] s)
+{
+ switch (s)
+ {
+ case "hello": ...
+ case "goodbye": ...
+ case "maybe": ...
+ default: ...
+ }
+}
Adding new cases becomes easy. The compiler can be relied on
@@ -749,16 +712,14 @@
program, and woe results if any modules or libraries didn't get
recompiled. To address this, #pragma's are used:
-
- #pragma pack(1)
- struct ABC
- {
- ...
- };
- #pragma pack()
+#pragma pack(1)
+struct ABC
+{
+ ...
+};
+#pragma pack()
-
But #pragmas are nonportable both in theory and in practice from
compiler to compiler.
@@ -767,19 +728,19 @@
Clearly, since much of the point to setting alignment is for
portability of data, a portable means of expressing it is necessary.
- struct ABC
- {
- int z; // z is aligned to the default
+struct ABC
+{
+ int z;
- align (1) int x; // x is byte aligned
- align (4)
- {
- ... // declarations in {} are dword aligned
- }
- align (2): // switch to word alignment from here on
+ align (1) int x; align (4)
+ {
+ ... }
+ align (2):
- int y; // y is word aligned
- }
+ int y; }
@@ -793,29 +754,27 @@
C doesn't allow anonymous structs or unions, which means that dummy tag names
and dummy members are necessary:
-
- struct Foo
- { int i;
- union Bar
- {
- struct Abc { int x; long y; } _abc;
- char *p;
- } _bar;
- };
-
- #define x _bar._abc.x
- #define y _bar._abc.y
- #define p _bar.p
-
- struct Foo f;
-
- f.i;
- f.x;
- f.y;
- f.p;
+struct Foo
+{ int i;
+ union Bar
+ {
+ struct Abc { int x; long y; } _abc;
+ char *p;
+ } _bar;
+};
+
+#define x _bar._abc.x
+#define y _bar._abc.y
+#define p _bar.p
+
+struct Foo f;
+
+f.i;
+f.x;
+f.y;
+f.p;
-
Not only is it clumsy, but using macros means a symbolic debugger won't understand
what is being done, and the macros have global scope instead of struct scope.
@@ -824,21 +783,21 @@
Anonymous structs and unions are used to control the layout in a
more natural manner:
- struct Foo
- { int i;
- union
- {
- struct { int x; long y; }
- char* p;
- }
- }
+struct Foo
+{ int i;
+ union
+ {
+ struct { int x; long y; }
+ char* p;
+ }
+}
- Foo f;
+Foo f;
- f.i;
- f.x;
- f.y;
- f.p;
+f.i;
+f.x;
+f.y;
+f.p;
@@ -849,25 +808,21 @@
Is to do it in one statement ending with a semicolon:
-
- struct Foo { int x; int y; } foo;
+struct Foo { int x; int y; } foo;
-
Or to separate the two:
-
- struct Foo { int x; int y; }; // note terminating ;
- struct Foo foo;
+struct Foo { int x; int y; }; // note terminating ;
+struct Foo foo;
-
The D Way
Struct definitions and declarations can't be done in the same statement:
- struct Foo { int x; int y; } // note there is no terminating ;
- Foo foo;
+struct Foo { int x; int y; } Foo foo;
which means that the terminating ; can be dispensed with, eliminating the
@@ -882,21 +837,19 @@
Naturally, another macro is used:
-
- #include <stddef>
- struct Foo { int x; int y; };
+#include <stddef>
+struct Foo { int x; int y; };
- off = offsetof(Foo, y);
+off = offsetof(Foo, y);
-
The D Way
An offset is just another property:
- struct Foo { int x; int y; }
+struct Foo { int x; int y; }
- off = Foo.y.offset;
+off = Foo.y.offset;
@@ -907,12 +860,10 @@
Unions are initialized using the "first member" rule:
-
- union U { int a; long b; };
- union U x = { 5 }; // initialize member 'a' to 5
+union U { int a; long b; };
+union U x = { 5 }; // initialize member 'a' to 5
-
Adding union members or rearranging them can have disastrous consequences
for any initializers.
@@ -920,8 +871,8 @@
In D, which member is being initialized is mentioned explicitly:
- union U { int a; long b; }
- U x = { a:5 }
+union U { int a; long b; }
+U x = { a:5 }
avoiding the confusion and maintenance problems.
@@ -934,12 +885,10 @@
Members are initialized by their position within the {}'s:
-
- struct S { int a; int b; };
- struct S x = { 5, 3 };
+struct S { int a; int b; };
+struct S x = { 5, 3 };
-
This isn't much of a problem with small structs, but when there
are numerous members, it becomes tedious to get the initializers
carefully lined up with the field declarations. Then, if members are
@@ -950,8 +899,8 @@
Member initialization can be done explicitly:
- struct S { int a; int b; }
- S x = { b:3, a:5 }
+struct S { int a; int b; }
+S x = { b:3, a:5 }
The meaning is clear, and there no longer is a positional dependence.
@@ -963,37 +912,33 @@
The C Way
C initializes array by positional dependence:
-
- int a[3] = { 3,2,2 };
+int a[3] = { 3,2,2 };
-
Nested arrays may or may not have the { }:
-
- int b[3][2] = { 2,3, {6,5}, 3,4 };
+int b[3][2] = { 2,3, {6,5}, 3,4 };
-
The D Way
D does it by positional dependence too, but an index can be used as well:
The following all produce the same result:
- int[3] a = [ 3, 2, 0 ];
- int[3] a = [ 3, 2 ]; // unsupplied initializers are 0, just like in C
- int[3] a = [ 2:0, 0:3, 1:2 ];
- int[3] a = [ 2:0, 0:3, 2 ]; // if not supplied, the index is the
- // previous one plus one.
+int[3] a = [ 3, 2, 0 ];
+int[3] a = [ 3, 2 ]; int[3] a = [ 2:0, 0:3, 1:2 ];
+int[3] a = [ 2:0, 0:3, 2 ];
This can be handy if the array will be indexed by an enum, and the order of
enums may be changed or added to:
- enum color { black, red, green }
- int[3] c = [ black:3, green:2, red:5 ];
+enum color { black, red, green }
+int[3] c = [ black:3, green:2, red:5 ];
Nested array initializations must be explicit:
- int[2][3] b = [ [2,3], [6,5], [3,4] ];
+int[2][3] b = [ [2,3], [6,5], [3,4] ];
- int[2][3] b = [[2,6,3],[3,5,4]]; // error
+int[2][3] b = [[2,6,3],[3,5,4]];
@@ -1003,32 +948,26 @@
The C Way
C has problems with the DOS file system because a \ is an escape in a string. To specifiy file c:\root\file.c:
-
- char file[] = "c:\\root\\file.c";
+char file[] = "c:\\root\\file.c";
-
This gets even more unpleasant with regular expressions.
Consider the escape sequence to match a quoted string:
-
- /"[^\\]*(\\.[^\\]*)*"/
+/"[^\\]*(\\.[^\\]*)*"/
-
In C, this horror is expressed as:
-
- char quoteString[] = "\"[^\\\\]*(\\\\.[^\\\\]*)*\"";
+char quoteString[] = "\"[^\\\\]*(\\\\.[^\\\\]*)*\"";
-
The D Way
Within strings, it is WYSIWYG (what you see is what you get).
Escapes are in separate strings. So:
- char[] file = `c:\root\file.c`;
- char[] quoteString = \" r"[^\\]*(\\.[^\\]*)*" \";
+char[] file = `c:\root\file.c`;
+char[] quoteString = \" r"[^\\]*(\\.[^\\]*)*" \";
The famous hello world string becomes:
- char[] hello = "hello world" \n;
+char[] hello = "hello world" \n;
@@ -1040,24 +979,20 @@
The C Way
C uses the wchar_t and the L prefix on strings:
-
- #include <wchar.h>
- char foo_ascii[] = "hello";
- wchar_t foo_wchar[] = L"hello";
+#include <wchar.h>
+char foo_ascii[] = "hello";
+wchar_t foo_wchar[] = L"hello";
-
Things get worse if code is written to be both ascii and wchar compatible.
A macro is used to switch strings from ascii to wchar:
-
- #include <tchar.h>
- tchar string[] = TEXT("hello");
+#include <tchar.h>
+tchar string[] = TEXT("hello");
-
The D Way
The type of a string is determined by semantic analysis, so there is no need to wrap strings in a macro call:
- char[] foo_ascii = "hello"; // string is taken to be ascii
- wchar[] foo_wchar = "hello"; // string is taken to be wchar
+char[] foo_ascii = "hello"; wchar[] foo_wchar = "hello";
@@ -1067,22 +1002,20 @@
The C Way
Consider:
-
- enum COLORS { red, blue, green, max };
- char *cstring[max] = {"red", "blue", "green" };
+enum COLORS { red, blue, green, max };
+char *cstring[max] = {"red", "blue", "green" };
-
This is fairly easy to get right because the number of entries is small. But suppose it gets to be fairly large. Then it can get difficult to maintain correctly when new entries are added.
The D Way
- enum COLORS { red, blue, green }
+enum COLORS { red, blue, green }
- char[][COLORS.max + 1] cstring =
- [
- COLORS.red : "red",
- COLORS.blue : "blue",
- COLORS.green : "green",
- ];
+char[][COLORS.max + 1] cstring =
+[
+ COLORS.red : "red",
+ COLORS.blue : "blue",
+ COLORS.green : "green",
+];
Not perfect, but better.
@@ -1097,62 +1030,54 @@
a new type. The compiler doesn't distinguish between a typedef
and its underlying type.
-
- typedef void *Handle;
- void foo(void *);
- void bar(Handle);
-
- Handle h;
- foo(h); // coding bug not caught
- bar(h); // ok
-
-
+typedef void *Handle;
+void foo(void *);
+void bar(Handle);
+
+Handle h;
+foo(h); // coding bug not caught
+bar(h); // ok
+
The C solution is to create a dummy struct whose sole
purpose is to get type checking and overloading on the new type.
-
- struct Handle__ { void *value; }
- typedef struct Handle__ *Handle;
- void foo(void *);
- void bar(Handle);
-
- Handle h;
- foo(h); // syntax error
- bar(h); // ok
-
-
+struct Handle__ { void *value; }
+typedef struct Handle__ *Handle;
+void foo(void *);
+void bar(Handle);
+
+Handle h;
+foo(h); // syntax error
+bar(h); // ok
+
Having a default value for the type involves defining a macro,
a naming convention, and then pedantically following that convention:
-
- #define HANDLE_INIT ((Handle)-1)
-
- Handle h = HANDLE_INIT;
- h = func();
- if (h != HANDLE_INIT)
- ...
-
+#define HANDLE_INIT ((Handle)-1)
+Handle h = HANDLE_INIT;
+h = func();
+if (h != HANDLE_INIT)
+ ...
+
For the struct solution, things get even more complex:
-
- struct Handle__ HANDLE_INIT;
+struct Handle__ HANDLE_INIT;
- void init_handle() // call this function upon startup
- {
- HANDLE_INIT.value = (void *)-1;
- }
+void init_handle() // call this function upon startup
+{
+ HANDLE_INIT.value = (void *)-1;
+}
- Handle h = HANDLE_INIT;
- h = func();
- if (memcmp(&h,&HANDLE_INIT,sizeof(Handle)) != 0)
- ...
+Handle h = HANDLE_INIT;
+h = func();
+if (memcmp(&h,&HANDLE_INIT,sizeof(Handle)) != 0)
+ ...
-
There are 4 names to remember: Handle, HANDLE_INIT,
struct Handle__, value.
@@ -1160,23 +1085,23 @@
No need for idiomatic constructions like the above. Just write:
- typedef void* Handle;
- void foo(void*);
- void bar(Handle);
-
- Handle h;
- foo(h);
- bar(h);
+typedef void* Handle;
+void foo(void*);
+void bar(Handle);
+
+Handle h;
+foo(h);
+bar(h);
To handle a default value, add an initializer to the typedef,
and refer to it with the .init property:
- typedef void* Handle = cast(void*)(-1);
- Handle h;
- h = func();
- if (h != Handle.init)
- ...
+typedef void* Handle = cast(void*)(-1);
+Handle h;
+h = func();
+if (h != Handle.init)
+ ...
There's only one name to remember: Handle.
@@ -1189,25 +1114,21 @@
While C defines struct assignment in a simple, convenient manner:
-
- struct A x, y;
- ...
- x = y;
-
-
+struct A x, y;
+...
+x = y;
+
it does not for struct comparisons. Hence, to compare two struct
instances for equality:
-
- #include <string.h>
-
- struct A x, y;
- ...
- if (memcmp(&x, &y, sizeof(struct A)) == 0)
- ...
-
+#include <string.h>
+struct A x, y;
+...
+if (memcmp(&x, &y, sizeof(struct A)) == 0)
+ ...
+
Note the obtuseness of this, coupled with the lack of any kind
of help from the language with type checking.
@@ -1223,10 +1144,10 @@
D does it the obvious, straightforward way:
- A x, y;
- ...
- if (x == y)
- ...
+A x, y;
+...
+if (x == y)
+ ...
@@ -1236,13 +1157,11 @@
The C Way
The library function strcmp() is used:
-
- char string[] = "hello";
-
- if (strcmp(string, "betty") == 0) // do strings match?
- ...
-
+char string[] = "hello";
+if (strcmp(string, "betty") == 0) // do strings match?
+ ...
+
C uses 0 terminated strings, so the C way has an inherent
inefficiency in constantly scanning for the terminating 0.
@@ -1251,10 +1170,10 @@
Why not use the == operator?
- char[] string = "hello";
+char[] string = "hello";
- if (string == "betty")
- ...
+if (string == "betty")
+ ...
D strings have the length stored separately from the string.
@@ -1265,10 +1184,10 @@
D supports comparison operators on strings, too:
- char[] string = "hello";
+char[] string = "hello";
- if (string < "betty")
- ...
+if (string < "betty")
+ ...
which is useful for sorting/searching.
@@ -1281,21 +1200,19 @@
Although many C programmers tend to reimplmement bubble sorts
over and over, the right way to sort in C is to use qsort():
-
- int compare(const void *p1, const void *p2)
- {
- type *t1 = (type *)p1;
- type *t1 = (type *)p2;
-
- return *t1 - *t2;
- }
+int compare(const void *p1, const void *p2)
+{
+ type *t1 = (type *)p1;
+ type *t1 = (type *)p2;
- type array[10];
- ...
- qsort(array, sizeof(array)/sizeof(array[0]),
- sizeof(array[0]), compare);
-
+ return *t1 - *t2;
+}
+type array[10];
+...
+qsort(array, sizeof(array)/sizeof(array[0]),
+ sizeof(array[0]), compare);
+
A compare() must be written for each type, and much careful
typo-prone code needs to be written to make it work.
@@ -1305,9 +1222,9 @@
Sorting couldn't be easier:
- type[] array;
- ...
- array.sort; // sort array in-place
+type[] array;
+...
+array.sort;
@@ -1317,20 +1234,18 @@
To access volatile memory, such as shared memory
or memory mapped I/O, a pointer to volatile is created:
-
- volatile int *p = address;
-
- i = *p;
-
+volatile int *p = address;
+i = *p;
+
The D Way
D has volatile as a statement type, not as a type modifier:
- int* p = address;
+int* p = address;
- volatile { i = *p; }
+volatile { i = *p; }
@@ -1341,12 +1256,10 @@
String literals in C cannot span multiple lines, so to have
a block of text it is necessary to use \ line splicing:
-
- "This text spans\n\
- multiple\n\
- lines\n"
-
-
+"This text spans\n\
+multiple\n\
+lines\n"
+
If there is a lot of text, this can wind up being tedious.
@@ -1354,10 +1267,10 @@
String literals can span multiple lines, as in:
- "This text spans
- multiple
- lines
- "
+"This text spans
+multiple
+lines
+"
So blocks of text can just be cut and pasted into the D
@@ -1382,50 +1295,48 @@
some context outside of the trees, so a custom struct Paramblock
is created and a pointer to it is used to maximize efficiency.
-
- struct Symbol
- { char *id;
- struct Symbol *left;
- struct Symbol *right;
- };
-
- struct Paramblock
- { char *id;
- struct Symbol *sm;
- };
+struct Symbol
+{ char *id;
+struct Symbol *left;
+struct Symbol *right;
+};
+
+struct Paramblock
+{ char *id;
+struct Symbol *sm;
+};
- static void membersearchx(struct Paramblock *p, struct Symbol *s)
+static void membersearchx(struct Paramblock *p, struct Symbol *s)
+{
+while (s)
+{
+ if (strcmp(p->id,s->id) == 0)
{
- while (s)
- {
- if (strcmp(p->id,s->id) == 0)
- {
- if (p->sm)
- error("ambiguous member %s\n",p->id);
- p->sm = s;
- }
-
- if (s->left)
- membersearchx(p,s->left);
- s = s->right;
- }
+ if (p->sm)
+ error("ambiguous member %s\n",p->id);
+ p->sm = s;
}
- struct Symbol *symbol_membersearch(Symbol *table[], int tablemax, char *id)
- {
- struct Paramblock pb;
- int i;
+ if (s->left)
+ membersearchx(p,s->left);
+ s = s->right;
+}
+}
- pb.id = id;
- pb.sm = NULL;
- for (i = 0; i < tablemax; i++)
- {
- membersearchx(pb, table[i]);
- }
- return pb.sm;
- }
-
+struct Symbol *symbol_membersearch(Symbol *table[], int tablemax, char *id)
+{
+struct Paramblock pb;
+int i;
+pb.id = id;
+pb.sm = NULL;
+for (i = 0; i < tablemax; i++)
+{
+ membersearchx(pb, table[i]);
+}
+return pb.sm;
+}
+
The D Way
@@ -1439,38 +1350,38 @@
The performance of the two versions is indistinguishable.
- class Symbol
- { char[] id;
- Symbol left;
- Symbol right;
- }
+class Symbol
+{ char[] id;
+ Symbol left;
+ Symbol right;
+}
- Symbol symbol_membersearch(Symbol[] table, char[] id)
- { Symbol sm;
+Symbol symbol_membersearch(Symbol[] table, char[] id)
+{ Symbol sm;
- void membersearchx(Symbol s)
+ void membersearchx(Symbol s)
+ {
+ while (s)
{
- while (s)
+ if (id == s.id)
{
- if (id == s.id)
- {
- if (sm)
- error("ambiguous member %s\n", id);
- sm = s;
- }
-
- if (s.left)
- membersearchx(s.left);
- s = s.right;
+ if (sm)
+ error("ambiguous member %s\n", id);
+ sm = s;
}
- }
- for (int i = 0; i < table.length; i++)
- {
- membersearchx(table[i]);
+ if (s.left)
+ membersearchx(s.left);
+ s = s.right;
}
- return sm;
}
+
+ for (int i = 0; i < table.length; i++)
+ {
+ membersearchx(table[i]);
+ }
+ return sm;
+}
@@ -1484,22 +1395,18 @@
integral type. To produce an unsigned right shift on an int,
a cast is necessary:
-
- int i, j;
- ...
- j = (unsigned)i >> 3;
-
-
+int i, j;
+...
+j = (unsigned)i >> 3;
+
If i is an int, this works fine. But if i is
of a typedef'd type,
-
- myint i, j;
- ...
- j = (unsigned)i >> 3;
-
-
+myint i, j;
+...
+j = (unsigned)i >> 3;
+
and myint happens to be a long int, then the cast to
unsigned
@@ -1514,9 +1421,9 @@
do an unsigned right shift regardless of the sign of the left
operand. Hence,
- myint i, j;
- ...
- j = i >>> 3;
+myint i, j;
+...
+j = i >>> 3;
avoids the unsafe cast and will work as expected with any integral
@@ -1539,34 +1446,32 @@
class that holds an array of int's, and a user of that container
that computes the maximum of those int's.
-
- struct Collection
- {
- int array[10];
-
- void apply(void *p, void (*fp)(void *, int))
- {
- for (int i = 0; i < sizeof(array)/sizeof(array[0]); i++)
- fp(p, array[i]);
- }
- };
+struct Collection
+{
+ int array[10];
- void comp_max(void *p, int i)
- {
- int *pmax = (int *)p;
+ void apply(void *p, void (*fp)(void *, int))
+ {
+ for (int i = 0; i < sizeof(array)/sizeof(array[0]); i++)
+ fp(p, array[i]);
+ }
+};
- if (i > *pmax)
- *pmax = i;
- }
+void comp_max(void *p, int i)
+{
+ int *pmax = (int *)p;
- void func(Collection *c)
- {
- int max = INT_MIN;
+ if (i > *pmax)
+ *pmax = i;
+}
- c->apply(&max, comp_max);
- }
-
+void func(Collection *c)
+{
+ int max = INT_MIN;
+ c->apply(&max, comp_max);
+}
+
The C way makes heavy use of pointers and casting.
The casting is tedious, error prone, and loses all type safety.
@@ -1578,41 +1483,41 @@
and nested functions both to capture context
information and to improve locality.
- class Collection
- {
- int[10] array;
+class Collection
+{
+ int[10] array;
- void apply(void delegate(int) fp)
- {
- for (int i = 0; i < array.length; i++)
- fp(array[i]);
- }
- }
+ void apply(void delegate(int) fp)
+ {
+ for (int i = 0; i < array.length; i++)
+ fp(array[i]);
+ }
+}
- void func(Collection c)
- {
- int max = int.min;
+void func(Collection c)
+{
+ int max = int.min;
- void comp_max(int i)
- {
- if (i > max)
- max = i;
- }
+ void comp_max(int i)
+ {
+ if (i > max)
+ max = i;
+ }
- c.apply(comp_max);
- }
+ c.apply(comp_max);
+}
Pointers are eliminated, as well as casting and generic
pointers. The D version is fully type safe.
An alternate method in D makes use of function literals:
- void func(Collection c)
- {
- int max = int.min;
+void func(Collection c)
+{
+ int max = int.min;
- c.apply(delegate(int i) { if (i > max) max = i; } );
- }
+ c.apply(delegate(int i) { if (i > max) max = i; } );
+}
eliminating the need to create irrelevant function names.
@@ -1669,23 +1574,23 @@
type, and the number of arguments becomes a property
of the array:
-int sum(int[] values ...)
+int sum(int[] values ...)
{
- int s = 0;
+ int s = 0;
- foreach (int x; values)
+ foreach (int x; values)
s += x;
- return s;
+ return s;
}
-int main()
+int main()
{
- int i;
+ int i;
i = sum(8,7,6);
- printf("sum = %d\n", i);
+ printf("sum = %d\n", i);
- return 0;
+ return 0;
}
diff -uNr dmd-0.156/dmd/html/d/dbc.html dmd-0.157/dmd/html/d/dbc.html
--- dmd-0.156/dmd/html/d/dbc.html 2006-04-26 22:34:32.000000000 +0200
+++ dmd-0.157/dmd/html/d/dbc.html 2006-05-08 15:25:44.000000000 +0200
@@ -25,7 +25,7 @@
| Comments
- Last update Wed Apr 26 22:34:30 2006
+ Last update Mon May 8 15:25:42 2006
@@ -57,97 +57,66 @@
· Lexical
-
· Modules
-
· Declarations
-
· Types
-
· Properties
-
· Attributes
-
· Pragmas
-
· Expressions
-
· Statements
-
· Arrays
-
· Structs & Unions
-
· Classes
-
· Interfaces
-
· Enums
-
· Functions
-
· Operator Overloading
-
· Templates
-
· Mixins
-
· Contracts
-
· Conditional Compilation
-
· Handling errors
-
· Garbage Collection
-
· Memory Management
-
· Floating Point
-
· Inline Assembler
-
· Documentation Comments
-
· Interfacing To C
-
· Portability Guide
-
· Embedding D in HTML
-
· Named Character Entities
-
· Application Binary Interface
-
|
@@ -189,7 +158,7 @@
assert.
An assert inserts a checkable expression into
the code, and that expression must evaluate to true:
-assert(expression);
+assert(expression);
C programmers will find it familiar. Unlike C, however, an assert
in function bodies
@@ -206,15 +175,15 @@
would be in validating the return value of a function and of any side effects it has.
The syntax is:
-in
+in
{
...contract preconditions...
}
-out (result)
+out (result)
{
...contract postconditions...
}
-body
+body
{
...code...
}
@@ -228,18 +197,18 @@
body, the variable result is declared and assigned the return
value of the function.
For example, let's implement a square root function:
-long square_root(long x)
- in
+long square_root(long x)
+ in
{
- assert(x >= 0);
+ assert(x >= 0);
}
- out (result)
+ out (result)
{
- assert((result * result) == x);
+ assert((result * result) == x);
}
- body
+ body
{
- return math.sqrt(x);
+ return math.sqrt(x);
}
The assert's in the in and out bodies are called contracts.
@@ -254,12 +223,12 @@
If the function returns a void, there is no result, and so there can be no
result declaration in the out clause.
In that case, use:
-void func()
- out
+void func()
+ out
{
...contracts...
}
- body
+ body
{
...
}
@@ -273,17 +242,17 @@
The in-out statement can also be used inside a function, for example, it can be used
to check the results of a loop:
- in
+in
{
- assert(j == 0);
+ assert(j == 0);
}
-out
+out
{
- assert(j == 10);
+ assert(j == 10);
}
-body
+body
{
- for (i = 0; i < 10; i++)
+ for (i = 0; i < 10; i++)
j++;
}
diff -uNr dmd-0.156/dmd/html/d/dcompiler.html dmd-0.157/dmd/html/d/dcompiler.html
--- dmd-0.156/dmd/html/d/dcompiler.html 2006-04-26 22:34:32.000000000 +0200
+++ dmd-0.157/dmd/html/d/dcompiler.html 2006-05-08 15:25:44.000000000 +0200
@@ -25,7 +25,7 @@
| Comments
- Last update Wed Apr 26 22:34:31 2006
+ Last update Mon May 8 15:25:43 2006
@@ -57,131 +57,94 @@
· Overview
-
· D for Win32
-
· Win32 DLLs in D
-
· C .h to D Modules
-
· FAQ
-
· Style Guide
-
· Example: wc
-
· Future
-
· D Change Log
-
· Tech Tips
-
· Rationale
-
· Warnings
-
Articles
· Exception Safety
-
· Templates Revisited
-
Tools
· DMD D Compiler
-
· GDC D Compiler
-
· Linker
-
· Profiler
-
· Code Coverage
-
· DMD Script Shell
-
· Windows Debugger
-
Community
· News
-
· Forum
-
· Announcements
-
· Learn
-
· D links
-
Archives
· digitalmars.D
-
· digitalmars.D.dtl
-
· digitalmars.D.announce
-
· digitalmars.D.dwt
-
· digitalmars.D.learn
-
· digitalmars.D.bugs
-
· D.gnu
-
· Old D
-
Appendices
· Glossary
-
· Ascii Table
-
· Acknowledgements
-
|
diff -uNr dmd-0.156/dmd/html/d/ddoc.html dmd-0.157/dmd/html/d/ddoc.html
--- dmd-0.156/dmd/html/d/ddoc.html 2006-04-26 22:34:32.000000000 +0200
+++ dmd-0.157/dmd/html/d/ddoc.html 2006-05-08 15:25:44.000000000 +0200
@@ -24,7 +24,7 @@
| D
| Comments
- Last update Wed Apr 26 22:34:31 2006
+ Last update Mon May 8 15:25:43 2006
@@ -56,97 +56,66 @@
· Lexical
-
· Modules
-
· Declarations
-
· Types
-
· Properties
-
· Attributes
-
· Pragmas
-
· Expressions
-
· Statements
-
· Arrays
-
· Structs & Unions
-
· Classes
-
· Interfaces
-
· Enums
-
· Functions
-
· Operator Overloading
-
· Templates
-
· Mixins
-
· Contracts
-
· Conditional Compilation
-
· Handling errors
-
· Garbage Collection
-
· Memory Management
-
· Floating Point
-
· Inline Assembler
-
· Documentation Comments
-
· Interfacing To C
-
· Portability Guide
-
· Embedding D in HTML
-
· Named Character Entities
-
· Application Binary Interface
-
@@ -228,46 +197,46 @@
- - /** ... */ The two *'s after the opening /
-
- /++ ... +/ The two +'s after the opening /
-
- /// The three slashes
+
- The two *'s after the opening /
+
- The two +'s after the opening /
+
- The three slashes
The following are all embedded documentation comments:
-/// This is a one line documentation comment.
+
-/** So is this. */
+
-/++ And this. +/
+
-/**
+
-/**
+
-/*********************************
+
-/++
+
-/++
+
-/+++++++++++++++++++++++++++++++++
+
-/**************** Closing *'s are not part *****************/
+
The extra *'s and +'s on the comment opening, closing and left margin are
@@ -302,33 +271,33 @@
put an empty declaration comment for it.
-int a; /// documentation for a; b has no documentation
-int b;
+int a; int b;
-/** documentation for c and d */
-/** more documentation for c and d */
-int c;
-/** ditto */
-int d;
+
+
+int c;
+
+int d;
-/** documentation for e and f */ int e;
-int f; /// ditto
+ int e;
+int f;
-/** documentation for g */
-int g; /// more documentation for g
+
+int g;
-/// documentation for C and D
-class C
+class C
{
- int x; /// documentation for C.x
+ int x;
- /** documentation for C.y and C.z */
- int y;
- int z; /// ditto
+
+ int y;
+ int z; }
-/// ditto
-class D
+class D
{
}
@@ -360,7 +329,7 @@
there cannot be a Description without a Summary section.
-/***********************************
+
-void myfunc() { }
+void myfunc() { }
Named sections follow the Summary and Description unnamed sections.
@@ -386,14 +355,14 @@
Authors:
Lists the author(s) of the declaration.
-/**
+
Bugs:
Lists any known bugs.
-/**
+
@@ -402,7 +371,7 @@
Specifies the date of the current revision. The date should be in a form
parseable by std.date.
-/**
+
@@ -411,16 +380,16 @@
Provides an explanation for and corrective action to take if the associated
declaration is marked as deprecated.
-/**
+
-deprecated void foo() { ... }
+deprecated void foo() { ... }
Examples:
Any usage examples
-/**
+ |
@@ -241,7 +210,8 @@
TemplateInstance . IdentifierList
Typeof:
- typeof ( Expression )
+ typeof (
+ Expression )
StorageClasses:
StorageClass
@@ -264,11 +234,14 @@
Declarator2:
BasicType2 Declarator2
- ( Declarator2 )
- ( Declarator2 ) DeclaratorSuffixes
+ (
+ Declarator2 )
+ (
+ Declarator2 ) DeclaratorSuffixes
Parameters:
- ( ParameterList )
+ (
+ ParameterList )
( )
ParameterList:
@@ -328,42 +301,42 @@
Declaration syntax generally reads right to left:
-int x; // x is an int
-int* x; // x is a pointer to int
-int** x; // x is a pointer to a pointer to int
-int[] x; // x is an array of ints
-int*[] x; // x is an array of pointers to ints
-int[]* x; // x is a pointer to an array of ints
+int x; int* x; int** x; int[] x; int*[] x; int[]* x;
Arrays read right to left as well:
-int[3] x; // x is an array of 3 ints
-int[3][5] x; // x is an array of 5 arrays of 3 ints
-int[3]*[5] x; // x is an array of 5 pointers to arrays of 3 ints
+int[3] x; int[3][5] x; int[3]*[5] x;
Pointers to functions are declared using the function keyword:
-int function(char) x; // x is a pointer to a function taking a char argument
- // and returning an int
-int function(char)[] x; // x is an array of pointers to functions
- // taking a char argument and returning an int
+int function(char) x; int function(char)[] x;
C-style array declarations may be used as an alternative:
-int x[3]; // x is an array of 3 ints
-int x[3][5]; // x is an array of 3 arrays of 5 ints
-int (*x[5])[3]; // x is an array of 5 pointers to arrays of 3 ints
-int (*x)(char); // x is a pointer to a function taking a char argument
- // and returning an int
-int (*[] x)(char); // x is an array of pointers to functions
- // taking a char argument and returning an int
+int x[3]; int x[3][5]; int (*x[5])[3]; int (*x)(char); int (*[] x)(char);
@@ -371,11 +344,11 @@
must be of the same type:
-int x,y; // x and y are ints
-int* x,y; // x and y are pointers to ints
-int x,*y; // error, multiple types
-int[] x,y; // x and y are arrays of ints
-int x[],y; // error, multiple types
+int x,y; int* x,y; int x,*y; int[] x,y; int x[],y;
@@ -384,13 +357,13 @@
an Initializer from which the type can be inferred,
the type on the declaration can be omitted.
-static x = 3; // x is type int
-auto y = 4u; // y is type uint
-auto s = "string"; // s is type char[6]
+static x = 3; auto y = 4u; auto s = "string";
-class C { ... }
+class C { ... }
-auto c = new C(); // c is a handle to an instance of class C
+auto c = new C();
The Initializer cannot contain forward references
@@ -401,10 +374,10 @@
An implicit type inference for a class reference is not
an auto declaration, even if the auto storage class is used:
-class C { ... }
+class C { ... }
-auto c = new C(); // c is not RAII
-auto C d = new C(); // c is automatically destructed at the end of its scope
+auto c = new C(); auto C d = new C();
@@ -415,21 +388,21 @@
distinct type to the type checking system, for function overloading, and for the debugger.
-typedef int myint;
+typedef int myint;
-void foo(int x) { . }
-void foo(myint m) { . }
+void foo(int x) { . }
+void foo(myint m) { . }
.
myint b;
-foo(b); // calls foo(myint)
+foo(b);
Typedefs can specify a default initializer different from the
default initializer of the underlying type:
-typedef int myint = 7;
-myint m; // initialized to 7
+typedef int myint = 7;
+myint m;
@@ -441,7 +414,7 @@
alias declaration:
-alias abc.Foo.bar myint;
+alias abc.Foo.bar myint;
@@ -450,10 +423,10 @@
overloading is concerned. For example:
-alias int myint;
+alias int myint;
-void foo(int x) { . }
-void foo(myint m) { . } // error, multiply defined function foo
+void foo(int x) { . }
+void foo(myint m) { . }
@@ -467,27 +440,27 @@
For example:
-import string;
+import string;
-alias string.strlen mylen;
+alias string.strlen mylen;
...
-int len = mylen("hello"); // actually calls string.strlen()
+int len = mylen("hello");
The following alias declarations are valid:
-template Foo2(T) { alias T t; }
-alias Foo2!(int) t1;
-alias Foo2!(int).t t2;
-alias t1.t t3;
-alias t2 t4;
-
-t1.t v1; // v1 is type int
-t2 v2; // v2 is type int
-t3 v3; // v3 is type int
-t4 v4; // v4 is type int
+template Foo2(T) { alias T t; }
+alias Foo2!(int) t1;
+alias Foo2!(int).t t2;
+alias t1.t t3;
+alias t2 t4;
+
+t1.t v1; t2 v2; t3 v3; t4 v4;
@@ -496,13 +469,13 @@
to another:
-version (Win32)
+version (Win32)
{
- alias win32.foo myfoo;
+ alias win32.foo myfoo;
}
-version (linux)
+version (linux)
{
- alias linux.bar myfoo;
+ alias linux.bar myfoo;
}
@@ -511,7 +484,7 @@
current scope:
-alias string.strlen strlen;
+alias string.strlen strlen;
@@ -519,30 +492,30 @@
be overloaded with functions in the current scope:
-class A {
- int foo(int a) { return 1; }
+class A {
+ int foo(int a) { return 1; }
}
-class B : A {
- int foo( int a, uint b ) { return 2; }
+class B : A {
+ int foo( int a, uint b ) { return 2; }
}
-class C : B {
- int foo( int a ) { return 3; }
- alias B.foo foo;
+class C : B {
+ int foo( int a ) { return 3; }
+ alias B.foo foo;
}
-class D : C {
+class D : C {
}
-void test()
+void test()
{
- D b = new D();
- int i;
+ D b = new D();
+ int i;
- i = b.foo(1, 2u); // calls B.foo
- i = b.foo(1); // calls C.foo
+ i = b.foo(1, 2u); i = b.foo(1); }
@@ -551,7 +524,7 @@
alias declarations:
-alias foo.bar abc; // is it a type or a symbol?
+alias foo.bar abc;
@@ -574,15 +547,15 @@
of an expression. For example:
-void func(int i)
+void func(int i)
{
- typeof(i) j; // j is of type int
- typeof(3 + 6.0) x; // x is of type double
- typeof(1)* p; // p is of type pointer to int
- int[typeof(p)] a; // a is of type int[int*]
+ typeof(i) j; typeof(3 + 6.0) x; typeof(1)* p; int[typeof(p)] a;
- printf("%d\n", typeof('c').sizeof); // prints 1
- double c = cast(typeof(1.0))j; // cast j to double
+ printf("%d\n", typeof('c').sizeof); double c = cast(typeof(1.0))j; }
@@ -591,10 +564,10 @@
generated:
-void func()
-{ int i = 1;
- typeof(++i) j; // j is declared to be an int, i is not incremented
- printf("%d\n", i); // prints 1
+void func()
+{ int i = 1;
+ typeof(++i) j; printf("%d\n", i); }
@@ -607,21 +580,21 @@
super would be in a non-static member function.
-class A { }
+class A { }
-class B : A
+class B : A
{
- typeof(this) x; // x is declared to be a B
- typeof(super) y; // y is declared to be an A
+ typeof(this) x; typeof(super) y; }
-struct C
+struct C
{
- typeof(this) z; // z is declared to be a C*
- typeof(super) q; // error, no super struct for C
+ typeof(this) z; typeof(super) q; }
-typeof(this) r; // error, no enclosing struct or class
+typeof(this) r;
@@ -637,10 +610,10 @@
however, the variable is not initialized. If its value is
used before it is set, undefined program behavior will result.
- void foo()
+void foo()
{
- int x = void;
- writefln(x); // will print garbage
+ int x = void;
+ writefln(x); }
diff -uNr dmd-0.156/dmd/html/d/dlinks.html dmd-0.157/dmd/html/d/dlinks.html
--- dmd-0.156/dmd/html/d/dlinks.html 2006-04-26 22:34:30.000000000 +0200
+++ dmd-0.157/dmd/html/d/dlinks.html 2006-05-08 15:25:42.000000000 +0200
@@ -24,7 +24,7 @@
| D
| Comments
- Last update Wed Apr 26 22:34:29 2006
+ Last update Mon May 8 15:25:41 2006
@@ -56,137 +56,101 @@
· Overview
-
· D for Win32
-
· Win32 DLLs in D
-
· C .h to D Modules
-
· FAQ
-
· Style Guide
-
· Example: wc
-
· Future
-
· D Change Log
-
· Tech Tips
-
· Rationale
-
· Warnings
-
Articles
· Exception Safety
-
· Templates Revisited
-
Tools
· DMD D Compiler
-
· GDC D Compiler
-
· Linker
-
· Profiler
-
· Code Coverage
-
· DMD Script Shell
-
· Windows Debugger
-
Community
· News
-
· Forum
-
· Announcements
-
· Learn
-
· D links
-
Archives
· digitalmars.D
-
· digitalmars.D.dtl
-
· digitalmars.D.announce
-
· digitalmars.D.dwt
-
· digitalmars.D.learn
-
· digitalmars.D.bugs
-
· D.gnu
-
· Old D
-
Appendices
· Glossary
-
· Ascii Table
-
· Acknowledgements
-
|
D
+
Links
Wikis
@@ -259,6 +223,7 @@
Program editors
customized for use with D
+
.
Build
@@ -269,6 +234,11 @@
The Ragel State Machine Compiler
compiles finite state machines from regular languages into executable D code.
+
+ CandyDoc
+ shows how one can customize the Ddoc results with macros
+ and style sheets.
+
Libraries
@@ -352,27 +322,42 @@
-Forums, Blogs
+Forums, Blogs, Journals
- - Lars Ivar Igesund's D blog
.
+
Miscellaneous
@@ -410,6 +397,11 @@
- Ben Hinkle's D page
contains several D-related projects.
+
- DMedia is dedicated to
+ multimedia development with D. It will include 2d and 3d graphics, sound
+ programming and probably more.
+
+
- Check for a D user's group
in your community.
@@ -421,11 +413,13 @@
-
Why D
+
isn't Java? By Daniel Yokomiso.
- Burton Radons has prepared a
linux port
of D
+
. This is a very useful guide
for anyone wanting to build a new code generator for D for a
different processor.
@@ -435,8 +429,10 @@
- Pavel's DedicateD site.
Lots of D
+
projects with source code,
FAQs, D
+
news, etc.
-
@@ -445,11 +441,13 @@
-
Gnu D
+
compiler project on SourceForge.
-
The D
+
Journal (coming soon!)
@@ -498,6 +496,7 @@
- MKoD
- D
+
Programming
Language (MKoD == Magikal Kingdom of Dreams)
Always expanding, currently the site contains projects
@@ -525,6 +524,11 @@
- Unsorted D links.
+ - Gnu-D, GNU for the D language
+
+ - Walter Bright's SDWest 2004
+
+ presentation on D.
Japanese Language
@@ -582,6 +586,7 @@
Cut & paste the following free images on your web pages of interest to
D
+
programmers:
@@ -603,15 +608,18 @@
Corto's
D
+
button images:
Submissions
If you have any D
+
code, documents,
images or web pages of interest to D
+
programmers,
please
email
diff -uNr dmd-0.156/dmd/html/d/dll.html dmd-0.157/dmd/html/d/dll.html
--- dmd-0.156/dmd/html/d/dll.html 2006-04-26 22:34:32.000000000 +0200
+++ dmd-0.157/dmd/html/d/dll.html 2006-05-08 15:25:44.000000000 +0200
@@ -24,7 +24,7 @@
| D
| Comments
- Last update Wed Apr 26 22:34:30 2006
+ Last update Mon May 8 15:25:42 2006
@@ -56,131 +56,94 @@
· Overview
-
· D for Win32
-
· Win32 DLLs in D
-
· C .h to D Modules
-
· FAQ
-
· Style Guide
-
· Example: wc
-
· Future
-
· D Change Log
-
· Tech Tips
-
· Rationale
-
· Warnings
-
Articles
· Exception Safety
-
· Templates Revisited
-
Tools
· DMD D Compiler
-
· GDC D Compiler
-
· Linker
-
· Profiler
-
· Code Coverage
-
· DMD Script Shell
-
· Windows Debugger
-
Community
· News
-
· Forum
-
· Announcements
-
· Learn
-
· D links
-
Archives
· digitalmars.D
-
· digitalmars.D.dtl
-
· digitalmars.D.announce
-
· digitalmars.D.dwt
-
· digitalmars.D.learn
-
· digitalmars.D.bugs
-
· D.gnu
-
· Old D
-
Appendices
· Glossary
-
· Ascii Table
-
· Acknowledgements
-
|
@@ -218,41 +181,41 @@
A DllMain()
is required, looking like:
-import std.c.windows.windows;
+import std.c.windows.windows;
HINSTANCE g_hInst;
-extern (C)
+extern (C)
{
- void gc_init();
- void gc_term();
- void _minit();
- void _moduleCtor();
- void _moduleUnitTests();
+ void gc_init();
+ void gc_term();
+ void _minit();
+ void _moduleCtor();
+ void _moduleUnitTests();
}
-extern (Windows)
+extern (Windows)
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
- switch (ulReason)
+ switch (ulReason)
{
- case DLL_PROCESS_ATTACH:
- gc_init(); // initialize GC
- _minit(); // initialize module list
- _moduleCtor(); // run module constructors
- _moduleUnitTests(); // run module unit tests
- break;
-
- case DLL_PROCESS_DETACH:
- gc_term(); // shut down GC
- break;
-
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- // Multiple threads not supported yet
- return false;
+ case DLL_PROCESS_ATTACH:
+ gc_init(); _minit(); _moduleCtor(); _moduleUnitTests(); break;
+
+ case DLL_PROCESS_DETACH:
+ gc_term(); break;
+
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ return false;
}
g_hInst=hInstance;
- return true;
+ return true;
}
@@ -291,8 +254,8 @@
which prints a string:
mydll2.d:
-module mydll;
-export void dllprint() { printf("hello dll world\n"); }
+module mydll;
+export void dllprint() { printf("hello dll world\n"); }
mydll.def:
@@ -317,19 +280,19 @@
Now for a program, test.d, which will use the dll:
test.d:
-import mydll;
+import mydll;
-int main()
+int main()
{
mydll.dllprint();
- return 0;
+ return 0;
}
Create a clone of mydll2.d that doesn't have the function bodies:
mydll.d:
-export void dllprint();
+export void dllprint();
Compile and link with the command:
@@ -411,11 +374,11 @@
So, to write a COM object:
-import std.c.windows.com;
+import std.c.windows.com;
-class MyCOMobject : ComObject
+class MyCOMobject : ComObject
{
- extern (Windows):
+ extern (Windows):
...
}
@@ -445,96 +408,96 @@
Starting with the code for the DLL, mydll.d:
- /*
+
-import std.c.stdio;
-import std.c.stdlib;
-import std.string;
-import std.c.windows.windows;
-import std.gc;
+import std.c.stdio;
+import std.c.stdlib;
+import std.string;
+import std.c.windows.windows;
+import std.gc;
HINSTANCE g_hInst;
-extern (C)
+extern (C)
{
- void _minit();
- void _moduleCtor();
- void _moduleDtor();
- void _moduleUnitTests();
+ void _minit();
+ void _moduleCtor();
+ void _moduleDtor();
+ void _moduleUnitTests();
}
-extern (Windows)
+extern (Windows)
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
- switch (ulReason)
+ switch (ulReason)
{
- case DLL_PROCESS_ATTACH:
- printf("DLL_PROCESS_ATTACH\n");
- break;
-
- case DLL_PROCESS_DETACH:
- printf("DLL_PROCESS_DETACH\n");
- std.c.stdio._fcloseallp = null; // so stdio doesn't get closed
- break;
-
- case DLL_THREAD_ATTACH:
- printf("DLL_THREAD_ATTACH\n");
- return false;
-
- case DLL_THREAD_DETACH:
- printf("DLL_THREAD_DETACH\n");
- return false;
+ case DLL_PROCESS_ATTACH:
+ printf("DLL_PROCESS_ATTACH\n");
+ break;
+
+ case DLL_PROCESS_DETACH:
+ printf("DLL_PROCESS_DETACH\n");
+ std.c.stdio._fcloseallp = null; break;
+
+ case DLL_THREAD_ATTACH:
+ printf("DLL_THREAD_ATTACH\n");
+ return false;
+
+ case DLL_THREAD_DETACH:
+ printf("DLL_THREAD_DETACH\n");
+ return false;
}
g_hInst = hInstance;
- return true;
+ return true;
}
-export void MyDLL_Initialize(void* gc)
+export void MyDLL_Initialize(void* gc)
{
- printf("MyDLL_Initialize()\n");
+ printf("MyDLL_Initialize()\n");
std.gc.setGCHandle(gc);
_minit();
_moduleCtor();
-// _moduleUnitTests();
+}
-export void MyDLL_Terminate()
+export void MyDLL_Terminate()
{
- printf("MyDLL_Terminate()\n");
- _moduleDtor(); // run module destructors
+ printf("MyDLL_Terminate()\n");
+ _moduleDtor(); std.gc.endGCHandle();
}
-static this()
+static this()
{
- printf("static this for mydll\n");
+ printf("static this for mydll\n");
}
-static ~this()
+static ~this()
{
- printf("static ~this for mydll\n");
+ printf("static ~this for mydll\n");
}
-/* --------------------------------------------------------- */
+
-class MyClass
+class MyClass
{
- char[] concat(char[] a, char[] b)
+ char[] concat(char[] a, char[] b)
{
- return a ~ " " ~ b;
+ return a ~ " " ~ b;
}
- void free(char[] s)
+ void free(char[] s)
{
- delete s;
+ delete s;
}
}
-export MyClass getMyClass()
+export MyClass getMyClass()
{
- return new MyClass();
+ return new MyClass();
}
@@ -653,22 +616,22 @@
mydll.dll. There are two versions, one statically binds to
the DLL, and the other dynamically loads it.
-import std.stdio;
-import std.gc;
+import std.stdio;
+import std.gc;
-import mydll;
+import mydll;
-//version=DYNAMIC_LOAD;
+
-version (DYNAMIC_LOAD)
+version (DYNAMIC_LOAD)
{
- import std.c.windows.windows;
+ import std.c.windows.windows;
- alias void function(void*) MyDLL_Initialize_fp;
- alias void function() MyDLL_Terminate_fp;
- alias MyClass function() getMyClass_fp;
+ alias void function(void*) MyDLL_Initialize_fp;
+ alias void function() MyDLL_Terminate_fp;
+ alias MyClass function() getMyClass_fp;
- int main()
+ int main()
{ HMODULE h;
FARPROC fp;
MyDLL_Initialize_fp mydll_initialize;
@@ -677,73 +640,73 @@
getMyClass_fp getMyClass;
MyClass c;
- printf("Start Dynamic Link...\n");
+ printf("Start Dynamic Link...\n");
- h = LoadLibraryA("mydll.dll");
- if (h == null)
- { printf("error loading mydll.dll\n");
- return 1;
+ h = LoadLibraryA("mydll.dll");
+ if (h == null)
+ { printf("error loading mydll.dll\n");
+ return 1;
}
- fp = GetProcAddress(h, "D5mydll16MyDLL_InitializeFPvZv");
- if (fp == null)
- { printf("error loading symbol MyDLL_Initialize()\n");
- return 1;
+ fp = GetProcAddress(h, "D5mydll16MyDLL_InitializeFPvZv");
+ if (fp == null)
+ { printf("error loading symbol MyDLL_Initialize()\n");
+ return 1;
}
- mydll_initialize = cast(MyDLL_Initialize_fp) fp;
+ mydll_initialize = cast(MyDLL_Initialize_fp) fp;
(*mydll_initialize)(std.gc.getGCHandle());
- fp = GetProcAddress(h, "D5mydll10getMyClassFZC5mydll7MyClass");
- if (fp == null)
- { printf("error loading symbol getMyClass()\n");
- return 1;
+ fp = GetProcAddress(h, "D5mydll10getMyClassFZC5mydll7MyClass");
+ if (fp == null)
+ { printf("error loading symbol getMyClass()\n");
+ return 1;
}
- getMyClass = cast(getMyClass_fp) fp;
+ getMyClass = cast(getMyClass_fp) fp;
c = (*getMyClass)();
foo(c);
- fp = GetProcAddress(h, "D5mydll15MyDLL_TerminateFZv");
- if (fp == null)
- { printf("error loading symbol MyDLL_Terminate()\n");
- return 1;
+ fp = GetProcAddress(h, "D5mydll15MyDLL_TerminateFZv");
+ if (fp == null)
+ { printf("error loading symbol MyDLL_Terminate()\n");
+ return 1;
}
- mydll_terminate = cast(MyDLL_Terminate_fp) fp;
+ mydll_terminate = cast(MyDLL_Terminate_fp) fp;
(*mydll_terminate)();
- if (FreeLibrary(h) == FALSE)
- { printf("error freeing mydll.dll\n");
- return 1;
+ if (FreeLibrary(h) == FALSE)
+ { printf("error freeing mydll.dll\n");
+ return 1;
}
- printf("End...\n");
- return 0;
+ printf("End...\n");
+ return 0;
}
}
-else
-{ // static link the DLL
+else
+{
- int main()
+ int main()
{
- printf("Start Static Link...\n");
+ printf("Start Static Link...\n");
MyDLL_Initialize(std.gc.getGCHandle());
foo(getMyClass());
MyDLL_Terminate();
- printf("End...\n");
- return 0;
+ printf("End...\n");
+ return 0;
}
}
-void foo(MyClass c)
+void foo(MyClass c)
{
- char[] s;
+ char[] s;
- s = c.concat("Hello", "world!");
+ s = c.concat("Hello", "world!");
writefln(s);
c.free(s);
- delete c;
+ delete c;
}
diff -uNr dmd-0.156/dmd/html/d/dstyle.html dmd-0.157/dmd/html/d/dstyle.html
--- dmd-0.156/dmd/html/d/dstyle.html 2006-04-27 21:15:54.000000000 +0200
+++ dmd-0.157/dmd/html/d/dstyle.html 2006-05-08 15:25:44.000000000 +0200
@@ -25,7 +25,7 @@
| Comments
- Last update Thu Apr 27 21:15:52 2006
+ Last update Mon May 8 15:25:42 2006
@@ -57,131 +57,94 @@
· Overview
-
· D for Win32
-
· Win32 DLLs in D
-
· C .h to D Modules
-
· FAQ
-
· Style Guide
-
· Example: wc
-
· Future
-
· D Change Log
-
· Tech Tips
-
· Rationale
-
· Warnings
-
Articles
· Exception Safety
-
· Templates Revisited
-
Tools
· DMD D Compiler
-
· GDC D Compiler
-
· Linker
-
· Profiler
-
· Code Coverage
-
· DMD Script Shell
-
· Windows Debugger
-
Community
· News
-
· Forum
-
· Announcements
-
· Learn
-
· D links
-
Archives
· digitalmars.D
-
· digitalmars.D.dtl
-
· digitalmars.D.announce
-
· digitalmars.D.dwt
-
· digitalmars.D.learn
-
· digitalmars.D.bugs
-
· D.gnu
-
· Old D
-
Appendices
· Glossary
-
· Ascii Table
-
· Acknowledgements
-
@@ -222,13 +185,13 @@
Comments
- Use // comments to document a single line:
-
statement; // comment
-statement; // comment
+statement; statement;
- Use block comments to document a multiple line block of
statements:
-
/*
+
@@ -237,7 +200,7 @@
- Use nesting comments to 'comment out' a piece of trial code:
-
/+++++
+ | | | | | | |