This shows you the differences between two versions of the page.
dss:laboratoare:04 [2019/06/21 15:10] razvan.nitu1305 |
dss:laboratoare:04 [2021/07/12 18:58] (current) razvan.nitu1305 [5. Ranges] |
||
---|---|---|---|
Line 427: | Line 427: | ||
</code> | </code> | ||
- | ==== Nogc Function ==== | + | ==== Nogc Functions ==== |
D is a garbage collected language. Many data structures and algorithms in most D programs take advantage of dynamic memory blocks that are managed by the garbage collector (GC). Such memory blocks are reclaimed again by the GC by an algorithm called garbage collection. | D is a garbage collected language. Many data structures and algorithms in most D programs take advantage of dynamic memory blocks that are managed by the garbage collector (GC). Such memory blocks are reclaimed again by the GC by an algorithm called garbage collection. | ||
Line 472: | Line 472: | ||
For an extensive list of operations forbidden in **@nogc** code, check this [[https://dlang.org/spec/function.html#nogc-functions|link]] | For an extensive list of operations forbidden in **@nogc** code, check this [[https://dlang.org/spec/function.html#nogc-functions|link]] | ||
+ | |||
+ | ==== Ranges ==== | ||
+ | |||
+ | Any object which fulfills the following interface is called a **range** (or more specific **InputRange**) and is thus a type that can be iterated over: | ||
+ | |||
+ | <code D> | ||
+ | interface InputRange(E) | ||
+ | { | ||
+ | bool empty(); | ||
+ | E front(); | ||
+ | void popFront(); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Check this [[https://tour.dlang.org/tour/en/basics/ranges|link]] for an example of a Fibonaci range implementation. | ||
+ | |||
+ | Besides the dumbest form of range, the **InputRange**, the are other forms of ranges: | ||
+ | |||
+ | * **ForwardRange** is an **InputRange** and additionally requires the **save** method that saves the state of the range. | ||
+ | * **BidirectionalRange** is a **ForwardRange** and additionally requires the **back** and **popBack** methods. | ||
+ | * **RandomAccessRange** is a **BidirectionalRange** and additionally requires the **[]** operator (and another property depending whether the range is finite or infinite) | ||
+ | |||
+ | For more informations on ranges, you can read the outstanding [[http://ddili.org/ders/d.en/ranges.html|description]] in Ali's book. | ||
+ | |||
+ | ===== Exercises ===== | ||
+ | |||
+ | The lab can be found at this [[https://github.com/RazvanN7/D-Summer-School/tree/master/lab-04|link]]. | ||
+ | |||
+ | ==== 1. Complex numbers ==== | ||
+ | |||
+ | Implement a struct that will emulate a [[https://en.wikipedia.org/wiki/Complex_number|complex number]]. The operations that need to be implemented on complex numbers are: assignment, addition, subtraction, multiply and division. Write a unittest to assure the validity of the implementation. | ||
+ | |||
+ | <note> | ||
+ | What happens if you comment the assignment operator? | ||
+ | </note> | ||
+ | |||
+ | ==== 2. Alias ==== | ||
+ | |||
+ | Navigate to the ''2-alias'' directory. Inspect the two source files. Compile de code: | ||
+ | |||
+ | <code bash> | ||
+ | dmd main.d func.d | ||
+ | </code> | ||
+ | |||
+ | What happens? Why? Before invoking function **fun**, add the line: | ||
+ | |||
+ | <code D> | ||
+ | alias fun = func.fun; | ||
+ | </code> | ||
+ | |||
+ | What happens? Why? | ||
+ | |||
+ | ==== 3. Nullable ==== | ||
+ | |||
+ | Implement a [[https://dlang.org/library/std/typecons/nullable.html#2|Nullable]] object. In D, there are certain types that cannot be null (such as int, struct objects etc.), also there are algorithms that work only for types that can be in the null state; for those algorithms to work with non-nullable types, an abstraction is considered in the form of a Nullable object. | ||
+ | |||
+ | * Implement the Nullable(T) struct by having a templated field which is the value and a boolean that keeps track whether the value is null or not; the Nullable object is considered null if the field holds the **.init** value | ||
+ | * Implement the methods: | ||
+ | - get: returns the value of the object if not null; if null, halts execution raising an assert error with the appropriate message; | ||
+ | - opAssign: a Nullable!T object can be assigned a value of type T; | ||
+ | - a constructor that takes a value of type T; | ||
+ | |||
+ | What is the problem with this implementation? | ||
+ | |||
+ | ==== 4. Alias this ==== | ||
+ | |||
+ | Solve the problem of the previous **Nullable!T** implementation by forwarding unknown operations to the T object contained. Test the new implementation by adding instances of **Nullable** with int, struct and class. | ||
+ | |||
+ | ==== 5. Ranges ==== | ||
+ | |||
+ | Implement a stack that respects the range interface. | ||
+ | |||
+ | - Implement the stack as an input range (you may use builtin arrays as the underlying data structure); | ||
+ | - Improve the stack by adding support for forward range methods; | ||
+ | - Improve the stack by adding support for bidirectional range methods; | ||
+ | - Improve the stack by adding support for random access range methods; | ||
+ | |||
+ | To test your implementation you can use these [[https://dlang.org/phobos/std_range_primitives.html|range primitives]] |