diff --git a/docs/omni-open-con-ws/intro.md b/docs/omni-open-con-ws/intro.md index dcacd7d..aaf48ae 100644 --- a/docs/omni-open-con-ws/intro.md +++ b/docs/omni-open-con-ws/intro.md @@ -129,3 +129,194 @@ This means that there are no uninitialized variables. int *p; // equivalent to int *p = null; // The same goes for structs and classes: their fields are recursively initialised. ``` + +### Arrays + +The fundamental difference between a C array and a D array is that the former is represented by a simple pointer, while the latter is represented by a pointer and a size. +This design decision was taken because of the numerous cases of C buffer overflow attacks that can be simply mitigated by automatically checking the array bounds. +Let's take a simple example: + +```c +#include + +void main() +{ + int a = 5; + int b[10]; + b[11] = 9; + printf("%d\n", a); +} +``` + +Compiling this code (without the stack protector activated) will lead to a buffer overflow in which the variable `a` will be modified and the print will output `9`. +Compiling the same code with D (simply replace the include with an `import std.stdio : printf`) will issue a compile time error that states that 11 is beyond the size of the array. +Aggregating the pointer of the array with its size facilitates a safer implementation of arrays. + +D implements 2 types of arrays: +1. [Static Arrays](https://dlang.org/spec/arrays.html#static-arrays): their length must be known at compile time and therefore cannot be modified; all examples up until this point have been using static arrays. +1. [Dynamic Arrays](https://dlang.org/spec/arrays.html#dynamic-arrays): their length may change dynamically at run time. + +#### Slicing + +Slicing an array means to specify a subarray of it. +An array slice does not copy the data, it is only another reference to it: + +```d +void main() +{ + int[10] a; // declare array of 10 ints + int[] b; + + b = a[1..3]; // a[1..3] is a 2 element array consisting of a[1] and a[2] + int x = b[1]; // equivalent to `int x = 0;` + a[2] = 3; + int y = b[1]; // equivalent to `int y = 3;` +} +``` + +#### Array setting + +```d +void main() +{ + int[3] a = [1, 2, 3]; + int[3] c = [ 1, 2, 3, 4]; // error: mismatched sizes + int[] b = [1, 2, 3, 4, 5]; + a = 3; // set all elements of a to 3 + a[] = 2; // same as `a = 3`; using an empty slice is the same as slicing the full array + b = a[0 .. $]; // $ evaluates to the length of the array (in this case 10) + b = a[]; // semantically equivalent to the one above + b = a[0 .. a.length]; // semantically equivalent to the one above + b[] = a[]; // semantically equivalent to the one above + b[2 .. 4] = 4; // same as b[2] = 4, b[3] = 4 + b[0 .. 4] = a[0 .. 4]; // error, a does not have 4 elements + a[0 .. 3] = b; // error, operands have different length +} +``` + +**.length** is a builtin array property. +For an extensive list of array properties click [here](https://dlang.org/spec/arrays.html#array-properties). + +#### Array Concatenation + +```d +void main() +{ + int[] a; + int[] b = [1, 2, 3]; + int[] c = [4, 5]; + + a = b ~ c; // a will be [1, 2, 3, 4, 5] + a = b; // a refers to b + a = b ~ c[0..0]; // a refers to a copy of b + a ~= c; // equivalent to a = a ~ c; +} +``` + +Concatenation always creates a copy of its operands, even if one of the operands is a 0-length array. +The operator `~=` does not always create a copy. + +When adjusting the length of a dynamic array there are 2 possibilities: +1. The resized array would overwrite data, so in this case a copy of the array is created. +1. The resized array does not interfere with other data, so it is resized in place. +For more information click [here](https://dlang.org/spec/arrays.html#resize). + +#### Vector operations + +```d +void main() +{ + int[] a = [1, 2, 3]; + int[] b; + int[] c; + + b[] = a[] + 4; // b = [5, 6, 7] + c[] = (a[] + 1) * b[]; // c = [10, 18, 28] +} +``` + +Many array operations, also known as vector operations, can be expressed at a high level rather than as a loop. +A vector operation is indicated by the slice operator appearing as the left-hand side of an assignment or an op-assignment expression. +The right-hand side can be an expression consisting either of an array slice of the same length and type as the left-hand side or a scalar expression of the element type of the left-hand side, in any combination. + +Using the concepts of slicing and concatenation, we can modify the original example (that does the removal of an element from the array) so that the `for` loop is no longer necessary: + +```d +int main() +{ + int position = 7, c, n = 10; + int[] array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + array = array[0 .. position] ~ array[position + 1 .. $]; + + import std.stdio; + writeln("Resultant array:"); + writeln(array); + + return 0; +} +``` + +[`writeln`](https://dlang.org/library/std/stdio/writeln.html) is a function from the standard D library that does not require a format and is easily usable with a plethora of types. + +As you can see, the resulting code is much more expressive and fewer lines of code were utilized. + +### Associative Arrays (AA) + +Associative arrays represent the D language hashtable implementation and have the following syntax: + +```d +void main() +{ + // Associative array of ints that are indexed by string keys. + // The KeyType is string. + int[string] aa; + + // set value associated with key "hello" to 3 + aa["hello"] = 3; + int value = aa["hello"]; + + // remove the pair ("hello", 3) + aa.remove("hello") +} +``` + +`remove(key)` does nothing if the given key does not exist and returns `false`. +If the given key does exist, it removes it from the AA and returns `true`. +All keys can be removed by using the method `clear`. + +For more advanced operations on AAs check this [link](https://dlang.org/spec/hash-map.html#construction_assignment_entries). +For an exhaustive list of the AA properties check this [link](https://dlang.org/spec/hash-map.html#properties). + +### Structs + +In D, structs are simple aggregations of data and their associated operations on that data: + +```d +struct Rectangle +{ + size_t length, width; + int id; + + size_t area() { return length*width; } + size_t perimeter() { return 2*(length + width); } + size_t isSquare() { return length == width; } + void setId(int id) { this.id = id; } +} +``` + +# Classes + +In D, classes are very similar with java classes: + +1. Classes can implement any number of interfaces +1. Classes can inherit a single class +1. Class objects are instantiated by reference only +1. super has the same meaning as in Java +1. overriding rules are very similar + +The fundamental difference between **structs** and **classes** is that the former are **value** types, while the latter are **reference** types. +This means that whenever a struct is passed as an argument to an lvalue function parameter, the function will operate on a copy of the object. +When a class is passed as an argument to an lvalue function parameter, the function will receive a reference to the object. + +Both **structs** and **classes** are covered more in depth in [Advanced Structs and Classes](./structs-classes/asc.md). \ No newline at end of file