> On 11 Jul 2021, at 01:11, Joseph Brenner <doom...@gmail.com> 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

Reply via email to