7

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?

Elizabeth Mattijsen
  • 25,654
  • 3
  • 75
  • 105
rajashekar
  • 3,460
  • 11
  • 27

2 Answers2

10

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.

Jonathan Worthington
  • 29,104
  • 2
  • 97
  • 136
5

Looks to me it's a combination of 2 things: 1. subroutine some-routine isn't exported, and 2. problems with scoping in the REPL.

The first can be fixed in two ways:

our sub some-routine() {

or

sub some-routine() is export {

The second is, in the current state of the REPL, not really fixable (and I have tried, but all of my fixes introduced problems in other situations). The REPL is currently implemented as doing an EVAL on every line you enter, while attempts are made to share elements of any previous EVAL with the next. In the current state of the runtime, it is impossible to do that sharing completely, which is the cause of many of the issues that people report about the REPL.

Work on the RakuAST branch also implies having the state of an interpreter to be more "objectified" if you will, allowing for a better state sharing between EVALs, and thus a better REPL. But that will take at least another few months before that lands in Rakudo.

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