Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reload modules used in the REPL?

Tags:

raku

The question is pretty self explanatory. If I load a module in the REPL during development I would like to pick up changes without having to exit first.

like image 835
matthias krull Avatar asked Sep 28 '18 16:09

matthias krull


1 Answers

You can use EVALFILE
(With some caveats)

lib/example.pm6

say (^256).pick.fmt('%02X')

REPL

> EVALFILE('lib/example.pm6'); # rather than `use lib 'lib'; use example;`
DE
> EVALFILE('lib/example.pm6');
6F

The problem comes when you try to use a namespace.

lib/example.pm6

class Foo {
  say (^256).pick.fmt('%02X')
}

REPL

> EVALFILE('lib/example.pm6')
C0
> EVALFILE('lib/example.pm6')
===SORRY!=== Error while compiling /home/brad/EVAL_2
Redeclaration of symbol 'Foo'
at /home/brad/EVAL_2:1
------> class Foo⏏ {
    expecting any of:
        generic role

This still doesn't work if you change the :ver part of the name between each time you load it.

lib/example.pm6

class Foo:ver(0.001) {
  say (^256).pick.fmt('%02X')
}

One way to get around this if you are just experimenting is to make them lexical rather than global.

lib/example.pm6

my class Foo {  # default is `our`
  say (^256).pick.fmt('%02X')
}

REPL

> EVALFILE('lib/test.pm6')
DD
> EVALFILE('lib/test.pm6')
88
> EVALFILE('lib/test.pm6')
6E

It has a separate lexical scope though:

> Foo
===SORRY!=== Error while compiling:
Undeclared name:
    Foo used at line 1

So you will want to alias it:

> my \Foo = EVALFILE('lib/test.pm6'); # store a ref to it in THIS lexical scope
0C
> Foo
(Foo)

> my \Foo = EVALFILE('lib/test.pm6'); # still works the second time
F7

This of course only works because the class definition is the last statement in that scope.


There may be a way to cause a reload similar to how you can in Perl 5 if you dig into the structure of Rakudo, but as far as I know this is not available as part of the language.

like image 116
Brad Gilbert Avatar answered Oct 12 '22 11:10

Brad Gilbert