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

Custom class :D coersers don't work #6410

Open
p6rt opened this issue Jul 24, 2017 · 7 comments
Open

Custom class :D coersers don't work #6410

p6rt opened this issue Jul 24, 2017 · 7 comments

Comments

@p6rt
Copy link

p6rt commented Jul 24, 2017

Migrated from rt.perl.org#131791 (status was 'open')

Searchable as RT131791$

@p6rt
Copy link
Author

p6rt commented Jul 24, 2017

From @zoffixznet

The coercion works fine here​:

17​:03 Zoffix m​: class B {…}; class A { method B { B.new }}; class B {}; sub foo(B() $b) { say "hi" }; foo(A.new)
17​:03 camelia rakudo-moar 2fb8c7​: OUTPUT​: «hi?»

But if I add `​:D` smiley, it fails​:

17​:03 Zoffix m​: class B {…}; class A { method B { B.new }}; class B {}; sub foo(B​:D() $b) { say "hi" }; foo(A.new)
17​:03 camelia rakudo-moar 2fb8c7​: OUTPUT​: «Type check failed in binding to parameter '$b'; expected B but got A (A.new)? in sub foo at <tmp> line 1? in block <unit> at <tmp> line 1??»

https://irclog.perlgeek.de/perl6/2017-07-24#i_14915397

@p6rt
Copy link
Author

p6rt commented Aug 23, 2017

From @skids

On Mon, 24 Jul 2017 10​:04​:54 -0700, cpan@​zoffix.com wrote​:

The coercion works fine here​:

17​:03 Zoffix m​: class B {…}; class A { method B { B.new }}; class B
{}; sub foo(B() $b) { say "hi" }; foo(A.new)
17​:03 camelia rakudo-moar 2fb8c7​: OUTPUT​: «hi?»

But if I add `​:D` smiley, it fails​:

17​:03 Zoffix m​: class B {…}; class A { method B { B.new }}; class B
{}; sub foo(B​:D() $b) { say "hi" }; foo(A.new)
17​:03 camelia rakudo-moar 2fb8c7​: OUTPUT​: «Type check failed
in binding to parameter '$b'; expected B but got A (A.new)? in sub
foo at <tmp> line 1? in block <unit> at <tmp> line 1??»

https://irclog.perlgeek.de/perl6/2017-07-24#i_14915397

Seems to be more generic than custom classes​:

$ perl6 -e 'sub foo(Int() $b) { say $b }; foo("42")'
42
$ perl6 -e 'sub foo(Int​:D() $b) { say $b }; foo("42")'
Type check failed in binding to parameter '$b'; expected Int but got Str ("42")
  in sub foo at -e line 1
  in block <unit> at -e line 1

This raises the spec question, should e.g. IO​:U($a) try to convert $a to an IO,
and if that succeeds, succeed the bind with the type object of whatever doer (or
subclass were IO a class) of IO which resulted? Or fail the bind? The latter is
more consistent with the above desired behavior... but does "Class​:D()" mean
coerce-to-then-check-definedness, or go-all-out-to-make-a-defined-value?

This doesn't make much sense yet either​:

$ perl6 -e 'Int​:D(4).say'
(Int​:D)

@p6rt
Copy link
Author

p6rt commented Aug 23, 2017

The RT System itself - Status changed from 'new' to 'open'

@p6rt
Copy link
Author

p6rt commented Sep 9, 2017

From @skids

On Wed, 23 Aug 2017 06​:20​:49 -0700, bri@​abrij.org wrote​:

On Mon, 24 Jul 2017 10​:04​:54 -0700, cpan@​zoffix.com wrote​:

The coercion works fine here​:

17​:03 Zoffix m​: class B {…}; class A { method B { B.new }}; class
B
{}; sub foo(B() $b) { say "hi" }; foo(A.new)
17​:03 camelia rakudo-moar 2fb8c7​: OUTPUT​: «hi?»

But if I add `​:D` smiley, it fails​:

17​:03 Zoffix m​: class B {…}; class A { method B { B.new }}; class
B
{}; sub foo(B​:D() $b) { say "hi" }; foo(A.new)
17​:03 camelia rakudo-moar 2fb8c7​: OUTPUT​: «Type check
failed
in binding to parameter '$b'; expected B but got A (A.new)? in sub
foo at <tmp> line 1? in block <unit> at <tmp> line 1??»

https://irclog.perlgeek.de/perl6/2017-07-24#i_14915397

Seems to be more generic than custom classes​:

$ perl6 -e 'sub foo(Int() $b) { say $b }; foo("42")'
42
$ perl6 -e 'sub foo(Int​:D() $b) { say $b }; foo("42")'
Type check failed in binding to parameter '$b'; expected Int but got
Str ("42")
in sub foo at -e line 1
in block <unit> at -e line 1

This raises the spec question, should e.g. IO​:U($a) try to convert $a
to an IO,
and if that succeeds, succeed the bind with the type object of
whatever doer (or
subclass were IO a class) of IO which resulted? Or fail the bind?
The latter is
more consistent with the above desired behavior... but does
"Class​:D()" mean
coerce-to-then-check-definedness, or go-all-out-to-make-a-defined-
value?

This doesn't make much sense yet either​:

$ perl6 -e 'Int​:D(4).say'
(Int​:D)

This ticket and RT#​126433 can be combined.

@p6rt
Copy link
Author

p6rt commented Sep 10, 2017

From @skids

On Fri, 08 Sep 2017 21​:13​:59 -0700, bri@​abrij.org wrote​:

On Wed, 23 Aug 2017 06​:20​:49 -0700, bri@​abrij.org wrote​:

On Mon, 24 Jul 2017 10​:04​:54 -0700, cpan@​zoffix.com wrote​:

The coercion works fine here​:

17​:03 Zoffix m​: class B {…}; class A { method B { B.new }}; class
B
{}; sub foo(B() $b) { say "hi" }; foo(A.new)
17​:03 camelia rakudo-moar 2fb8c7​: OUTPUT​: «hi?»

But if I add `​:D` smiley, it fails​:

17​:03 Zoffix m​: class B {…}; class A { method B { B.new }}; class
B
{}; sub foo(B​:D() $b) { say "hi" }; foo(A.new)
17​:03 camelia rakudo-moar 2fb8c7​: OUTPUT​: «Type check
failed
in binding to parameter '$b'; expected B but got A (A.new)? in sub
foo at <tmp> line 1? in block <unit> at <tmp> line 1??»

https://irclog.perlgeek.de/perl6/2017-07-24#i_14915397

Seems to be more generic than custom classes​:

$ perl6 -e 'sub foo(Int() $b) { say $b }; foo("42")'
42
$ perl6 -e 'sub foo(Int​:D() $b) { say $b }; foo("42")'
Type check failed in binding to parameter '$b'; expected Int but got
Str ("42")
in sub foo at -e line 1
in block <unit> at -e line 1

This raises the spec question, should e.g. IO​:U($a) try to convert $a
to an IO,
and if that succeeds, succeed the bind with the type object of
whatever doer (or
subclass were IO a class) of IO which resulted? Or fail the bind?
The latter is
more consistent with the above desired behavior... but does
"Class​:D()" mean
coerce-to-then-check-definedness, or go-all-out-to-make-a-defined-
value?

This doesn't make much sense yet either​:

$ perl6 -e 'Int​:D(4).say'
(Int​:D)

This ticket and RT#​126433 can be combined.

I spent some more time digging into this. There are a couple layers to this issue.

The first is a syntax conflict. Consider (example from specs)​:

use Dog​:auth(/​:i jrandom/)​:ver(v1.2.1 | v1.3.4);

...in order to parse that the generic "extended identifier" syntax is allowed to
take a statement list as the value of a colonpair-in-a-name. This is somewhat
more liberal than what is normally allowed in a coercion type.

Now in the S02, "extended identifiers" are said to only allow a
"subscript-like adverbial form", which would exclude parens as the circumfix,
so one solution to this would be to restrict the above syntax to
useish statements only, or some broader but still limited syntactic
category. There seems to be some logic for this already in token term​:sym<name>,
but not in token typename, which is where this case ends up.

The second issue bears on the spec issue I raised above​: if you do manage to
chop through the syntax issues, then you have to decide whether the class
coercion method that is called is named "B" or "B​:D"... having separate
methods for all smiley types could be advantageous, but would be tedious.
Perhaps looking for "B​:D" and if not found, calling "B" instead would be
something to consider here.

To pile on that, we get to the (NYI) behavior where the adverbial components
of an extended identifier are supposed to be orderless, along with the prospect
for compound smileys to be added later... cross that bridge when we get there I guess.

@p6rt
Copy link
Author

p6rt commented Sep 11, 2017

From @skids

On Sun, 10 Sep 2017 11​:44​:09 -0700, bri@​abrij.org wrote​:

On Fri, 08 Sep 2017 21​:13​:59 -0700, bri@​abrij.org wrote​:

On Wed, 23 Aug 2017 06​:20​:49 -0700, bri@​abrij.org wrote​:

On Mon, 24 Jul 2017 10​:04​:54 -0700, cpan@​zoffix.com wrote​:

The coercion works fine here​:

17​:03 Zoffix m​: class B {…}; class A { method B { B.new }};
class
B
{}; sub foo(B() $b) { say "hi" }; foo(A.new)
17​:03 camelia rakudo-moar 2fb8c7​: OUTPUT​: «hi?»

But if I add `​:D` smiley, it fails​:

17​:03 Zoffix m​: class B {…}; class A { method B { B.new }};
class
B
{}; sub foo(B​:D() $b) { say "hi" }; foo(A.new)
17​:03 camelia rakudo-moar 2fb8c7​: OUTPUT​: «Type check
failed
in binding to parameter '$b'; expected B but got A (A.new)? in
sub
foo at <tmp> line 1? in block <unit> at <tmp> line 1??»

https://irclog.perlgeek.de/perl6/2017-07-24#i_14915397

Seems to be more generic than custom classes​:

$ perl6 -e 'sub foo(Int() $b) { say $b }; foo("42")'
42
$ perl6 -e 'sub foo(Int​:D() $b) { say $b }; foo("42")'
Type check failed in binding to parameter '$b'; expected Int but
got
Str ("42")
in sub foo at -e line 1
in block <unit> at -e line 1

This raises the spec question, should e.g. IO​:U($a) try to convert
$a
to an IO,
and if that succeeds, succeed the bind with the type object of
whatever doer (or
subclass were IO a class) of IO which resulted? Or fail the bind?
The latter is
more consistent with the above desired behavior... but does
"Class​:D()" mean
coerce-to-then-check-definedness, or go-all-out-to-make-a-defined-
value?

This doesn't make much sense yet either​:

$ perl6 -e 'Int​:D(4).say'
(Int​:D)

This ticket and RT#​126433 can be combined.

I spent some more time digging into this. There are a couple layers
to this issue.

The first is a syntax conflict. Consider (example from specs)​:

use Dog​:auth(/​:i jrandom/)​:ver(v1.2.1 | v1.3.4);

...in order to parse that the generic "extended identifier" syntax is
allowed to
take a statement list as the value of a colonpair-in-a-name. This is
somewhat
more liberal than what is normally allowed in a coercion type.

Now in the S02, "extended identifiers" are said to only allow a
"subscript-like adverbial form", which would exclude parens as the
circumfix,
so one solution to this would be to restrict the above syntax to
useish statements only, or some broader but still limited syntactic
category. There seems to be some logic for this already in token
term​:sym<name>,
but not in token typename, which is where this case ends up.

The second issue bears on the spec issue I raised above​: if you do
manage to
chop through the syntax issues, then you have to decide whether the
class
coercion method that is called is named "B" or "B​:D"... having
separate
methods for all smiley types could be advantageous, but would be
tedious.
Perhaps looking for "B​:D" and if not found, calling "B" instead would
be
something to consider here.

To pile on that, we get to the (NYI) behavior where the adverbial
components
of an extended identifier are supposed to be orderless, along with the
prospect
for compound smileys to be added later... cross that bridge when we
get there I guess.

When fixing, please note also RT#​130657

@usev6
Copy link

usev6 commented Oct 7, 2023

To update this old issue a bit:

Original report: The evaluation given in the original report no longer errors out when a :D smiley is added to a coercer for a custom class:

$ ./rakudo-m -e 'class B {...}; class A { method B { B.new } }; class B {}; sub foo(B:D() $b) { say "hi" }; foo(A.new)'
hi

(And since the link to irclog.perlgeek.de no longer works, here is equivalent link to colabti.org: https://colabti.org/irclogger/irclogger_log/perl6?date=2017-07-24#l754.)

Non-custom class: Using Int:D() (from the first response) works fine as well (no error anymore):

$ ./rakudo-m -e 'sub foo(Int:D() $b) { say $b }; foo("42")'
42

Int:D(4) fails now: The last snippet from the first response no longer returns Int:D (which was described as "doesn't make much sense yet either"), but errors out:

$ ./rakudo-m -e 'Int:D(4).say'
===SORRY!=== Error while compiling -e
Coercer is too complex. Only type objects, with optional type smileys, or empty parentheses, implying 'Any', are supported.
at -e:1
------> Int:D(4)⏏.say

RT#126433: The mentioned issue RT#126433 -- aka #4673 has been resolved back in 2018. It also has a link with a commit that unfudges a corresponding test in roast: Raku/roast@7327b52b82214d440


So far, so clear. Only looking at those points, I'd say that this issue can be closed.

But the first response also raised a spec question -- with an elaborated comment later on.
For the sake of clarity, I'll quote that spec question here (but not the later, much longer comment):

This raises the spec question, should e.g. IO​:U($a) try to convert $a to an IO,
and if that succeeds, succeed the bind with the type object of whatever doer (or
subclass were IO a class) of IO which resulted? Or fail the bind? The latter is
more consistent with the above desired behavior... but does "Class​:D()" mean
coerce-to-then-check-definedness, or go-all-out-to-make-a-defined-value?

Given that question, I'll leave this issue open.

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

No branches or pull requests

2 participants