Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change custom infix operation to compile to something else

Tags:

raku

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

like image 345
freddy Avatar asked Oct 18 '25 19:10

freddy


1 Answers

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.

like image 58
raiph Avatar answered Oct 21 '25 06:10

raiph



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!