Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the _intended_ value of &?ROUTINE?

The Rakudo implementation of Raku tracks multiple issues about the (very useful!) &?ROUTINE variable not providing the correct value (e.g., #1768 and 2362), so I realize that it's not behaving quite correctly. But I'm trying to understand what it's intended behavior is – which seems like an essential first step in fixing that behavior.

Running this code with Rakudo v2021.06 produces the output noted in the comments. Which parts of this output are correct, and which represent bugs?

sub foo  {
    note '## ifs:';
    do if True { say &?ROUTINE.name }                # OUTPUT: «foo»
    if True    { say &?ROUTINE.name }                # OUTPUT: «<unit>»

    note '## ifs w/ topic:';
    do if True -> $a { say $a; say &?ROUTINE.name }  # OUTPUT: «True», # OUTPUT«""»
    if True -> $a    { say $a; say &?ROUTINE.name }  # OUTPUT: «True», # OUTPUT«foo»
    
    note '## fors:';
    for 1 { say &?ROUTINE.name }                     # OUTPUT: «foo»
    say &?ROUTINE.name for 1;                        # OUTPUT: «""»

    note '## methods:';
    42.&{              say &?ROUTINE.name }          # OUTPUT: «foo»
    my method m($a:) { say &?ROUTINE.name }
    42.&m;                                           # OUTPUT: «m»
}
foo 

The relevant docs say that &?ROUTINE returns "an instance of Sub", which makes it sound like all of the above should be 'foo'. On the other hand, a Method is a Routine, so I'm somewhat inclined to think that the last two (an anonymous method and a named method) should not be 'foo'. I'm also unsure whether all the '' and "" values represent bugs, or if there's a principle at work that makes some (or all?) of those intended behavior.

(I also tested the above code with the use soft pragma to make sure that inlining wasn't having an effect that I could fix with that pragma; it had no effect on the output)

like image 950
codesections Avatar asked Jul 08 '21 21:07

codesections


2 Answers

The &?ROUTINE symbol should evaluate to an object representing the nearest lexically enclosing routine - that is, the nearest enclosing declaration of type Routine. This includes both Sub and Method. Furthermore, given these are all in principle closures, it should evaluate to the correct closure clone of the routine.

Thus a correct implementation would produce:

sub foo  {
    note '## ifs:';
    do if True { say &?ROUTINE.name }                # OUTPUT: «foo»
    if True    { say &?ROUTINE.name }                # OUTPUT: «foo»

    note '## ifs w/ topic:';
    do if True -> $a { say $a; say &?ROUTINE.name }  # OUTPUT: «True», # OUTPUT«foo»
    if True -> $a    { say $a; say &?ROUTINE.name }  # OUTPUT: «True», # OUTPUT«foo»
    
    note '## fors:';
    for 1 { say &?ROUTINE.name }                     # OUTPUT: «foo»
    say &?ROUTINE.name for 1;                        # OUTPUT: «foo»

    note '## methods:';
    42.&{              say &?ROUTINE.name }          # OUTPUT: «foo»
    my method m($a:) { say &?ROUTINE.name }
    42.&m;                                           # OUTPUT: «m»
}
foo 

Current Rakudo is thus getting this wrong in a number of cases. Despite having worked extensively on the compiler, I don't have a good guess what it's doing here; I do know that I won't be copying the current implementation when I get to adding &?ROUTINE support in the new compiler frontend that I'm working on!

like image 190
Jonathan Worthington Avatar answered Oct 23 '22 16:10

Jonathan Worthington


Per @Larry's spec[1]:

&?ROUTINE is always an alias for the lexically innermost Routine (which may be a Sub, Method, or Submethod) ...

You can get the current routine name by calling &?ROUTINE.name. Outside of any [routine] declaration, this call returns failure.

Note that &?ROUTINE refers to the current single [routine], even if it is declared multi. To redispatch to the entire suite under a given short name, just use the named form to call the proto, since there are no anonymous multis.

Footnotes

[1] "@Larry" is/was historical shorthand for the evolving de facto Raku design team. "spec" is/was historical shorthand for the evolving design. The above quotes are from S06 section The &?ROUTINE object

like image 36
raiph Avatar answered Oct 23 '22 16:10

raiph