for-looprakuflip-flop

How to use the raku operator 'ff'or 'fff' in a 'for lines()' loop


Given the input file:

----------------
A
----------------
information for A
on these lines
----------------
B
----------------
Something about B
on these lines
etc

I want to produce:

A: information for A
A: on these lines
B: Something about B
B: on these lines
B: etc

My attempt to use Raku to do this looks like:

#!/usr/bin/env raku

my $head-info;

for lines() -> $line {
    given $line {
#        when /^ '-' **16 $/ { }   # skip dashed lines
        when /^ '-' **16 $/ ^fff^ /^ '-' ** 16 $ / {
           $head-info = $line;
           say "set head-info $head-info";
        }
        default { say $head-info, ": ", $line; }
    }
}

I tried some variations of this but never seem to be able to execute the block that sets $head-info. Uncommenting the line does skip the dashed lines. I don't necessarily need to use ff or fff but I thought it would be appropriate here.


Solution

  • I tried some variations of this but never seem to be able to execute the block that sets $head-info

    I think both when and the ff family doing $_ ~~ operations is resulting in the undesired output by messing up with $_ somehow. So to bypass this, we can either do when so ... or use plain if. I choose the latter to get:

    my $head-info;
    
    for lines() -> $line {
        $_ := $line;
    
        if /^ "-"+ $/ ^fff^ /^ "-"+ $/ {
            $head-info = $line;
        }
        elsif !/^ "-"+ $/ {
            say "$head-info: $line";
        }
    }
    

    where I now manually bind $_ to the line at hand for ^fff^. So the code now says

    Note that all-"-" lines satisfy neither of these, so they are silently skipped in the loop.


    Extra: the part

    for lines() -> $line {
        $_ := $line;
    

    is slightly annoying to do manually, there's a third-party library that introduces the forgiven keyword that combines the for loop and a given statement and does that binding on $_ behind the scenes, so one can do:

    use Slang::Forgiven;
    
    my $head-info;
    
    forgiven lines() -> $line {
        if /^ "-"+ $/ ^fff^ /^ "-"+ $/ {
            $head-info = $line;
        }
        elsif !/^ "-"+ $/ {
            say "$head-info: $line";
        }
    }
    

    to get the same result.

    Disclaimer: author.