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

Semantics of coercion type on an "rw" parameter #21

Open
jnthn opened this issue Apr 30, 2019 · 8 comments
Open

Semantics of coercion type on an "rw" parameter #21

jnthn opened this issue Apr 30, 2019 · 8 comments
Labels
language Changes to the Raku Programming Language

Comments

@jnthn
Copy link
Contributor

jnthn commented Apr 30, 2019

Currently, if writing:

sub foo(Num() $n is rw) { $n++ }

Then we can call it successfully like this:

my $x = 1e0;
foo($x);
dd $x;    # Num $x = 2e0

However, if the coercion is applied, such as in this case:

my $x = 1;
foo($x);

Then it binds the result of the coercion to $n in foo, resulting in an error since ++ is being done on an immutable value. This is almost certainly the result of not having considered how this interaction should work.

@jnthn jnthn added the language Changes to the Raku Programming Language label Apr 30, 2019
@jnthn
Copy link
Contributor Author

jnthn commented Apr 30, 2019

Initial proposal: I see two main options.

We could make it a compile-time error, so folks can't run into it accidentally. This avoids any further gotchas in this area. However, this could break working code that is successful because all the cases that exercise it pass a matching type.

Alternatively, we could define the use of a coercion type together with is rw as meaning that we should assign the result of the coercion into the passed container. This would mean that:

sub nummy(Num() $x is rw) { }
my $x = 42;
nummy($x);

Would result in $x being coerced an Int after the call. That might be OK, however there's a problem with multi-dispatch that needs a bind check. For example:

multi sub nummy(Num() $x is rw, Num $y where something-needing-nums($x, $y)) { }

Would require one, and would potentially as part of signature processing mutate $x - even in the case that the multi candidate were not selected because the where clause failed to match! It's not like you can't construct such cases today anyway, by doing side-effects in a default expression or a where clause. But it's worth considering whether that I managed to think of a surprise within 5 minutes consideration might mean there's others we didn't think of, if we try to make this DWIM.

@Xliff
Copy link

Xliff commented Apr 30, 2019

In this situation, I suggest that in this situation:

sub nummy(Num() $x is rw) { }
my $x = 42;
nummy($x);

The coercion is fine, since there is no type applied to $x. However in the more restrictive situation:

sub nummy(Num() $x is rw) { }
my Int $x = 42;
nummy($x);

The coercion is incorrect and should generate a run-time exception.

Thoughts?

@alabamenhu
Copy link

sub nummy(Num() $x is rw) { }
my Int $x = 42;
nummy($x);

The coercion is incorrect and should generate a run-time exception.

Thoughts?

I don't mind that behavior at all. Just a quick type check on the assignment.

my Cool $x = 42;
my Str $y = "42";
nummy($x); # no error
nummy($y); # error

I think that'd be a pretty nice if eventually we could specify coercion on assignment such that:

my Int() $x = 42;
nummy($x);

Could recoerce back to Int upon completion, if possible, and generate a run-time exception otherwise, but doing a coercing assignment would be a very different topic indeed, so I digress.

As to the concerns that Jonathan had, from a user perspective, I'd expect

multi sub nummy(Num() $x is rw, Num $y where something-needing-nums($x, $y)) { }

to work more or less like this:

sub nummy($x is rw, Num $y) {
  my Num $x-temp = $x.Num;
  die unless something-needing-nums($x, $y);
  # signature match is successful so …
  $x = $x-temp;
  # begin nummy
  ...
}

In other words, the coerced value would be temporarily stored, and only properly assigned to the rw container upon a successful signature completion.

@jnthn
Copy link
Contributor Author

jnthn commented May 11, 2019

... The coercion is incorrect and should generate a run-time exception.

This is what I'd expect, yes.

In other words, the coerced value would be temporarily stored, and only properly assigned to the rw container upon a successful signature completion.

Signature binding is defined as processing the parameters in order. The point of the where clause in the example is that we actually expect $x to be the coerced value at that point, which it would not be with the proposed desugar. As another example, consider (Num() $x is rw, Num $y = $x), which would clearly fail if $x did not contain the Num by the point the default of $y was evaluated. I'm not convinced there's any trickery we can do with regards to delaying it that I can't come up with a counter-example for.

@lizmat lizmat unassigned jnthn Oct 5, 2020
@raiph
Copy link

raiph commented Dec 26, 2020

Is there consensus that it would be good to have a general principle along the following lines?

  • If a problematic semantic is being discussed; and

  • The option to disallow the problem by newly making it a compile time failure is available; and

  • Discussion stalls before a consensus is reached on what, who, and when a better solution will be introduced (and perhaps even then);; then

  • The compile-time rejection should be considered for introduction on master as a probably appropriate immediate step; with blining to see what fall out there appears to be, and then introduction into a subsequent release, to stop the problem of code relying on the given problematic semantic becoming more entrenched.

@patrickbkr
Copy link
Member

@raiph I do like the idea to introduce compiler errors when a construct is clearly problematic and serves no use. How could such a policy introduced? Is this a topic for the RSC?

@niner
Copy link

niner commented Jan 6, 2021 via email

@lizmat
Copy link
Collaborator

lizmat commented Jan 6, 2021

As far as I can remember, making something a compile time error when semantics are still unclear, has been the policy. That's why we have a X::NYI exception :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
language Changes to the Raku Programming Language
Projects
None yet
Development

No branches or pull requests

7 participants