-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #224 from wilzbach/use_names
- Loading branch information
Showing
63 changed files
with
4,012 additions
and
3,922 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# Alias & Strings | ||
|
||
Now that we know what arrays are, have gotten in touch of `immutable` | ||
and had a quick look at the basic types, it's time to introduce two | ||
new constructs in one line: | ||
|
||
alias string = immutable(char)[]; | ||
|
||
The term `string` is defined by an `alias` expression which defines it | ||
as a slice of `immutable(char)`'s. That is, once a `string` has been constructed | ||
its content will never change again. And actually this is the second | ||
introduction: welcome UTF-8 `string`! | ||
|
||
Due to their immutablility `string`s can perfectly be shared among | ||
different threads. Being a slice parts can be taken out of it without | ||
allocating memory. The standard function `std.algorithm.splitter` | ||
for example splits a string by newline without any memory allocations. | ||
|
||
Beside the UTF-8 `string` there are two more: | ||
|
||
alias wstring = immutable(dchar)[]; // UTF-16 | ||
alias dstring = immutable(wchar)[]; // UTF-32 | ||
|
||
The variants are most easily converted between each other using | ||
the `to` method from `std.conv`: | ||
|
||
dstring myDstring = to!dstring(myString); | ||
string myString = to!string(myDstring); | ||
|
||
Because `string`s are arrays the same operations apply to them | ||
e.g. strings might be concatenated using the `~` operator for example. | ||
The property `.length` isn't necessarily the number of characters | ||
for UTF strings so in that case use the function `std.utf.count`. | ||
|
||
To create multi-line strings use the | ||
`string str = q{ ... }` syntax. For raw strings you can either use | ||
backticks `` ` "unescaped string"` `` | ||
or the r-prefix `r"string that "doesn't" need to be escaped"`. | ||
|
||
## {SourceCode} | ||
|
||
import std.stdio; | ||
import std.utf: count; | ||
import std.string: format; | ||
|
||
void main() { | ||
// format generates a string using a printf | ||
// like syntax. D allows native UTF string | ||
// handling! | ||
string str = format("%s %s", "Hellö", | ||
"Wörld"); | ||
writeln("My string: ", str); | ||
writeln("Array length of string: ", | ||
str.length); | ||
writeln("Character length of string: ", | ||
count(str)); | ||
|
||
// Strings are just normal arrays, so any | ||
// operation that works on arrays works here | ||
// too! | ||
import std.array: replace; | ||
writeln(replace(str, "lö", "lo")); | ||
import std.algorithm: endsWith; | ||
writefln("Does %s end with 'rld'? %s", | ||
str, endsWith(str, "rld")); | ||
|
||
import std.conv: to; | ||
// Convert to UTF-32 | ||
dstring dstr = to!dstring(str); | ||
// .. which of course looks the same! | ||
writeln("My dstring: ", dstr); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
# Arrays | ||
|
||
The are two types of Arrays in D: **static** and **dynamic** | ||
arrays. Access to arrays of any kind is always bounds checked - | ||
a failed range check yields a `RangeError` which aborts the application. | ||
The brave can disable this with the compiler flag `-boundschecks=off` to squeeze | ||
the last cycles out of their binary. | ||
|
||
#### Static arrays | ||
|
||
*Static arrays are stored on the stack if defined inside a function | ||
or in static memory otherwise. They have a fixed, | ||
compile-time known length. A static array's type includes | ||
the fixed size: | ||
|
||
int[8] arr; | ||
|
||
`arr`s type is `int[8]`. Note that the size of the array is denoted | ||
near the type and not after the variable name like in C/C++. | ||
|
||
#### Dynamic arrays | ||
|
||
Dynamic arrays are stored on the heap and can be expanded | ||
or shrunk at runtime. A dynamic array is created using a `new` expression | ||
and its length: | ||
|
||
int size = 8; // run-time variable | ||
int[] arr = new int[size]; | ||
|
||
The type of `arr` is `int[]` which is a **slice** | ||
and will be explained in more detail in the next section. Multi-dimensional | ||
arrays can be created easily using the `auto arr = new int[3][3]` syntax. | ||
|
||
#### Array operations and properties | ||
|
||
Arrays can be concatenated using the `~` operator which | ||
will create a new dynamic array. Mathematical operations can | ||
be applied to whole arrays using the `c[] = a[] + b[]` syntax. | ||
Those operations might be optimized | ||
by the compiler to use special processors instructions that | ||
do the operations in one go. | ||
|
||
Both static and dynamic array provide the property `.length` | ||
which is read-only for static arrays but can be written to | ||
in case of dynamic arrays to change its size dynamically. The | ||
property `.dup` creates a copy of the array. | ||
|
||
When indexing an array through the `arr[idx]` syntax the special | ||
`$` syntax denotes an array's length. `arr[$ - 1]` thus | ||
references the last element and is a short form for `arr[arr.length - 1]`. | ||
|
||
### Exercise | ||
|
||
Complete the function `encrypt` to decrypt the secret message. | ||
The text should be encrypted using *Caesar encryption* | ||
that shifts the characters in the alphabet using a certain index. | ||
The to-be-encrypted text just contains characters in the range `a-z` | ||
which should make things easier. | ||
|
||
## {SourceCode:incomplete} | ||
|
||
import std.stdio; | ||
|
||
/** | ||
Shifts every character in the | ||
array `input` for `shift` characters. | ||
The character range is limited to `a-z` | ||
and the next character after z is a. | ||
|
||
Params: | ||
input = array to shift | ||
shift = shift length for each char | ||
Returns: | ||
Shifted char array | ||
*/ | ||
char[] encrypt(char[] input, char shift) | ||
{ | ||
auto result = input.dup; | ||
// ... | ||
return result; | ||
} | ||
|
||
void main() | ||
{ | ||
// We will now encrypt the message with | ||
// Caesar encryption and a | ||
// shift factor of 16! | ||
char[] toBeEncrypted = [ 'w','e','l','c', | ||
'o','m','e','t','o','d', | ||
// The last , is okay and will just | ||
// be ignored! | ||
]; | ||
writeln("Before: ", toBeEncrypted); | ||
auto encrypted = encrypt(toBeEncrypted, 16); | ||
writeln("After: ", encrypted); | ||
|
||
// Make sure we the algorithm works | ||
// as expected | ||
assert(encrypted == [ 'm','u','b','s','e', | ||
'c','u','j','e','t' ]); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# Associative Arrays | ||
|
||
D has built-in *associative arrays* also known as hash maps. | ||
An associative array with a key type of `int` and a value type | ||
of `string` is declared as follows: | ||
|
||
int[string] arr; | ||
|
||
The syntax follows the actual usage of the hashmap: | ||
|
||
arr["key1"] = 10; | ||
|
||
To test whether a key is located in the associative array, use the | ||
`in` expression: | ||
|
||
if ("key1" in arr) | ||
writeln("Yes"); | ||
|
||
The `in` expression actually returns a pointer to the value | ||
which is not `null` when found: | ||
|
||
if (auto test = "key1" in arr) | ||
*test = 20; | ||
|
||
Access to a key which doesn't exist yields an `RangeError` | ||
that immediately aborts the application. For a safe access | ||
with a default value, you can use `get(key, defaultValue)`. | ||
|
||
AA's have the `.length` property like arrays and provide | ||
a `.remove(val)` member to remove entries by their key. | ||
It is left as an exercise to the reader to explore | ||
the special `.byKeys` and `.byValues` ranges. | ||
|
||
### In-depth | ||
|
||
- [Associative arrays spec](https://dlang.org/spec/hash-map.html) | ||
- [byPair](http://dlang.org/phobos/std_array.html#.byPair) | ||
|
||
## {SourceCode} | ||
|
||
import std.stdio; | ||
|
||
/** | ||
Splits the given text into words and returns | ||
an associative array that maps words to their | ||
respective word counts. | ||
|
||
Params: | ||
text = text to be splitted | ||
*/ | ||
int[string] wordCount(string text) | ||
{ | ||
// The function splitter lazily splits the | ||
// input into a range | ||
import std.algorithm.iteration: splitter; | ||
import std.string: toLower; | ||
|
||
// Indexed by words and returning the count | ||
int[string] words; | ||
|
||
// Define a predicate to use for splitting | ||
// the string. | ||
alias pred = c => c == ' ' || c == '.' | ||
|| c == ',' || c == '\n'; | ||
|
||
// The parameter we pass behind ! is an | ||
// expression that marks the condition when | ||
// to split text | ||
foreach(word; splitter!pred(text.toLower())) | ||
{ | ||
// Increment word count if word | ||
// has been found. | ||
// Integers are by default 0. | ||
words[word]++; | ||
} | ||
|
||
return words; | ||
} | ||
|
||
void main() | ||
{ | ||
string text = q{This tour will give you an | ||
overview of this powerful and expressive systems | ||
programming language which compiles directly | ||
to efficient, *native* machine code.}; | ||
|
||
writeln("Word counts: ", wordCount(text)); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
# Basic types | ||
|
||
D provides a number of basic types which always have the same | ||
size **regardless** of the platform - the only exception | ||
is the `real` type which provides the highest possible floating point | ||
precision. There is no difference | ||
between the size of an integer regardless whether the application | ||
is compiled for 32bit or 64bit systems. | ||
|
||
<table class="table table-hover"> | ||
<tr><td width="250px"><code class="prettyprint">bool</code></td> <td>8-bit</td></tr> | ||
<tr><td><code class="prettyprint">byte, ubyte, char</code></td> <td>8-bit</td></tr> | ||
<tr><td><code class="prettyprint">short, ushort, wchar</code></td> <td>16-bit</td></tr> | ||
<tr><td><code class="prettyprint">int, uint, dchar</code></td> <td>32-bit</td></tr> | ||
<tr><td><code class="prettyprint">long, ulong</code></td> <td>64-bit</td></tr> | ||
</table> | ||
|
||
#### Floating point types: | ||
|
||
<table class="table table-hover"> | ||
<tr><td width="250px"><code class="prettyprint">float</code></td> <td>32-bit</td></tr> | ||
<tr><td><code class="prettyprint">double</code></td> <td>64-bit</td></tr> | ||
<tr><td><code class="prettyprint">real</code></td> <td>depending on platform, 80 bit on Intel x86 32-bit</td></tr> | ||
</table> | ||
|
||
The prefix `u` denotes *unsigned* types. `char` translates to | ||
UTF-8 characters, `wchar` is used in UTF-16 strings and `dchar` | ||
in UTF-32 strings. | ||
|
||
A conversion between variables of different types is only | ||
allowed by the compiler if no precision is lost. A conversion | ||
between floating point types (e.g `double` to `float`) | ||
is allowed though. | ||
|
||
A conversion to another type may be forced by using the | ||
`cast(TYPE) var` expression. | ||
|
||
The special keyword `auto` creates a variable and infers its | ||
type from the right hand side of the expression. `auto var = 7` | ||
will deduce the type `int` for `var`. Note that the type is still | ||
set at compile-time and can't be changed - just like with any other | ||
variable with an explicitly given type. | ||
|
||
### Type properties | ||
|
||
All data types have a property `.init` to which they are initialized. | ||
For all integers this is `0` and for floating points it is `NaN` (*not a number*). | ||
Integral and floating point types have a `.min` and `.max` property for the lowest | ||
and highest value they can represent. Floating point values have more properties | ||
`.nan` (NaN-value), `.infinity` (Infinity value), `.dig` (number of | ||
decimal digits of precisions), `.mant_dig` (number of bits in mantissa) and more. | ||
|
||
Every type also has a `.stringof` property which yields its name as a string. | ||
|
||
### In-depth | ||
|
||
- [Overview of all basic data types in D](https://dlang.org/spec/type.html) | ||
- [Type properties](https://dlang.org/spec/property.html) | ||
|
||
In D indexes have usually the alias type `size_t` as it is a type that | ||
is large enough to represent an offset into all addressible memory - that is | ||
`uint` for 32-bit and `ulong` for 64-bit architectures. | ||
|
||
`assert` is compiler built-in which verifies conditions in debug mode and aborts | ||
with an `AssertionError` if it fails. | ||
|
||
## {SourceCode} | ||
|
||
import std.stdio; | ||
|
||
void main() | ||
{ | ||
// Big numbers can be separated | ||
// with an underscore "_" | ||
// to enhance readability. | ||
int b = 7_000_000; | ||
short c = cast(short) b; // cast needed | ||
uint d = b; // fine | ||
int g; | ||
assert(g == 0); | ||
|
||
auto f = 3.1415f; // .f denotes a float | ||
|
||
// typeid(VAR) returns the type information | ||
// of an expression. | ||
writeln("type of f is ", typeid(f)); | ||
double pi = f; // fine | ||
// for floating-point types | ||
// implicit down-casting is allowed | ||
float demoted = pi; | ||
|
||
// access to type properties | ||
assert(int.init == 0); | ||
assert(int.sizeof == 4); | ||
assert(bool.max == 1); | ||
writeln(int.min, " ", int.max); | ||
writeln(int.stringof); // int | ||
} | ||
|
Oops, something went wrong.