problem-solving icon indicating copy to clipboard operation
problem-solving copied to clipboard

RFE: returns for multiple variables

Open ToddAndMargo opened this issue 5 years ago • 7 comments

Dear Raku,

Would you please consider the following Request for Enhancement?

I live and die by top down. I have subs and modules out the nose. On the declaration line of a sub, I love to use the "returns" or the "-->" syntax. This give a good idea at a glance what the sub does and helps with maintainability and readability. Well, me at least. So when I return two of more values return($a, $b, $c) from a sub, I would like Raku to add to the declaration line a way to do a “returns” for that situation. Something like -→ Int, UInt, Str or returns Uint, Int,Str.

The result would be the same as:

subset Tuple where * ~~ (Int, UInt, Str); 
sub f($a,$b,$c --> Tuple) { ($a,$b,$c) }; 
say f(-1, 'x', 5) 
# out of order, fails.

But all on the declaration line to improve readability/maintainability.

Thank you for your consideration, -T

ToddAndMargo avatar Jan 22 '20 18:01 ToddAndMargo

We could allow (...) and [...] with the same semantics as we have for parameter checking - that is to say, they'd parse a signature inside of them, the latter also adding a Positional constraint upon the overall return value. Thus one could write:

sub f($a,$b,$c --> (Int, UInt, Str)) { ($a,$b,$c) }; 
say f(-1, 'x', 5) 

To achieve the desired effect. Implementation wise, it coerces the return value to a Capture and then does a signature match - just like sub-signatures used in destructuring.

This means one could also add where constraints in there too:

sub f($a, $b --> (Int where * > 0, Int where * < 0)) {
    ...
}

Or even nested signatures to validate recursive structure.

jnthn avatar Feb 20 '20 00:02 jnthn

I'm wondering whether this RFE is 'a bridge too far'. Specifically I'd like to know if other programming languages have implemented 'multiple returns from functions' and how successful they've been.

Multiple-returns in the R-programming language is accomplished by placing the return items into a singular data object, usually a list. In doing so the items obtain a positional value, so that subsequent functions know where to look.

I don't see how this feature could be implemented without assigning some sort of "implicit" positional reference-parameter to each of the returned items. Which in my mind suggests that an explicit @array return is better, or possibly a %hash return with the key of the hash standing in for the 'positional' reference-parameter.

Best Regards.

jubilatious1 avatar Feb 18 '21 20:02 jubilatious1

Multiple-returns in the R-programming language is accomplished by placing the return items into a singular data object, usually a list. In doing so the items obtain a positional value, so that subsequent functions know where to look.

That's how returning "multiple values" already works in Raku. However, there's not currently a convenient way to express that in the return type, and thus have the list elements validated.

jnthn avatar Feb 18 '21 21:02 jnthn

So it wasn't clear to me if @ToddAndMargo was requesting multiple returns as individual variables/values, or within a data object that does Positional and/or does Associative.

I hope I understand the current Raku implementation. I agree that within the context of a Positional and/or Associative return object it would be huge to [add the following]:

...a convenient way to express that in the return type, and thus have the list elements validated.

jubilatious1 avatar Feb 20 '21 15:02 jubilatious1

Reading through this issue, it sound like there is general consensus behind the idea of adding support for validating sub-signature of a returned Positional or Associative with the same syntax that is currently used for destructuring parameters (e.g., sub f(--> (Int, Str) would require &f to return a Positional with only an Int and a Str. It also sounds like we have at least a plan for an implementation – coerce the returned value to a Capture and match on it.

If so, all we are missing is someone to volunteer to implement the solution. I'd be happy to do so (I've missed the ability to use this syntax more than once in my past few projects!). If no one disagrees with my reading of the issue, I'll submit a PR with a more detailed description of the solution in the next few days.

(If I do implement this solution, it'll be my first change to the true nqp side of the compiler – my changes so far have been on the Raku side. Given that, I'd appreciate it if someone could be available as a sounding board/mentor if I get stuck. But I'm also happy to muddle through on my own as well)

codesections avatar Mar 21 '21 16:03 codesections

It also sounds like we have at least a plan for an implementation – coerce the returned value to a Capture and match on it.

Yes, that's probably the way to go - at least in the current compiler frontend. (For the new RakuAST-based frontend I'm aiming to having destructuring compiled just as parameter binding is, which should be a significant performance win. This would then cover this case, destructuring :=, and destructuring in parameter lists.)

If no one disagrees with my reading of the issue, I'll submit a PR with a more detailed description of the solution in the next few days.

No disagreement from me. The implementation will need re-doing for the new compiler frontend, but that's months away, and I'd not want it to hold up getting language improvements implemented. Of course the tests, docs, and so on that are produced along the way will be just as valid too. So, go for it.

Given that, I'd appreciate it if someone could be available as a sounding board/mentor if I get stuck.

In theory I know how the signature binding stuff works, feel free to ping me if you need help. :-)

jnthn avatar Mar 21 '21 17:03 jnthn

I'm very interested in being able to constrain multiple-return values. Any news on the status of this?

arkiuat avatar Nov 28 '23 03:11 arkiuat