Skip to content

Commit

Permalink
qf
Browse files Browse the repository at this point in the history
  • Loading branch information
edi33416 committed Sep 26, 2024
1 parent 63b19f6 commit d401c39
Showing 1 changed file with 191 additions and 0 deletions.
191 changes: 191 additions & 0 deletions docs/omni-open-con-ws/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <stdio.h>

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).

0 comments on commit d401c39

Please sign in to comment.