11
sub hanoi(Int:D $n, Str:D $start, Str:D $end, Str:D $extra,
          &move_disk:(Int:D, Str:D, Str:D --> Nil)
          --> Nil)
{
    if $n == 1 {
        move_disk(1, $start, $end);              # Step 1
    }
    else {
        hanoi($n - 1, $start, $extra, $end);     # Step 2
        move_disk($n, $start, $end);             # Step 3
        hanoi($n - 1, $extra, $end, $start);     # Step 4
    }
}

sub print_instruction(Int:D $n, Str:D $start, Str:D $end --> Nil)
{
    say "Move disk #$n from $start to $end";
}

Calling hanoi(3, 'A', 'B', 'C', print_instruction) gives:

Too few positionals passed; expected 3 arguments but got 0
  in sub print_instruction at <unknown file> line 15
  in block <unit> at <unknown file>
Elizabeth Mattijsen
  • 25,654
  • 3
  • 75
  • 105
vonbrand
  • 11,412
  • 8
  • 32
  • 52
  • 4
    `print_instruction` in `hanoi(3, 'A', 'B', 'C', print_instruction)` *calls* `print_instruction` instead of referring to it like in Python. (Why? Too many good reasons to fit in comments but one is that Raku unifies field references and method calls -- both are `.bar` -- as part of 100% encapsulation of object state. That [solves the Fragile base class problem](https://en.wikipedia.org/wiki/Fragile_base_class#:~:text=One%20possible,superclass%20states.) and makes Raku [Actor model "ready"](https://gist.github.com/raiph/849a4a9d8875542fb86df2b2eda89296#:~:text=Actor%20model%20%22consistent%22).) – raiph Apr 10 '23 at 17:38

1 Answers1

16

There are several things wrong with your code:

  1. hanoi(3, 'A', 'B', 'C', print_instruction)

In that statement, you're passing the result of the call to print_instruction as the 4th parameter. You're evidently expecting it to be something Callablejudging from the signature of the hanoi sub. If you want to pass the callable, you need to prefix the name with a &, so:

hanoi(3, 'A', 'B', 'C', &print_instruction);

Because the print_instruction sub does expect 3 arguments, and you called it with zero, you get the "expected 3 arguments but got 0" error.

  1. The first call to hanoi has 5 arguments, but the recursive calls only pass 4. You will get a similar error there, but with different numbers: expected 5 arguments but got 4. The simplest solution is to pass that on as well:

    hanoi($n - 1, $start, $extra, $end, &move_disk);

Finally: using underscores in identifiers is sooo 1990's :-) You can also use the hyphen in identifiers in the Raku Programming Language! So you can call the move_disk subroutine move-disk :-)

Elizabeth Mattijsen
  • 25,654
  • 3
  • 75
  • 105