Search code examples
evalrakurakudo

Class symbol introduction due to EVALFILE


Class names are available in scope after EVALFILE, while the documentation may have stated otherwise.

The documentation for EVALFILE states:

Slurps the specified file and evaluates it. Behaves the same way as EVAL with regard to Blob decoding, scoping, the $lang parameter and the $check parameter. Evaluates to the value produced by the final statement in the file when $check is not True.

The documentation for EVAL states:

since the set of symbols in a lexical scope is immutable after compile time, an EVAL can never introduce symbols into the surrounding scope.

My input file is:

class SomeClass {
    method a () { "In SomeClass method a"; };
}

sub some-routine () {
    "Some routine";
}
> my $f = EVALFILE("/tmp/eval-bug.raku");
&some-routine

> $f()
Some routine

> some-routine()
===SORRY!=== Error while compiling:
Undeclared routine:
    some-routine used at line 1

The above three executions comply with the documentation, but the following does not:

> SomeClass.a()
In SomeClass method a

So does symbol mean only a routine name and not a class name? Or is this a bug?


Solution

  • since the set of symbols in a lexical scope is immutable after compile time, an EVAL can never introduce symbols into the surrounding scope

    The key words here are "lexical scope". Classes, however, are not lexically scoped by default (unlike routines), but rather package scoped. This means that they introduce a global name by default. If you instead write:

    my class SomeClass {
        method a () { "In SomeClass method a"; };
    }
    

    Then this declares a lexically scoped class, no global name will be introduced, and thus it will not be installed anywhere that persists beyond the EVALFILE.

    To me at least the documentation seems correct; it explicitly mentions lexical scope, and the words "surrounding scope" also carry the implication of textual (thus lexical) scoping. However, it could gain a mention that package-scoped things declared in the EVALFILE will be installed globally.