[![Build Status](https://travis-ci.com/Kaiepi/p6-Supply-Folds.svg?branch=master)](https://travis-ci.com/Kaiepi/p6-Supply-Folds) NAME ==== Supply::Folds - Alternative fold methods for Supply SYNOPSIS ======== ```perl6 # Let's say we want to parse payloads from a TCP connection: my Supply:D $connection = supply { emit 'fo'; emit 'obarb'; emit 'azf'; emit 'ooba'; emit 'rbazfooba'; emit 'rbaz'; done; }; # It's not guaranteed that these payloads will be complete messages, so our # parser needs to keep context for where it is in the stream of payloads... grammar Connection::Grammar { token TOP { ( foo | bar | baz )+ } } class Connection::Actions { method TOP($/) { make $0ยป.Str } } # ...but this is a problem! We don't want locks slowing down communication with # our peer, but we need to hold on to our parser as we parse each payload # received! Psych, this isn't a problem with Supply.scan: react whenever $connection.scan: &parse-payload, Connection::Grammar { .made.say; # OUTPUT: # Nil # [foo bar] # [baz] # [foo] # [bar baz foo] # [bar baz] } proto sub parse-payload(Connection::Grammar:_, Str:D --> Connection::Grammar:D) {*} multi sub parse-payload(Connection::Grammar:U $acc, Str:D $payload --> Connection::Grammar:D) { $acc.subparse: $payload, actions => Connection::Actions.new; } multi sub parse-payload(Connection::Grammar:D $acc, Str:D $payload --> Connection::Grammar:D) { $acc.subparse: $acc.orig.substr(max $acc.pos, 0) ~ $payload, actions => $acc.actions } ``` DESCRIPTION =========== Supply::Folds is a library that provides the `Supply.fold` and `Supply.scan` methods, which can be used as an alternative to `Supply.reduce` and `Supply.produce`. The main advantage these methods have over those is that they may optionally take an initial value to begin a fold/scan with, rather than only working using values emitted by the supply. METHODS ======= method fold ----------- ```perl6 method fold(::?CLASS:D: &folder is raw --> ::?CLASS:D) ``` Alias for `Supply.reduce`. ```perl6 method fold(::?CLASS:D: &folder is raw, $init is raw --> ::?CLASS:D) ``` Using `$init` as the initial result of the fold, for each value emitted from `self`, call `&folder` with the previous result and the value emitted, setting the result to the return value. This will be emitted once the supply is done. method scan ----------- ```perl6 method scan(::?CLASS:D: &scanner is raw --> ::?CLASS:D) ``` Alias for `Supply.produce`. ```perl6 method scan(::?CLASS:D: &scanner is raw, $init is raw, Bool:D :$keep = False --> ::?CLASS:D) ``` Using `$init` as the initial result of the scan, for each value emitted from `self`, call `&scanner` with the previous result and the value emitted, setting the result to the return value and emitting it. If `$keep` is set to `True`, `$init` will be emitted before the scan starts. AUTHOR ====== Ben Davies (Kaiepi) COPYRIGHT AND LICENSE ===================== Copyright 2020 Ben Davies This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.