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

multi subs with inconsistent where clauses don't work correctly #6109

Closed
p6rt opened this issue Feb 27, 2017 · 5 comments
Closed

multi subs with inconsistent where clauses don't work correctly #6109

p6rt opened this issue Feb 27, 2017 · 5 comments

Comments

@p6rt
Copy link

p6rt commented Feb 27, 2017

Migrated from rt.perl.org#130886 (status was 'resolved')

Searchable as RT130886$

@p6rt
Copy link
Author

p6rt commented Feb 27, 2017

From @b2gills

This prints the numbers 1 to 9 then fails with a constraint error

  my \one-out-of-ten = (|(False,False,False,False,False,False,False,False,False,True) xx *).iterator;

  multi sub rarely ( $_ where one-out-of-ten.pull-one ){ say "test $_"; nextsame}
  multi sub rarely ( $_ ) { .say }

  (1..100).map​: &rarely;

If I switch it so that it usually matches it doesn't fail

  my \nine-out-of-ten = (|(False,True,True,True,True,True,True,True,True,True) xx *).iterator;

  multi sub often ( $_ where nine-out-of-ten.pull-one ){ say "test $_"; nextsame }
  multi sub often ( $_ ) { .say }

  (1..100).map​: &often;

It does seem as if the constraint is being called twice
because the first skip is on 5.

The reason I stumbled across this I thought something like this
could be good for logging one out of every ten inputs.

@p6rt
Copy link
Author

p6rt commented Feb 28, 2017

From @timo

I'd say this is NOTABUG via the DIHWIDT category. If your where clause
has side-effects, you're bound to get in trouble.

If you're fine with relying on internals, you can just put True into the
one-out-of-ten three times at the end and the program will run through
to 100.

  test 90
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
  test 100
  100
  timo@​schmand ~> cat /tmp/inconsistent.p6
  my \one-out-of-ten =
(|(False,False,False,False,False,False,False,False,False,True,True,True)
xx *).iterator;
 
  multi sub rarely ( $_ where one-out-of-ten.pull-one ){ say "test
$_"; nextsame}
  multi sub rarely ( $_ ) { .say }
 
  (1..100).map​: &rarely;

We rely on binding a signature to give the same result multiple times in
a row to make signature binding code a whole bunch faster. We have a
"slow binder" and a "fast binder". The fast one can only produce a "it
worked" or "it didn't work" result, so after a "it didn't work" result
was encountered we run the slow one over the same values to produce an
actual error message. Normally if your where clauses behave in an impure
manner, you'd get "Internal error​: inconsistent bind result" (that's
when the fast binder says "failed" and the slow binder can't reproduce
the failure).

I'm not entirely sure why it gives you "Constraint type check failed for
parameter '$_'". My best guess is that because it first tries to figure
out which candidate to invoke and then actually calls into the candidate
(which starts with code generated by the fast binder) it hits a bind
failure as if you had directly invoked that candidate yourself but with
non-matching arguments.

Zoffix wrote a bit of code on IRC that demonstrates "inconsistent bind
result", btw​:

  perl6 -e 'my $val; multi foo($ where {$val++ %% 2 ?? 1 !! 0}) { say
"here" }; multi foo($) { say "♥" }; foo(42) for ^20'
  Internal error​: inconsistent bind result
  in sub foo at <tmp> line 1
  in block <unit> at <tmp> line 1

Hope that clears things up!
  - Timo

BTW, for a fun time, put a "say 'here'" into a where clause and count
how often it gets invoked.

@p6rt
Copy link
Author

p6rt commented Feb 28, 2017

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

@p6rt
Copy link
Author

p6rt commented Mar 4, 2017

From @zoffixznet

On Tue, 28 Feb 2017 05​:54​:51 -0800, timo wrote​:

I'd say this is NOTABUG via the DIHWIDT category. If your where clause
has side-effects, you're bound to get in trouble.

If you're fine with relying on internals, you can just put True into the
one-out-of-ten three times at the end and the program will run through
to 100.

test 90
90
91
92
93
94
95
96
97
98
99
test 100
100
timo@&#8203;schmand ~> cat /tmp/inconsistent\.p6
    my \\one\-out\-of\-ten =

(|(False,False,False,False,False,False,False,False,False,True,True,True)
xx *).iterator;

    multi sub rarely \( $\_ where one\-out\-of\-ten\.pull\-one \)\{ say "test

$_"; nextsame}
multi sub rarely ( $_ ) { .say }

    \(1\.\.100\)\.map&#8203;: &rarely;

We rely on binding a signature to give the same result multiple times in
a row to make signature binding code a whole bunch faster. We have a
"slow binder" and a "fast binder". The fast one can only produce a "it
worked" or "it didn't work" result, so after a "it didn't work" result
was encountered we run the slow one over the same values to produce an
actual error message. Normally if your where clauses behave in an impure
manner, you'd get "Internal error​: inconsistent bind result" (that's
when the fast binder says "failed" and the slow binder can't reproduce
the failure).

I'm not entirely sure why it gives you "Constraint type check failed for
parameter '$_'". My best guess is that because it first tries to figure
out which candidate to invoke and then actually calls into the candidate
(which starts with code generated by the fast binder) it hits a bind
failure as if you had directly invoked that candidate yourself but with
non-matching arguments.

Zoffix wrote a bit of code on IRC that demonstrates "inconsistent bind
result", btw​:

perl6 \-e 'my $val; multi foo\($ where \{$val\+\+ %% 2 ?? 1 \!\! 0\}\) \{ say

"here" }; multi foo($) { say "♥" }; foo(42) for ^20'
Internal error​: inconsistent bind result
in sub foo at <tmp> line 1
in block <unit> at <tmp> line 1

Hope that clears things up!
- Timo

BTW, for a fun time, put a "say 'here'" into a where clause and count
how often it gets invoked.

Closing this per comments above.

I've committed a note into the docs to clarify side-effects from where clauses aren't meant to work​: Raku/doc@3ed1803

@p6rt
Copy link
Author

p6rt commented Mar 4, 2017

@zoffixznet - Status changed from 'open' to 'resolved'

@p6rt p6rt closed this as completed Mar 4, 2017
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

1 participant