Delight inherits most of its type system from D. This page contains a brief summary, and a list of the changes from D.
The basic types are the same as in D. The main ones are:
# Integers, signed and unsigned bool byte, ubyte short, ushort int, uint long, ulong # Floating point values with various levels of precision float, double, real # Complex values cfloat, cdouble, creal # UTF 8/16/32 elements char, wchar, dchar
There are three types of array:
# A static array # (four integers, initially all zero) int a a = 50 # A dynamic array # (initially empty) int b b ~= [1,2,3] # Append three values # An associative array (hash / dictionary / map) # (initially empty) int[int] c c = 123
Array accesses are bounds-checked.
An important difference between D and Delight is that a Delight array is considered true if and only if its length is non-zero:
int a assert not a # Empty a =  assert not a # Still empty a =  assert a # Contains a 0
In D, an empty array may be considered true or false, depending on exactly how it was allocated. Also, D allows null to be used to mean an empty array. In Delight, you can only use .
Delight inherits D's powerful (but somewhat complicated) const/invariant system. Some examples:
# This function requires an array it can change void a(char data): ... # This function will not change the array void b(const(char) data): ... # This function requires an array that will not change void c(invariant(char) data): ...
Neither b not c can change their input array, but c additionally requires that no-one else will change it either. For example, c might want to store the data somewhere and use it later.
These modifiers are transitive: if foo is const then so are foo.a and foo.a.b, etc.
Mutable and invariant types are implicitly converted to const where needed.
If an object is const, only const methods on it can be called. A const method looks like this (days):
class Foo: int weeks = 2 int days() const: return weeks * 7 unittest: const f = new Foo() assert f.days == 14
This has the effect of making the implicit this parameter const in the method.
The string type is defined as an alias for an array of invariant characters:
alias invariant(char) string
Therefore, strings never change. If you want to edit a string, use dup to make a mutable copy. Use idup to get an invariant copy:
string spaceToUnder(string before): char buffer = before.dup for ref char c in buffer: if c == ' ': c = '_' return buffer.idup assert spaceToUnder("a nice message") == "a_nice_message"
(note the use of ref to make c refer to the element in the buffer, rather than a copy of it)
Structs work just as in C. They are allocated on the stack and passed by value (copied).
Classes are implemented as pointers. They are allocated on the heap and passed by reference.
class Foo: char name struct Bar: char name void myFunc(): Foo foo = new Foo() Bar bar
Class pointers cannot be null by default. See the NullPointerException page for details.
You can also use pointers (as in C), but usually you won't need them. Arrays are bounds-checked, but there are no safe-guards when using pointers.
If you want a variable to hold a call-back, use:
int myFunc(string a): ... int delegate(string a) myCallback myCallback = &myFunc myCallback("foo")
A delegate is a structure containing two pointers: the address of the function and a context. A delegate can therefore be used to hold a method on a particular object. There is also a simpler function type which only holds one address. You should probably avoid using this as it's less flexible.
# A named enum # (creates a new type extending int) enum Colour: Red, Green, Blue assert Colour.Red == 0 assert Colour.Green == 1 Colour c = Colour.Blue # An anonymous enum enum extends bool: On = true, Off = false assert On == true # The values can be specified explicitly enum Flags: None = 0 Needed = 0x1 Provided = 0x2 Error = 0x4
Casting a class to another class results in null if the object isn't derived from the target class or interface. The result is therefore a maybe type, which you can remove using an if statement, e.g.
void age(Tree tree): if Oak oak = cast(Oak) tree: oak.produceAcorns()
Of course, casting should be avoided where possible. A generic produceSeed method would have been more appropriate in this case.
Install it and try it out...