Compare commits

...

2 Commits

Author SHA1 Message Date
Tristan B. Velloza Kildaire c8e63b8082 Blog
- Work-in-progress entry fpr the `niknaks` project and its updates
2024-05-02 08:17:22 +02:00
Tristan B. Velloza Kildaire 87d52986b4 Blog
- Work-in-progress entry fpr the `niknaks` project and its updates
2024-05-02 08:12:13 +02:00
1 changed files with 176 additions and 0 deletions

View File

@ -145,4 +145,180 @@ else
ERROR("Could not get a valid project description");
return;
}
```
## Configuration engine
TODO: Add this
## Predicates, Optionals and some tooling
One of the things that come sup quite a lot when programming
and dealing with arrays of data (items of the same data type)
is the ability to programatically filter such collections of
data by some form of reusable component - enter _the predicate_.
The predicate is not any sort of new wrapper type I came up
with, but rather it is a templatised (type-parameterized) alias
which when used, expands into a `bool delegate(T)` - some delegate
which takes in a single argument of type `T` and returns a `bool`,
a _verdict_.
The definition is as follows:
```d
/**
* Predicate for testing an input type
* against a condition and returning either
* `true` or `false`
*
* Params:
* T = the input type
*/
template Predicate(T)
{
/**
* Parameterized delegate pointer
* taking in `T` and returning
* either `true` or `false`
*/
alias Predicate = bool delegate(T);
}
```
There is also a handy `predicateOf(alias)` template used for
constructing predicates from some symbol (either a function
or a delegate).
### Example code
#### Predicate example
Suppose we have some function as shown below:
```d
private bool isEven(int number)
{
return number%2==0;
}
```
We can then construct a predicate out of it
and test it against some input values:
```d
/**
* Uses a `Predicate` which tests
* an integer input for evenness
*
* We create the predicate by
* passing in the symbol of the
* function or delegate we wish
* to use for testing truthiness
* to a template function
* `predicateOf!(alias)`
*/
unittest
{
Predicate!(int) pred = predicateOf!(isEven);
assert(pred(0) == true);
assert(pred(1) == false);
bool delegate(int) isEvenDel = toDelegate(&isEven);
pred = predicateOf!(isEvenDel);
assert(pred(0) == true);
assert(pred(1) == false);
}
```
## Delay mechanism
One of the things I decided to put together was a programming
structure that I thought would be usable in a scenario as follows:
> You have run some task on some remote server and now you want to
regularly check in with it and see when a reply is sent back that
satisfies some requirement. You _also_ can't do this forever so you
want to set an interval for how frequently you re-check and then also
a total timeout time which will be your deadline - when you exceed
it then you stop checking.
This mechanism is called the `Delay` and can be found in the
`niknaks.mechanisms` package.
The constructor appears as follows:
```d
/**
* Constructs a new delay mechanism
* with the given delegate to call
* in order to determine the verdict,
* an interval to call it at and the
* total timeout
*
* Params:
* verdictProvider = the provider of the verdicts
* interval = thje interval to retry at
* timeout = the timeout
*/
this(VerdictProviderDelegate verdictProvider, Duration interval, Duration timeout)
{
this.verdictProvider = verdictProvider;
this.interval = interval;
this.timeout = timeout;
}
```
Therefore you can set those two parameters mentioned earlier. The first
parameter is the "check" that is to be periodically called. The delay
system will return successfully if at some point this `VerdictProviderDelegate`
returns a `true` _within_ the timeout window of `timeout`. If you
keep getting `false` returned and go over the `timeout` period then
a `DelayTimeoutException` is thrown.
### Example code
Here is an example where my verdict function (technically a delegate in
the case of a D unittest) which refers to a variable `cnt`. This example
illustrates the multiple retry calls to said function due to it only
returning a `true` verdict on the _second_ call.
```d
/**
* Tests out the delay mechanism
* with a verdict provider (as a
* delegate) which is only true
* on the second call
*/
unittest
{
int cnt = 0;
bool happensLater()
{
cnt++;
if(cnt == 2)
{
return true;
}
else
{
return false;
}
}
Delay delay = new Delay(&happensLater, dur!("seconds")(1), dur!("seconds")(1));
try
{
delay.go();
assert(true);
}
catch(DelayTimeoutException e)
{
assert(false);
}
}
```