Transducers
Transducers are composable transformations of reducing functions. They provide a way to implement high-order operations such as map
, filter
, take
or drop
in a way that they are independent of the collection they operate on. This way, these operations are defined only once, for all collections in Yona, specifically for Seq
, Set
and Dict
and in fact, they can be used for custom user-built data collections, provided that it exposes a reduce
function.
Transducer constructor is a function that takes a transducer as an argument and returns a new transducer.
Using a transducer¶
Transducer needs to be used in a combination with reduce
function, best seen in an example, a sequence can be filtered like this:
let
transducer = Transducers::filter \val -> val < 0 (0, \acc val -> acc + val, \acc -> acc * 2)
in
Seq::reducer [-2,-1,0,1,2] transducer
What this code does, is that it calls function Seq::reducer
with two arguments:
- sequence to reduce
- transducer
And the transducer is constructed by function Transducers::filter
, which takes two arguments:
- predicate - function to filter elements added to the resulting collection
- transducer
The second argument here is another transducer actually. This is how transducers are composed. Transducer can either be created by using a predefined one in the Transducers
module, or created manually as a tripple, as described in the next section.
Implementing a transducer¶
Transducer in Yona is a tripple, with following elements:
- initial state - is the initial state of the accumulator of the step function
- step function - is a function of two arguments - accumulator and an element, returning a new state of the accumulator
- complete function - is a function of one argument - the final state of the accumulator, returning the final value of the
reduce
function
Example: filter
transducer¶
# pred: function of one argument (element) returning boolean value
# init: initial state
# step: function of two arguments (accumulator, element) returning new value of the accumulator
# complete: function of one argument (final state of accumulator) returning final return value
filter pred (init, step, complete) = let
new_step = \acc val -> if pred val then step acc val else acc
in
(init, new_step, complete)
Source code for all transducers available in Yona is available here.
Note that transducers are actually used in generators as well, they are just a syntax sugar for them for the built-in collections.