Skip to content

Commit

Permalink
Merge pull request #224 from wilzbach/use_names
Browse files Browse the repository at this point in the history
Use individual section files #137 #184
  • Loading branch information
wilzbach authored Jun 14, 2016
2 parents 049259d + 2545469 commit 6db66e9
Show file tree
Hide file tree
Showing 63 changed files with 4,012 additions and 3,922 deletions.
1,549 changes: 0 additions & 1,549 deletions public/content/en/basics.md

This file was deleted.

73 changes: 73 additions & 0 deletions public/content/en/basics/alias-strings.md
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);
}

102 changes: 102 additions & 0 deletions public/content/en/basics/arrays.md
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' ]);
}

89 changes: 89 additions & 0 deletions public/content/en/basics/associative-arrays.md
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));
}

99 changes: 99 additions & 0 deletions public/content/en/basics/basic-types.md
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
}

Loading

0 comments on commit 6db66e9

Please sign in to comment.