Search code examples
expressionrakudo-notationrakudo

Does the `do` keyword run a block or treat it as an expression?


The docs state that "The simplest way to run a block where it cannot be a stand-alone statement is by writing do before it" and provide the following example:

# This dies half of the time 
do { say "Heads I win, tails I die."; Bool.pick } or die; say "I win.";

However, do doesn't seem to cause all blocks to run. In particular, it doesn't seem to run blocks with a signature:

do -> $a = 42 { say "ran with $a"; 0 } or die; say 'done'; # OUTPUT: «done»

So would it be better to say that do treats a block as an expression which sometimes causes it to be run? Or is Rakudo incorrect in its behavior here? Or is my understanding incorrect?


Solution

  • Afaik:

    • Like all "statement prefixes", do consumes a "blorst" (block or statement) on its right and treats it as a statement.

    • do's only special power is that it evaluates to the value of the (last) statement. I think this is the only sense in which there's any sense of "expression" in its operation.

    This interacts with the following behaviors, which are unrelated to do:

    • When a "bare" block ({...}) is treated as a statement, it runs the block.

    • Other blocks, treated as a statement, don't (or shouldn't), run.

    I think the fix to the doc sentence is something like:

    The simplest way to run a bare block where it cannot be is not behaving as a stand-alone statement is by writing do before it"

    Though I don't know where/if the doc talks about the difference between bare blocks and other blocks.