Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LAST phaser doesn't fire with return #5542

Open
alabamenhu opened this issue Mar 29, 2024 · 4 comments
Open

LAST phaser doesn't fire with return #5542

alabamenhu opened this issue Mar 29, 2024 · 4 comments
Labels

Comments

@alabamenhu
Copy link
Contributor

The Problem

Here's the code that has issues with proper calling of LAST.

sub foo ($x) { 
    ENTER say "entered"; 
    LEAVE say "left"; 
    for ^$x { 
        FIRST say "first"; 
        LAST say "last"; 
        return if $_ == 0; 
    }
}
foo 42

Expected Behavior

The output should read in order, entered, first, last, left

Actual Behavior

The output reads in order, entered, first, left.

lizmat added a commit that referenced this issue Mar 29, 2024
- fix error if a block had both a LEAVE and LAST phaser: found this
  will investigating #5542
- increment counters only when needed
- only check once for number of exceptions
@lizmat
Copy link
Contributor

lizmat commented Mar 29, 2024

For the record, it is documented to work: https://docs.raku.org/language/phasers#LAST

lizmat added a commit to Raku/doc that referenced this issue Mar 29, 2024
@lizmat
Copy link
Contributor

lizmat commented Mar 29, 2024

Apart from the fact that you could argue that the LAST phaser should only be fired after the last iteration, it turns out to be very hard to implement this feature.

At a technical level, it's because the nqp::handle that handles the body of the loop, is not able to catch the return control message, unless it's within the lexical scope of the body.

So:

$ raku -e 'use nqp; sub a($a) { nqp::handle({return $a}(), "RETURN", nqp::stmts((say "caught return"), (return $a))) }; dd a 42'           
caught return
42

works, but

$ raku -e 'use nqp; my $b := { return 42 }; sub a($a) { nqp::handle($b(), "RETURN", nqp::stmts((say "caught return"), (return $a))) }; dd a 42'
Attempt to return outside of any Routine

does not.

Since to be able to support this, it would require same serious redesign with regards to return handling, and the fact that it could be considered correct that the LAST phaser won't fire until you've actually done the last iteration or done a last, I've adapted the documentation.

I propose to close this issue with a WONTFIX.

@alabamenhu
Copy link
Contributor Author

Since to be able to support this, it would require same serious redesign with regards to return handling, and the fact that it could be considered correct that the LAST phaser won't fire until you've actually done the last iteration or done a last, I've adapted the documentation.

I propose to close this issue with a WONTFIX.

When we say a WONTFIX, are we saying it's going to be considered canonically correct as designed, or a "not sufficiently common and too difficult to fix at present"?

I'd update in the meantime the documentation to say that if there is a need for LAST to be fired with return, as a workaround, one can do last() && return, last() and return, or last() andthen return. All these ensure that last is called (although sadly parens are necessary)

@lizmat
Copy link
Contributor

lizmat commented Mar 30, 2024

When we say a WONTFIX, are we saying it's going to be considered canonically correct as designed, or a "not sufficiently common and too difficult to fix at present"?

I'd focus on the "canonically correct" since the last iteration was never reached with return. And you could consider last not only as exiting the loop, but also as marking the current iteration as the last one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants