diff --git a/hands-on_dlang.md b/hands-on_dlang.md index d2a7c2b..488f60c 100644 --- a/hands-on_dlang.md +++ b/hands-on_dlang.md @@ -79,11 +79,18 @@ * [Uniform function call syntax (UFCS)](#uniform-function-call-syntax-ufcs) * [Scope guards](#scope-guards) * [Range algorithms](#range-algorithms) - * [Unittesting](#unittesting) + * [Unit testing](#unit-testing) * [Example](#example) - * [Executing unittests](#executing-unittests) + * [Executing unit tests](#executing-unit-tests) * [Code coverage](#code-coverage) * [String mixins](#string-mixins) + * [Compile Time Function Evaluation (CTFE)](#compile-time-function-evaluation-ctfe) + * [Conditional compilation](#conditional-compilation) + * [`static if` & `is`](#static-if-&-is) + * [`static foreach`](#static-foreach) + * [Template constraints](#template-constraints) + + ## Setup @@ -153,7 +160,7 @@ brew cask install visual-studio-code #### Without DUB -No special project setup is needed, you can order your sourcefiles any way you +No special project setup is needed, you can order your source files any way you like. You can compile them by invoking DMD: ```bash @@ -251,7 +258,7 @@ E.g. `my.thing` refers to a file `thing.d` in the folder `my/`. D has the following basic types: -| Datatypes | Size | +| Data types | Size | | ------------------------------- | ------------------------------------------------------------ | | `bool`, `byte`, `ubyte`, `char` | 8-bit | | `short`, `ushort`, `wchar` | 16-bit | @@ -298,7 +305,7 @@ And so do floating point types: | `.min_normal` | The smallest representable normalized value that is not `0` | | `.nan` | NaN value | | `.infinity` | Infinity value | -| `.dig` | number of decimal digits of precisions | +| `.dig` | number of decimal digits of precision | | `.mant_dig` | number of bits in mantissa | | … | | @@ -355,14 +362,14 @@ immutable int a; a = 5; // error ``` -`immutable` objects are implicitly shared accross threads, because the can never +`immutable` objects are implicitly shared across threads, because the can never change their value and thus race conditions are impossible. #### `const` `const` objects also can not be modified, but this is enforced only in the current scope. This means, that the object could be modified from a different -scope. Both mutable and `immutable` objects implictly convert to `const` +scope. Both mutable and `immutable` objects implicitly convert to `const` objects: ```D @@ -391,7 +398,7 @@ int add(int lhs, int rhs) { #### Return type deduction A functions return type can be defined to be `auto`. -In this case, the return type will be infered. +In this case, the return type will be inferred. Multiple return statements are possible, but must return compatible types. ```D @@ -503,7 +510,7 @@ struct Person { int height; this(int age, int height) { this.age = age; - this. height = height; + this.height = height; } } ``` @@ -541,7 +548,7 @@ They work basically the same as in C etc. D has two types of arrays, static arrays and dynamic arrays. Both of them are bounds checked unless this feature is explicitly switched of with the compiler -flag `--boundcheck=off`. +flag `--boundscheck=off`. #### Static arrays @@ -555,7 +562,7 @@ int[8] arr; #### Dynamic arrays -Dynamic arrays are stored on the heap and have a variabe length, which can +Dynamic arrays are stored on the heap and have a variable length, which can change during runtime. A dynamic array is created with the new expression: ```D @@ -645,7 +652,7 @@ alias string = immutable(char)[]; This works very similar to `typedef` from C / C++. -The above definition of `string` is atually the definition that is used by D. +The above definition of `string` is actually the definition that is used by D. This means that `string`s are just mutable slices of `immutable` `char`s. ### Control flow @@ -725,7 +732,7 @@ D has a `foreach` loops which allows for much better readable iterations. ##### Element iteration -We can easily iterate ofer slices using `foreach`: +We can easily iterate over slices using `foreach`: ```D auto arr = new int[5]; @@ -819,7 +826,7 @@ an infinite range can be taken: #### Copying ranges Copying a range by just using the assignment operator might not have the desired -effect, because iterationg over a range can be destructive (i.e. when the range +effect, because iterating over a range can be destructive (i.e. when the range holds internal pointers and a deep copy would be necessary). “copyable” ranges are called `ForwardRange`s. They need to implement a `.save` method which returns a copy of the range: @@ -870,10 +877,10 @@ map.remove("key1"); // remove a key from an associative array D's `class`es are very similar to Java's `class`es. -Any `class` type implicitely inherits from `Object`. +Any `class` type implicitly inherits from `Object`. ```D -class Foo { } // implicitely inherits from Object +class Foo { } // implicitly inherits from Object class Bar : Foo { } // Bar inherits from Foo ``` @@ -914,7 +921,7 @@ Classes can only inherit from a single class #### Checking for identity The `==` operator compares the content of two class objects. Checking for -identity is done using the `is` operator. Coparing to `null` is only possible +identity is done using the `is` operator. Comparing to `null` is only possible with this operator: ```D @@ -972,7 +979,7 @@ template add(T) { } ``` -D also allows implicit function template instanciation: +D also allows implicit function template instantiation: ```D add(5, 10); // same as add!int(5,10) @@ -991,7 +998,7 @@ print!(int, string)(42, "is the best number"); #### Other templates -Of course, `struct`s, `class`es and `interface`s can also be templated: +Of course, `struct`s, `class`es and `interface`s can also be templates: ```D struct S(T) { @@ -1237,9 +1244,9 @@ void foo() { ### Range algorithms -The modules `std.range` and `std.algorith` contain many functions which can be +The modules `std.range` and `std.algorithm` contain many functions which can be composed to express complex operations in a readable way. They are based on -ranges and will work on your datatypes, if they implement the range interface. +ranges and will work on your data types, if they implement the range interface. ```D import std.algorithm : canFind, map, @@ -1291,9 +1298,9 @@ to efficient, *native* machine code.`; } ``` -### Unittesting +### Unit testing -D has built-in unittests via a very simple syntax, which can appear anywhere in +D has built-in unit tests via a very simple syntax, which can appear anywhere in a D module: ```D @@ -1345,10 +1352,10 @@ unittest { } ``` -#### Executing unittests +#### Executing unit tests -To execute the unittests, just compile with the `-unittest` flag. When running -the program, the unittests get run before the main function is executed. When +To execute the unit tests, just compile with the `-unittest` flag. When running +the program, the unit tests get run before the main function is executed. When using DUB, just run ```bash @@ -1422,7 +1429,7 @@ void main() { ### Conditional compilation D has several methods of conditional compilation which can be used for code -generation. D’s traits and the module `std.traits` contain many usefull tools +generation. D’s traits and the module `std.traits` contain many useful tools which can be used with the following constructs. #### `static if` & `is`