> On 11 Jul 2021, at 01:11, Joseph Brenner <[email protected]> wrote:
>
> I want my test files to be able to find the modules they're testing
> just using their relative locations, given the usual layout of "lib"
> and "t" locations in parallel inside the project directory.
>
> I find that while this works:
>
> use lib $*PROGRAM.parent.add('../lib');
>
> This doesn't work:
>
> my $lib_loc = $*PROGRAM.parent.add('../lib');
> use lib "$lib_loc";
>
> I get a compile time error
>
> Use of uninitialized value $lib_loc of type Any in string context.
> ...
> Repository specification can not be an empty string. Did you mean
> 'use lib "."' ?
"use lib" is a compile time statement.
"my $lib_loc = ..." is a runtime statement, with a compile time component for
the definition.
So what happens is that when the "use lib" is executed (at compile time), the
$lib_loc variable *is* known, but it hasn't been initialized yet. Which is
basically what the error message says :-)
This can be easily fixed in Raku: the BEGIN statement can also be used as a
prefix:
BEGIN my $lib_loc = $*PROGRAM.parent.add('../lib');
use lib "$lib_loc";
One note: I'm a bit surprised of the mixture of OS dependent (../) and OS
independent (.parent) directory walking. I guess you meant:
$*PROGRAM.parent.parent.add("lib")
?
If so, you could shorten this with the "sibling" method to:
$*PROGRAM.parent.sibling("lib")
> I thought that this would fix the problem, but I see the same
> compile time error with it:
>
> BEGIN {
> my $lib_loc = $*PROGRAM.parent.add('../lib');
> use lib "$lib_loc";
> }
Inside the BEGIN block, it's just the same: the variable is defined, but not
initialized yet when the "use lib" is executed at compile time *inside* the
BEGIN block. Yes, it's compile times all the way down :-)
> Does that make sense to anyone? It feels like a bug to me.
This is not a bug.
It's a misunderstanding of the phases through which a program goes when it is
being compiled and run. This is not different from Perl, BTW. The only thing
different from Perl (which is a very nice improvement, I'd say) is that you can
use BEGIN as a prefix, so that it shares its scope with its surrounding scope.
This allows you to define *and* initialize a variable at compile time and have
it exist in the surrounding scope.
Liz