Liking cljdoc? Tell your friends :D

dvlopt.dsim

Idiomatic, purely-functional discrete event simulation and much more.

See README first in order to make sense of all this. It provides definitions and rationale for concepts.

Arity convention for e-XXX functions

Arities for e-XXX functions follow the same convention. Providing both ranks and path refers explicitely to a prioritized location in the event tree. Without path, the path of the currently executing flat event is retrieved (ie. acts with the given ranks relative to the current path). Not providing either refers explicitely to the current flat event and its working queue.

Idiomatic, purely-functional discrete event simulation and much more.

See README first in order to make sense of all this. It provides definitions and rationale for concepts.


Arity convention for `e-XXX` functions
======================================

Arities for `e-XXX` functions follow the same convention. Providing both `ranks` and `path` refers explicitely
to a prioritized location in the event tree. Without `path`, the path of the currently executing flat event is
retrieved (ie. acts with the given `ranks` relative to the current `path`). Not providing either refers explicitely
to the current flat event and its working queue.

raw docstring

basic-engineclj/s

(basic-engine)

Returns a function ctx -> ctx which pops the next ranked events and executes them.

If the said ctx does not have any event, returns nil.

Returns a function `ctx -> ctx` which pops the next ranked events and executes them.

If the said `ctx` does not have any event, returns nil.
sourceraw docstring

e-assocclj/s

(e-assoc ctx event)
(e-assoc ctx ranks event)
(e-assoc ctx ranks path event)

Schedules an event.

Follows arity convention presented in the namespace description.

ArityMeans
2Replaces the current working queue with the given event.
3Schedules the event in the event tree for the given ranks and path returned by path.
4Full control of when and where in the event tree.

It is bad practice to associate something such as an empty queue. It means that "nothing" is unnecessarily scheduled.

Schedules an `event`.

Follows arity convention presented in the namespace description.

| Arity | Means |
|---|---|
| 2 | Replaces the current working queue with the given `event`. |
| 3 | Schedules the `event` in the event tree for the given `ranks` and path returned by [[path]]. |
| 4 | Full control of when and where in the event tree. |

It is bad practice to associate something such as an empty queue. It means that "nothing" is unnecessarily
scheduled.
sourceraw docstring

e-conjclj/s

(e-conj ctx event)
(e-conj ctx ranks event)
(e-conj ctx ranks path event)

Enqueues an event, creating a queue if there is none.

Follows arity convention presented in the namespace description (see also e-assoc).

It is bad practice to conj something such as an empty queue. It means that "nothing" is unnecessarily scheduled.

Enqueues an `event`, creating a queue if there is none.

Follows arity convention presented in the namespace description (see also [[e-assoc]]).

It is bad practice to conj something such as an empty queue. It means that "nothing" is unnecessarily
scheduled.
sourceraw docstring

e-dissocclj/s

(e-dissoc ctx)
(e-dissoc ctx ranks)
(e-dissoc ctx ranks path)

Cancels a scheduled event.

Follows arity convention presented in the namespace description.

ArityMeans
1Removes the currently executing flat event.
2In the event tree, removes the event located at ranks relative to the current path.
3In the event tree, remove the event located at ranks and path.
Cancels a scheduled event.

Follows arity convention presented in the namespace description.

| Arity | Means |
|---|---|
| 1 | Removes the currently executing flat event. |
| 2 | In the event tree, removes the event located at `ranks` relative to the current path. |
| 3 | In the event tree, remove the event located at `ranks` and `path`. |
sourceraw docstring

e-getclj/s

(e-get ctx)
(e-get ctx ranks path)
(e-get ctx ranks path not-found)

Retrieves a scheduled event.

Follows arity convention presented in the namespace description.

ArityMeans
1Returns the current working queue.
3Returns the event located path and prioritized by ranks in the event tree.
4As above, but returns not-found is instead of nil when there is no event.
Retrieves a scheduled event.

Follows arity convention presented in the namespace description.

| Arity | Means |
|---|---|
| 1 | Returns the current working queue. |
| 3 | Returns the event located `path` and prioritized by `ranks` in the event tree. |
| 4 | As above, but returns `not-found` is instead of nil when there is no event. |
sourceraw docstring

e-intoclj/s

(e-into ctx events)
(e-into ctx ranks events)
(e-into ctx ranks path events)

Like e-conj, but for a collection of events.

Follows arity convention presented in the namespace description (see also e-assoc).

Metadata of the given collection is merged with the already existing queue if there is one.

It is bad practice to add empty events. A queue will be scheduled for nothing.

Like [[e-conj]], but for a collection of `events`.

Follows arity convention presented in the namespace description (see also [[e-assoc]]).

Metadata of the given collection is merged with the already existing queue if there is one.

It is bad practice to add empty events. A queue will be scheduled for nothing.
sourceraw docstring

e-isolateclj/s

(e-isolate ctx)
(e-isolate ctx ranks)
(e-isolate ctx ranks path)

Isolating means that the current working queue or the requested queue in the event tree will be nested in an outer queue.

Follows arity convention presented in the namespace description.

Isolating means that the current working queue or the requested queue in the event tree
will be nested in an outer queue.

Follows arity convention presented in the namespace description.
sourceraw docstring

e-pushclj/s

(e-push ctx q)
(e-push ctx ranks q)
(e-push ctx ranks path q)

Similar to e-into but works the other way around. Already scheduled events are added to the given queue q and their metadata data is merged.

Follows arity convention presented in the namespace description.

Similar to [[e-into]] but works the other way around. Already scheduled events are added to the given
queue `q` and their metadata data is merged.

Follows arity convention presented in the namespace description.
sourceraw docstring

e-updateclj/s

(e-update ctx f)
(e-update ctx ranks f)
(e-update ctx ranks path f)

Seldom used by the user, often used by other e-XXX functions.

Follows arity convention presented in the namespace description.

Works like standard update but tailored for the current working queue or the event tree.

Returning nil will dissociate whatever is at that location.

Seldom used by the user, often used by other `e-XXX` functions.

Follows arity convention presented in the namespace description.

Works like standard `update` but tailored for the current working queue or the event tree.

Returning nil will dissociate whatever is at that location.
sourceraw docstring

end-flowclj/s

(end-flow ctx)

Is mainly used to end an infinite flow.

Can also be used inside a finite or sampled-finite flow is it needs to end sooner than expected.

When a flow ends, the rest of the queue that was saved when that flow was created will resume. This behavior makes it extremely easy to chain flows and events, simply add them to the same queue.

Is mainly used to end an [[infinite]] flow.

Can also be used inside a [[finite]] or [[sampled-finite]] flow is it needs to end sooner than expected.

When a flow ends, the rest of the queue that was saved when that flow was created will resume. This behavior
makes it extremely easy to chain flows and events, simply add them to the same queue.
sourceraw docstring

engine*clj/s

(engine*)

Used for building rank-based event engines.

Unless one is building something creative and/or evil, one should feel satisfied with either basic-engine or ptime-engine. Someone trully interested will study how ptime-engine is built before attempting to use this function for building a specific engine. Will only be useful for modelling a universe where time flows differently (multidimensional? some sort of time travel?)

Returns map containing:

{::period-start (fn [ctx]
                  "Prepares context for running")
                  
 ::period-end   (fn [ctx]
                  "Does some clean-up in the context")
 ::run          (fn
                  ([ctx]
                   "Pops and runs the next ranked event subtree, returns nil if there are not events")
                  ([ctx events]
                   "Ditto, but uses directly the given events (only useful for some optimizations)"))}

An engine, if it detects that events need to be processed, must call ::period-start. It can then call ::run one or several times, and when all needed events are processed defining some period, the engine must call ::period-end. For instance, ptime-engine considers a single point in time as a period during which events can be further ranked.

Used for building rank-based event engines.

Unless one is building something creative and/or evil, one should feel satisfied with either
[[basic-engine]] or [[ptime-engine]]. Someone trully interested will study how [[ptime-engine]] is
built before attempting to use this function for building a specific engine. Will only be useful
for modelling a universe where time flows differently (multidimensional? some sort of time travel?)

Returns map containing:

```clojure
{::period-start (fn [ctx]
                  "Prepares context for running")
                  
 ::period-end   (fn [ctx]
                  "Does some clean-up in the context")
 ::run          (fn
                  ([ctx]
                   "Pops and runs the next ranked event subtree, returns nil if there are not events")
                  ([ctx events]
                   "Ditto, but uses directly the given events (only useful for some optimizations)"))}
```

An engine, if it detects that events need to be processed, must call ::period-start. It can then call
::run one or several times, and when all needed events are processed defining some period, the engine
must call ::period-end. For instance, [[ptime-engine]] considers a single point in time as a period
during which events can be further ranked.
sourceraw docstring

finiteclj/s

(finite duration flow)
(finite duration flow ctx)

Similar to infinite. However, the flow is meant to last as long as the given duration.

Knowing the duration means end-flow will be called automatically after that interval of time. Also, before each sample, the ptime is linearly normalized to a value between 0 and 1 inclusive. In simpler terms, the value at [::e-flat ::ptime] (also returned by ptime) is the percentage of completion for that flow.

Samples are automatically scheduled at creation for initialization and at the end for clean-up.

Similar to [[infinite]]. However, the flow is meant to last as long as the given `duration`.

Knowing the `duration` means [[end-flow]] will be called automatically after that interval of time. Also,
before each sample, the ptime is linearly normalized to a value between 0 and 1 inclusive. In simpler terms,
the value at `[::e-flat ::ptime]` (also returned by [[ptime]]) is the percentage of completion for that flow.

Samples are automatically scheduled at creation for initialization and at the end for clean-up.
sourceraw docstring

flow-pathclj/s

(flow-path ctx)

Returns the path in the flow tree of the currently executing flow.

When a flow is created, it is added to the flow tree ([::flows] in ctx) using path. When a flow ends, it is removed from the flow tree.

Instead of polluting the global state in the ctx, if a flow needs some state in order to work during its lifetime, this is the perfect place to keep it as it will be removed and garbage collected when the flow ends.

Returns the path in the flow tree of the currently executing flow.

When a flow is created, it is added to the flow tree (`[::flows]` in `ctx`) using [[path]].
When a flow ends, it is removed from the flow tree.

Instead of polluting the global state in the `ctx`, if a flow needs some state in order to
work during its lifetime, this is the perfect place to keep it as it will be removed and
garbage collected when the flow ends.
sourceraw docstring

flowing?clj/s

(flowing? ctx)
(flowing? ctx path)

Is the given ctx or some part of it currently flowing?

Is the given `ctx` or some part of it currently flowing?
sourceraw docstring

historicclj/s

(historic engine)

Given an engine, returns a function ctx -> lazy sequence of each run until all events are executed.

For instance, given a ptime-engine, each element in the sequence will be a view of the ctx at a specific ptime.

Given an engine, returns a function `ctx` -> lazy sequence of each run until all events
are executed.

For instance, given a [[ptime-engine]], each element in the sequence will be a view of
the `ctx` at a specific ptime.
sourceraw docstring

infiniteclj/s

(infinite flow)
(infinite flow ctx)

When using a ptime-engine, a flow represent some continuous phenomenon, unlike an event which is modelled as being instantaneous and having virtually no duration.

A flow is sampled, updated could we say, using a sample event.

An "infinite" flow is either endless or ends at a moment that is not known in advance (eg. when the context satifies some condition not knowing when it will occur). It can be ended using end-flow.

Here is a simple example of an infinite flow that increments a value and schedules samples itself. In other words, that value will be incremented every 500 time units until it is randomly decided to stop. Then, the rest of the queue is resumed (event-a and event-b after a delay of 150 time units).

(dsim/queue (infinite (fn flow [ctx]
                        (let [ctx-2 (update-in ctx
                                               (path ctx)
                                               inc)]
                          (if (< (rand)
                                 0.1)
                            (end-flow ctx-2)
                            (rel-conj ctx-2
                                      (rank+ 500)
                                      sample)))))
            (wq-delay (rank+ 150))
            event-a
            event-b)

Note that when a flow is created, it saves the rest of the working queue and will resume execution when it is done. This designs allows for simply building complex sequences of flows and events, including delays if needed (see wq-delay) and repetitions (see [[capture]]).

When created, a flow is sampled right away for initialization. At each sample, a relative ptime is available under [::e-flat ::ptime]] (returned by ptime), starting with 0 at the ptime of creation.

See also flow-path.

When using a [[ptime-engine]], a flow represent some continuous phenomenon, unlike an event which is
modelled as being instantaneous and having virtually no duration.

A flow is sampled, updated could we say, using a [[sample]] event.

An "infinite" flow is either endless or ends at a moment that is not known in advance (eg. when the context
satifies some condition not knowing when it will occur). It can be ended using [[end-flow]].

Here is a simple example of an infinite flow that increments a value and schedules samples itself. In other
words, that value will be incremented every 500 time units until it is randomly decided to stop. Then, the rest
of the queue is resumed (`event-a` and `event-b` after a delay of 150 time units).

```clojure
(dsim/queue (infinite (fn flow [ctx]
                        (let [ctx-2 (update-in ctx
                                               (path ctx)
                                               inc)]
                          (if (< (rand)
                                 0.1)
                            (end-flow ctx-2)
                            (rel-conj ctx-2
                                      (rank+ 500)
                                      sample)))))
            (wq-delay (rank+ 150))
            event-a
            event-b)
```

Note that when a flow is created, it saves the rest of the working queue and will resume execution when it is done.
This designs allows for simply building complex sequences of flows and events, including delays if needed (see
[[wq-delay]]) and repetitions (see [[capture]]).

When created, a flow is sampled right away for initialization. At each sample, a relative ptime is available
under `[::e-flat ::ptime]]` (returned by [[ptime]]), starting with 0 at the ptime of creation.

See also [[flow-path]].
```
sourceraw docstring

millis->utimeclj/s

(millis->utime millis hz)

Converts an interval in milliseconds to an arbitrary time unit happening hz times per second.

;; Converting milliseconds to frames for an animation.
;; We know something lasts 2000 milliseconds and the frame-rate is 60 times per second.
;; Hence, it lasts 120 frames.

(= (millis->utime 2000
                  60)
   120)
Converts an interval in milliseconds to an arbitrary time unit happening `hz` times per second.

```clojure
;; Converting milliseconds to frames for an animation.
;; We know something lasts 2000 milliseconds and the frame-rate is 60 times per second.
;; Hence, it lasts 120 frames.

(= (millis->utime 2000
                  60)
   120)
```
sourceraw docstring

minmax-normclj/s

(minmax-norm min-v interval v)

Min-max normalization, linearly scales x to fit between 0 and 1 inclusive.

See scale(arity 3), which is the opposite operation.

(min-max-norm 20
              10
              25)

0.5
Min-max normalization, linearly scales `x` to fit between 0 and 1 inclusive.

See [[scale]](arity 3), which is the opposite operation.

```clojure
(min-max-norm 20
              10
              25)

0.5
```
sourceraw docstring

mirrorclj/s

(mirror f)
(mirror f ctx)

Many discrete events and flows are typically interested in two things: the path they work on and the current ptime (ie. the first rank in their ranks, using a ptime-engine).

Turns f into a regular event which accepts a ctx. Underneath, calls (f ctx data-at-path current-ptime). The result is automatically associated in the ctx at the same path.

Notably useful for finite and sampled-finite, and many regular events for that matter.

Many discrete events and flows are typically interested in two things: the path they work on and the current
ptime (ie. the first rank in their ranks, using a [[ptime-engine]]).

Turns `f` into a regular event which accepts a `ctx`. Underneath, calls `(f ctx data-at-path current-ptime)`.
The result is automatically associated in the `ctx` at the same path.

Notably useful for [[finite]] and [[sampled-finite]], and many regular events for that matter.
sourceraw docstring

next-ptimeclj/s

(next-ptime ctx)

On what ptime is scheduled the next event?

Returns nil if there is none.

On what ptime is scheduled the next event?

Returns nil if there is none.
sourceraw docstring

pathclj/s

(path ctx)

Returns the path of the currently executing flat event (ie. under [::e-flat ::path]).

Returns the path of the currently executing flat event (ie. under `[::e-flat ::path]`).
sourceraw docstring

pred-repeatclj/s

(pred-repeat _ctx n)

Example of a predicate meant to be used with wq-sreplay.

The seed provided to wq-sreplay, corresponding here to n, is the number of times a captured queue will be repeated. For instance, 2 means 3 occurences: the captured queue is first executed, then repeated twice.

See wq-capture for an example.

Example of a predicate meant to be used with [[wq-sreplay]].

The seed provided to [[wq-sreplay]], corresponding here to `n`, is the number of times a captured queue
will be repeated. For instance, 2 means 3 occurences: the captured queue is first executed, then repeated
twice.

See [[wq-capture]] for an example.
sourceraw docstring

ptimeclj/s

(ptime ctx)

Returns either the ptime of the currently executing flat event (ie. under [::e-flat ::ptime]) or the global ptime in the ctx (ie. under [::ptime]).

Returns either the ptime at [::e-flat ::ptime] (notably useful for finite or sampled-finite or, if there is none, at [::ptime].

Returns either the `ptime` of the currently executing flat event (ie. under `[::e-flat ::ptime]`) or
 the global `ptime` in the `ctx` (ie. under `[::ptime]`).

Returns either the ptime at `[::e-flat ::ptime]` (notably useful for [[finite]] or [[sampled-finite]]
 or, if there is none, at [::ptime].
sourceraw docstring

ptime-engineclj/s

(ptime-engine)
(ptime-engine options)

Like basic-engine, but treats the first rank of events as a ptime (point in time).

It is essentially a discrete-event simulation engine but serving a whole variety of other purposes as described in the README.

At each run, it executes all events for the next ptime while ensuring that time move forwards. An event can schedule other events in the future or, at the earliest, for the same ptime. Throws at execution if time misbehaves.

Current ptime is associated in the context at ::ptime (see also ptime).

options is a nilable map containing:

kv
::beforeFunction ctx -> ctx called right before the first event of the next ptime
::afterFunction ctx -> ctx called after executing all events of a ptime.

If a ctx does not have any event, a run returns nil.

Like [[basic-engine]], but treats the first rank of events as a ptime (point in time).

It is essentially a discrete-event simulation engine but serving a whole variety of other
purposes as described in the README.

At each run, it executes all events for the next ptime while ensuring that time move forwards.
An event can schedule other events in the future or, at the earliest, for the same ptime. Throws
at execution if time misbehaves.

Current ptime is associated in the context at `::ptime` (see also [[ptime]]).

`options` is a nilable map containing:

| k | v |
|---|---|
| ::before | Function ctx -> ctx called right before the first event of the next ptime |
| ::after | Function ctx -> ctx called after executing all events of a ptime. |

If a ctx does not have any event, a run returns nil.
sourceraw docstring

queueclj/s

(queue)
(queue & values)

Clojure has persistent queues but no straightforward way to create them.

Here is one.

Clojure has persistent queues but no straightforward way to create them.

Here is one.
sourceraw docstring

queue?clj/s

(queue? x)

Is x a persistent queue?

See also queue.

Is `x` a persistent queue?

See also [[queue]].
sourceraw docstring

rank+clj/s

(rank+ +rank)
(rank+ n-rank +rank)
(rank+ n-rank +rank ctx)

Like ranks+ but optimized for summing only the rank at position n-rank (defaulting to 0, the first one).

Commonly used in the context of a ptime-engine where most of the time we only care about ptime (ie. the first rank).

See ranks+ for rationale.

(= [42]
   (rank+ {::e-flat {::ranks [30]}}
          12))
Like [[ranks+]] but optimized for summing only the rank at position `n-rank` (defaulting
to 0, the first one).

Commonly used in the context of a [[ptime-engine]] where most of the time we only care about
ptime (ie. the first rank).

See [[ranks+]] for rationale.

```clojure
(= [42]
   (rank+ {::e-flat {::ranks [30]}}
          12))
```
sourceraw docstring

ranksclj/s

(ranks ctx)

Returns the ranks of the currently executing flat event (ie. under [::e-flat ::ranks]).

Returns the ranks of the currently executing flat event (ie. under `[::e-flat ::ranks]`).
sourceraw docstring

ranks+clj/s

(ranks+ +ranks)
(ranks+ +ranks ctx)

Returns the ranks of the currently executing flat event summed with the given ones.

Not providing ctx returns a partially applied version.

Some functions such as rel-conj or wq-delay take one as argument for scheduling something in the future at the same path that the currently executing flat event. Using rank+ or ranks+ comes in handy.

Its sibling, singular rank+, is optimized for summing only one rank.

(= [10 15 3]
   (ranks+ {::e-flat {::ranks [5 5]}}
           [5 10 3]))

Returns the ranks of the currently executing flat event summed with the given ones.

Not providing `ctx` returns a partially applied version.

Some functions such as [[rel-conj]] or [[wq-delay]] take one as argument for scheduling
something in the future at the same path that the currently executing flat event. Using [[rank+]]
or [[ranks+]] comes in handy.

Its sibling, singular [[rank+]], is optimized for summing only one rank.

```clojure
(= [10 15 3]
   (ranks+ {::e-flat {::ranks [5 5]}}
           [5 10 3]))

```
sourceraw docstring

reached?clj/s

(reached? ctx ptime-target)

Uses ptime to tell if a certain ptime has been reached.

Uses [[ptime]] to tell if a certain ptime has been reached.
sourceraw docstring

rel-conjclj/s

(rel-conj ctx ctx->ranks event)

Adds event in the event tree at the same path as the currently executing flat event, at some future ranks.

Typically used for scheduling something in the future related to the current flat event.

See ranks+ for understaning ctx->ranks. If it returns nil, nothing is scheduled.

Adds `event` in the event tree at the same path as the currently executing flat event, at some future ranks.

Typically used for scheduling something in the future related to the current flat event.

See [[ranks+]] for understaning `ctx->ranks`. If it returns nil, nothing is scheduled.
sourceraw docstring

sampleclj/s

(sample)
(sample ctx)
(sample ctx ctx->ranks)

When using a ptime-engine, samples the flow associated with the current path.

Sampling is deduplicated on a per-ptime basis. For a given ptime, it is garanteed a flow will be sampled once and only once.

This is especially important considering that a sample event can be scheduled for anywhere in the flow tree. For instance, when drawing a frame in an animation, it is way simpler to sample everything at once, scheduling a sample event at the root (without any path) rather than scheduling manually every single element that needs to be animated.

Hence, a flow can be sampled at different rates by different interested parties without worrying about non-idempotency.

See sampler.

When using a [[ptime-engine]], samples the flow associated with the current [[path]].

Sampling is deduplicated on a per-ptime basis. For a given ptime, it is garanteed a flow will be sampled
once and only once.

This is especially important considering that a sample event can be scheduled for anywhere in the flow tree.
For instance, when drawing a frame in an animation, it is way simpler to sample everything at once, scheduling
a sample event at the root (without any path) rather than scheduling manually every single element that
needs to be animated.

Hence, a flow can be sampled at different rates by different interested parties without worrying about
non-idempotency.

See [[sampler]].
sourceraw docstring

sampled-finiteclj/s

(sampled-finite ctx->ranks duration flow)
(sampled-finite ctx->ranks duration flow ctx)

Just like finite but eases the process of repeatedly sampling the flow.

After each sample, starting at initialization, schedules another one using ctx->ranks (see the commonly used rank+ and ranks+), maxing out the ptime at the ptime of completion so that the forseen interval will not be exceeded.

Just like [[finite]] but eases the process of repeatedly sampling the flow.

After each sample, starting at initialization, schedules another one using `ctx->ranks` (see the commonly
used [[rank+]] and [[ranks+]]), maxing out the ptime at the ptime of completion so that the forseen interval will
not be exceeded.
sourceraw docstring

samplerclj/s

(sampler ctx->ranks)
(sampler ctx->ranks ctx)

A sampler event schedules a sample at future ranks computed by 'ctx->ranks'. It will continue to do so until there is nothing flowing anymore for that path or 'ctx->ranks' returns nil.

It is commonly used for sampling repeatedly a subtree of flows rather than a specific flow. For instance, one could use a sampler for drawing every frame of an animation. Supposing a single ptime represents one millisecond and we draw at 60 frames per second:

(e-conj ctx
        [0 1000000]
        nil
        (sampler (rank+ (/ 1000
                           60))))

Two things are interesting. First, besides scheduling for ptime 0, the sampler is scheduled for a secondary rank of 1000000, meaning all futures samples it performs, being rescheduled with that same secondary rank, will have a very low priority. Second, we did not provide a path, meaning we want sampling to occur for the whole flow tree (ie. all existing flows).

Sometimes, specific flow samples are ordered using further ranks beyond the ptime. Had we scheduled that sampler without that secondary rank, all future samples would run with the highest priority within ptimes, sampling the whole tree at once, thus disrupting samples that were already ordered for those ptimes in a more specific order.

Ensuring that this sampler executes last garantees ordering of all sample events. Remember that samples are deduplicated, meaning that when a sample ordered by the sampler executes, it will execute only flows that have not been sampled yet.

A [[sampler]] event schedules a [[sample]] at future ranks computed by 'ctx->ranks'. It will
continue to do so until there is nothing flowing anymore for that [[path]] or 'ctx->ranks' returns nil.

It is commonly used for sampling repeatedly a subtree of flows rather than a specific flow. For
instance, one could use a sampler for drawing every frame of an animation. Supposing a single ptime
represents one millisecond and we draw at 60 frames per second:

```clojure
(e-conj ctx
        [0 1000000]
        nil
        (sampler (rank+ (/ 1000
                           60))))
```

Two things are interesting. First, besides scheduling for ptime 0, the sampler is scheduled for a
secondary rank of 1000000, meaning all futures samples it performs, being rescheduled with that
same secondary rank, will have a very low priority. Second, we did not provide a path, meaning we want
sampling to occur for the whole flow tree (ie. all existing flows).

Sometimes, specific flow samples are ordered using further ranks beyond the ptime. Had we scheduled that
sampler without that secondary rank, all future samples would run with the highest priority within ptimes,
sampling the whole tree at once, thus disrupting samples that were already ordered for those ptimes in
a more specific order.

Ensuring that this sampler executes last garantees ordering of all sample events. Remember that
samples are deduplicated, meaning that when a sample ordered by the sampler executes, it will execute
only flows that have not been sampled yet.
sourceraw docstring

scaleclj/s

(scale min-v interval percent)
(scale scaled-min-v scaled-interval min-v interval v)

Linear scaling of numerical values.

ArityMeans
3Scales a percent value to be between min-v and (+ min-v interval) inclusive. &
5Scales v, between min-v and (+ min-v interval), to be between scaled-minv and (+ scaled-min-v scaled-interval) inclusive.
(scale 200
       100
       0.5)

250


(scale 200
       100
       2000
       1000
       2500)

250
Linear scaling of numerical values.

| Arity | Means |
|---|---|
| 3 | Scales a `percent` value to be between `min-v` and (+ `min-v` `interval`) inclusive. &
| 5 | Scales `v`, between `min-v` and (+ `min-v` `interval`), to be between `scaled-min`v and (+ `scaled-min-v` `scaled-interval`) inclusive. |

```clojure
(scale 200
       100
       0.5)

250


(scale 200
       100
       2000
       1000
       2500)

250
```
sourceraw docstring

scheduled?clj/s

(scheduled? ctx)
(scheduled? ctx ranks)

Is there anything scheduled at all or for the given ranks?

Is there anything scheduled at all or for the given `ranks`?
sourceraw docstring

serializableclj/s

It can be particularly useful being able to serialize a ctx in order to save if to a file or sending it over the wire (saving the whole state of a game, saving long running simulations, sharing them, etc).

However, how could one serialize all those event functions? The answer to that problem is an external library called dvlopt/fdat. The following functions of this API are indeed serializable using dvlopt/fdat:

  • finite
  • infinite
  • mirror
  • pred-repeat
  • rank+
  • ranks+
  • sample
  • sampled-finite
  • sampler
  • stop
  • wq-capture
  • wq-delay
  • wq-do!
  • wq-exec
  • wq-replay
  • wq-sreplay

https://github.com/dvlopt/fdat.cljc

It can be particularly useful being able to serialize a `ctx` in order to save if to a file or sending
it over the wire (saving the whole state of a game, saving long running simulations, sharing them, etc).

However, how could one serialize all those event functions? The answer to that problem is an external library
called `dvlopt/fdat`. The following functions of this API are indeed serializable using `dvlopt/fdat`:

- finite
- infinite
- mirror
- pred-repeat
- rank+
- ranks+
- sample
- sampled-finite
- sampler
- stop
- wq-capture
- wq-delay
- wq-do!
- wq-exec
- wq-replay
- wq-sreplay

[https://github.com/dvlopt/fdat.cljc](https://github.com/dvlopt/fdat.cljc)
sourceraw docstring

stopclj/s

(stop)
(stop ctx)

Removes anything that is currently being executed (if any), all events and all flows, meaning there is nothing left to run.

Removes anything that is currently being executed (if any), all events and all flows,
meaning there is nothing left to run.
sourceraw docstring

wq-captureclj/s

(wq-capture)
(wq-capture ctx)

Captures and saves the rest of the working queue. Next call to wq-replay or wq-sreplay will replay or clean that captured queue.

This is extremely useful for repeating queues or portion of queues. Without this abilty to capture the current state of a queue, it would be tricky to model activities or successions of flows that need some repetition.

When called more than once, repetitions are nested. For instance:

(queue wq-capture
       event-a
       wq-capture
       event-b
       (wq-delay (rank+ 100))
       (wq-sreplay pred-repeat
                   1)
       event-c
       (wq-replay pred-repeat
                  1))

;; Equivalent to:

(queue event-a
       event-b
       (wq-delay (rank+ 100))
       event-b
       event-c
       event-a
       event-b
       (wq-delay (rank+ 100))
       event-b
       event-c)
Captures and saves the rest of the working queue. Next call to [[wq-replay]] or [[wq-sreplay]]
will replay or clean that captured queue.

This is extremely useful for repeating queues or portion of queues. Without this abilty to capture
the current state of a queue, it would be tricky to model activities or successions of flows that need
some repetition.

When called more than once, repetitions are nested. For instance:

```clojure
(queue wq-capture
       event-a
       wq-capture
       event-b
       (wq-delay (rank+ 100))
       (wq-sreplay pred-repeat
                   1)
       event-c
       (wq-replay pred-repeat
                  1))

;; Equivalent to:

(queue event-a
       event-b
       (wq-delay (rank+ 100))
       event-b
       event-c
       event-a
       event-b
       (wq-delay (rank+ 100))
       event-b
       event-c)
```
sourceraw docstring

wq-delayclj/s

(wq-delay ctx->ranks)
(wq-delay ctx->ranks ctx)

Moves the rest of the working queue to the computed ranks in the event tree.

For instance, inducing a 500 time units delay between 2 events:

(queue event-a
       (wq-delay (rank+ 500))
       event-b)

Particularly useful for modelling activities (sequences of events dispatched in time, using a ptime-engine). Knowing that several events logically bound together at the same path have to be scheduled at different ptimes, one approach would be to schedule all of them in one go, eargerly. However, that could quickly lead to the event tree becoming extremely big. More importantly, if an earlier event fails (eg. event-a), future ones (eg. event-b) are already scheduled and will execute.

By using wq-delay, both problems are solved. All events are part of the same queue, which makes sense, and delays reschedule the rest of the queue when needed. An event failing means the queue fails, so the activity stops.

An example of an activity, a customer in a bank, assuming some sort of random delays being provided:

(queue customer-arrives
       (wq-delay ...)
       customer-handled
       (wq-delay ...)
       customer-leaves)

Unless something more sophisticated is needed, ctx->ranks will often be the result of rank+ or ranks+. If ctx->ranks returns nil, no delay is incurred.

Moves the rest of the working queue to the computed ranks in the event tree.

For instance, inducing a 500 time units delay between 2 events:

```clojure
(queue event-a
       (wq-delay (rank+ 500))
       event-b)
```

Particularly useful for modelling activities (sequences of events dispatched in time, using a [[ptime-engine]]).
Knowing that several events logically bound together at the same path have to be scheduled at different ptimes, one
approach would be to schedule all of them in one go, eargerly. However, that could quickly lead to the event tree
becoming extremely big. More importantly, if an earlier event fails (eg. `event-a`), future ones (eg. `event-b`) are
already scheduled and will execute.

By using [[wq-delay]], both problems are solved. All events are part of the same queue, which makes sense, and
delays reschedule the rest of the queue when needed. An event failing means the queue fails, so the activity stops.

An example of an activity, a customer in a bank, assuming some sort of random delays being provided:

```
(queue customer-arrives
       (wq-delay ...)
       customer-handled
       (wq-delay ...)
       customer-leaves)
``` 

Unless something more sophisticated is needed, `ctx->ranks` will often be the result of [[rank+]] or
[[ranks+]]. If `ctx->ranks` returns nil, no delay is incurred.
sourceraw docstring

wq-dissocclj/s

(wq-dissoc ctx)

Removes the current working queue, stopping effectively its execution.

Removes the current working queue, stopping effectively its execution.
sourceraw docstring

wq-do!clj/s

(wq-do! side-effect)
(wq-do! side-effect ctx)

Calls side-effect with the ctx to do some side effect. Ignores the result and simply returns the unmodified ctx.

Calls `side-effect` with the `ctx` to do some side effect. Ignores the result and simply
returns the unmodified `ctx`.
sourceraw docstring

wq-execclj/s

(wq-exec q)
(wq-exec q ctx)

Executes the given event queue q in isolation from the rest of the current working queue.

See also e-isolate.

Executes the given event queue `q` in isolation from the rest of the current working queue.

See also [[e-isolate]].
sourceraw docstring

wq-metaclj/s

(wq-meta ctx)

Returns the metadata of the current working queue.

See also wq-vary-meta.

Returns the metadata of the current working queue.

See also [[wq-vary-meta]].
sourceraw docstring

wq-replayclj/s

(wq-replay pred?)
(wq-replay pred? ctx)

When pred? returns true after being called with the current ctx, replays the last queue captured by wq-capture.

When it returns a falsy value, that last captured queue is removed and the rest of the current working queue is executed.

When `pred?` returns true after being called with the current `ctx`, replays the last queue captured by 
[[wq-capture]].

When it returns a falsy value, that last captured queue is removed and the rest of the current working
queue is executed.
sourceraw docstring

wq-sreplayclj/s

(wq-sreplay pred seed)
(wq-sreplay pred seed ctx)

Similar to wq-replay but pred is stateful. It is called with the ctx and (initially) the seed. Returning anything but nil is considered as truthy and is stored as state replacing seed in the next call.

See [[wq-captured]] for an example with pred-repeat.

Similar to [[wq-replay]] but `pred` is stateful. It is called with the `ctx` and (initially) the `seed`.
Returning anything but nil is considered as truthy and is stored as state replacing `seed` in the next call.

See [[wq-captured]] for an example with [[pred-repeat]].
sourceraw docstring

wq-vary-metaclj/s

(wq-vary-meta ctx f & args)

Uses Clojure's vary-meta on the working queue.

When that queue is copied or moved into the future (eg. by calling wq-delay), it is a convenient way of storing some state at the level of a queue which can later be retrieved using wq-meta. When a queue is garbage-collected, so is its metadata.

Uses Clojure's `vary-meta` on the working queue.

When that queue is copied or moved into the future (eg. by calling [[wq-delay]]), it is a convenient way of storing
some state at the level of a queue which can later be retrieved using [[wq-meta]]. When a queue is garbage-collected,
so is its metadata.
sourceraw docstring

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close