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

infix:<o> always returns a Block with .arity 0 and .count Inf #6112

Closed
p6rt opened this issue Feb 28, 2017 · 7 comments
Closed

infix:<o> always returns a Block with .arity 0 and .count Inf #6112

p6rt opened this issue Feb 28, 2017 · 7 comments
Labels
LTA Less Than Awesome; typically an error message that could be better

Comments

@p6rt
Copy link

p6rt commented Feb 28, 2017

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

Searchable as RT130891$

@p6rt
Copy link
Author

p6rt commented Feb 28, 2017

From @smls

  my &a = *+1;
  my &b = */2;

  say &a.arity; # 1
  say &b.arity; # 1
  say (&a o &b).arity; # 0

  say &a.count; # 1
  say &b.count; # 1
  say (&a o &b).count; # Inf

Ideally, the result of the `o` operator should probably have the same
signature as its right-hand argument (which gets the input "first").

Things that care about arity/count, and thus might currently behave
differently than users expect when given a Block created by `o`,
include​:

  .sort (comparator vs Schwartzian transform)
  .map (normal map vs n-at-a-time)
  o (interpolates input lists if count>1)

@p6rt
Copy link
Author

p6rt commented Mar 8, 2017

From @zoffixznet

On Tue, 28 Feb 2017 14​:41​:07 -0800, smls75@​gmail.com wrote​:

my &a = \*\+1;
my &b = \*/2;

say &a\.arity;         \# 1
say &b\.arity;         \# 1
say \(&a o &b\)\.arity;  \# 0

say &a\.count;         \# 1
say &b\.count;         \# 1
say \(&a o &b\)\.count;  \# Inf

Ideally, the result of the `o` operator should probably have the same
signature as its right-hand argument (which gets the input "first").

Things that care about arity/count, and thus might currently behave
differently than users expect when given a Block created by `o`,
include​:

.sort (comparator vs Schwartzian transform)
.map (normal map vs n-at-a-time)
o (interpolates input lists if count>1)

I have a patch (attached). That solves this ticket and passes all stresstests​:

  cpan@​perlbuild2~/CPANPRC/rakudo (nom)$ ./perl6 -e 'm​: say ([o] {$_ xx 3} xx 3)(5)'
  (((5 5 5) (5 5 5) (5 5 5)) ((5 5 5) (5 5 5) (5 5 5)) ((5 5 5) (5 5 5) (5 5 5)))

However, it has a definite stench of an evil hack about it, so I'll leave it for someone who knows more about the internals to figure out whether it can be committed. One example of evil weirdness​: the `.signature` becomes the sub's signature (e.g. `($a, $b)`), but the block still uses `|args` capture to pass around args? waaaat...

@p6rt
Copy link
Author

p6rt commented Mar 8, 2017

From @zoffixznet

infix-o.diff
diff --git a/src/core/operators.pm b/src/core/operators.pm
index f5da866..d1661e0 100644
--- a/src/core/operators.pm
+++ b/src/core/operators.pm
@@ -726,7 +726,14 @@ multi sub trait_mod:<is>(Routine $r, Str :$looser!) {
 proto sub infix:<∘> (&?, &?) {*}
 multi sub infix:<∘> () { *.self }
 multi sub infix:<∘> (&f) { &f }
-multi sub infix:<∘> (&f, &g --> Block) { (&f).count > 1 ?? -> |args { f |g |args } !! -> |args { f g |args } }
+multi sub infix:<∘> (&f, &g --> Block) {
+    my \ret = &f.count > 1
+        ?? -> |args { f |g |args }
+        !! -> |args { f  g |args }
+    nqp::bindattr(ret, Code, '$!signature',
+        nqp::getattr(nqp::decont(&g), Code, '$!signature'));
+    ret;
+}
 my &infix:<o> := &infix:<∘>;
 
 # vim: ft=perl6 expandtab sw=4

@p6rt
Copy link
Author

p6rt commented Mar 8, 2017

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

@p6rt
Copy link
Author

p6rt commented Mar 8, 2017

From @zoffixznet

P.S.​: RT seems to be messing up Unicode ∘ char in the patch above. Download the file, don't copy-paste from this page.

@p6rt
Copy link
Author

p6rt commented Mar 9, 2017

From @zoffixznet

On Tue, 28 Feb 2017 14​:41​:07 -0800, smls75@​gmail.com wrote​:

my &a = \*\+1;
my &b = \*/2;

say &a\.arity;         \# 1
say &b\.arity;         \# 1
say \(&a o &b\)\.arity;  \# 0

say &a\.count;         \# 1
say &b\.count;         \# 1
say \(&a o &b\)\.count;  \# Inf

Ideally, the result of the `o` operator should probably have the same
signature as its right-hand argument (which gets the input "first").

Things that care about arity/count, and thus might currently behave
differently than users expect when given a Block created by `o`,
include​:

.sort (comparator vs Schwartzian transform)
.map (normal map vs n-at-a-time)
o (interpolates input lists if count>1)

Thank you for the report. This is now fixed.

Fixes​:
rakudo/rakudo@032b283d5a
rakudo/rakudo@cb149a836e

Tests​:
Raku/roast@270dcf82f2
Raku/roast@f31eeabab5

@p6rt
Copy link
Author

p6rt commented Mar 9, 2017

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

@p6rt p6rt closed this as completed Mar 9, 2017
@p6rt p6rt added the LTA Less Than Awesome; typically an error message that could be better label Jan 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
LTA Less Than Awesome; typically an error message that could be better
Projects
None yet
Development

No branches or pull requests

1 participant