terse Raku `transduce`

Run Settings
LanguageRaku
Language Version
Run Command
sub transduce ($stream, |transducers ) { my ($stream-iterator, $input); # Step through specified transducers: gather transducer: for transducers -> $transducer { # Start pulling from $stream. # Code written here inside the `for transducers` iteration for right scoping of the `last` in &pull-one. # Next line is called once when `transduce` sub execution begins, BEFORE `for transducers` loop begins. FIRST { $stream-iterator = $stream .iterator; $input = pull-one } # `last` out of the `for transducers` iteration above if stream's IterationEnd reached: sub pull-one { my $element := $stream-iterator .pull-one; last if $element =:= IterationEnd; $element } my role Keep {} # Extract or construct transducer (consumer => producer pair) given each transducer's rule type. # This transducer `given`/`when` must be in sync with the consumer & producer ones further down. my ($consumer, $producer) = do given $transducer { # eg transducer rule: does this transduction: when Array[Code] { .[0], Keep } # `[* %% 2]` Keeps while number is even when [] { Keep, Keep } # `[]` Keeps entire rest of stream when Pair { .key[0], .value[0] } # `[] => Nil` Skips entire rest of stream # `10 => Nil` Skips 10 elements of stream # `[*.Int] => [++*]` Adds 1 to input while Int default { .[0], Keep } # `* %% 2` Keeps until number not even # `10` Keeps 10 elements of stream } # Step through stream: loop { # All consumers except Keep (`[]`) have a test. If test fails, time for next transducer: given $consumer { when Code { next transducer unless .($input) } when Int { next transducer unless $consumer-- } } # A Keep producer always outputs (takes) the input (aka keep). # A `Nil` producer always outputs nothing (aka skip). # A code producer that returns an undefined value when run outputs nothing (aka conditional skip). # A code producer that returns a defined value outputs that value. # Any other producer value outputs the producer as the value. given $producer { when Keep { take $input } # If no explicit producer (or `[]` CONSUMER) then Keep when Any:U { } # `=> Nil` producer means take nothing (aka skip it) when Code { .($input) andthen .take if *.defined } # $producer($input) is taken unless result is Empty default { .take } # If none of the above, take $producer as is as value } $input = pull-one } } } say transduce ^20, 3 => 'strings', [* < 6] => Nil, [* < 10] => [++*], [* %% 5] => 'divisible by 5', [] => -1;
castle cattle acetal acetol ctttld aaaaab aaaabb aabbbb abbbbb
Editor Settings
Theme
Key bindings
Full width
Lines