Change custom infix operation to compile to something else

use Something;

sub infix:<%%%>(*@args) is assoc("list") { [*] @args }

say 9 %%% 10;
say 9 %%% 10 %%% -44; 

i want to change it so that this compiles to 28 %%% 5 for first and 28 %%% 5 %%% -22 for second because if operand is odd, it is 3*$_+1 instead. if operand is even number, it is halved instead. What should I do in use Something to make this work

TL;DR Riddle. When is half an answer already an answer? Answer: when you double it by doing nothing. Ain’t that Something?

The initial examples without Something

sub infix:<%%%>(*@args) is assoc("list") { [*] @args }

say 9 %%% 10;         # 90
say 9 %%% 10 %%% -44; # -3960

The goal is to introduce Something such that the output for the above (90 and -3960) change to be output below (140 and -3080):

say 28 %%% 5;         # 140
say 28 %%% 5 %%% -22; # -3080

We don’t care about that second example from here on, just getting those two numbers output for the first example.

First attempt at something. Half an answer?

Introduce a custom infix * and make it oddeven its arguments. Stick it at the top of the file to test (we can pop it in module later):

# use Something;

sub oddeven ($_) { $_ %% 2 ?? $_/2 !! &CORE::infix:<*>(3,$_) + 1 }

sub infix:<*>(*@args) is assoc<right> { &CORE::infix:<*>( |@args>>.&oddeven ) }

# Your original code:

sub infix:<%%%>(*@args) is assoc("list") { [*] @args }

say 9 %%% 10;         # 140
say 9 %%% 10 %%% -44; # -1540

The -1540 is half what it should be. &oddeven is obviously being eval’d twice on the middle argument. Hmm.

An answer? Do nothing, half the time.

Introduce a noop role (trait) and use appropriately:

role noop {}

multi oddeven (noop $_) { $_ }
multi oddeven (     $_) { $_ %% 2 ?? $_/2 !! &CORE::infix:<*>(3,$_) + 1 }

sub infix:<*>(*@args) is assoc<right> { &CORE::infix:<*>( |@args>>.&oddeven ) but noop }

sub infix:<%%%>(*@args) is assoc("list") { [*] @args }

say 9 %%% 10;         # 140
say 9 %%% 10 %%% -44; # -3080
  • Declare a noop role that does… nothing.

  • Split oddeven to do nothing with a noop argument.

  • Add a noop tag to the value calculated by my custom infix * so oddeven would leave it alone when it gets called on that value a second time, as happens in a chained expression (the value that starts out as 10 in 9 %%% 10 %%% -22).

I’ll leave popping it into a module as an exercise for the reader.

Problem solved?

That depends on the nature of the X in what is presumably an XY problem. I deliberately chose not to explore what you were really after (X), and instead focused on problem Y, the one you literally asked.

I’ve come up with an answer, but, but … but. Also, I’m tired, so I haven’t explained some of the code that maybe needs an explanation. So maybe this isn’t yet an acceptable answer. If not, let’s talk, but it won’t be tonight.

Leave a Comment