Include mystery

#1

I have two files. The first includes the second. The compiler complains about the variable var not being defined in the second file. Why?

First file:

function a()
	var = 1;
	include("b.jl")
end
a()

Second file:

@show var

When I run include("a.jl") I get:

ERROR: LoadError: LoadError: UndefVarError: var not defined               
Stacktrace:           
...
0 Likes

#2

Because things are evaluated into global scope (where there is no var).

2 Likes

#3

I’m not sure I follow. I thought that the compiler would simply slurp the contents of the included file.
Evaluation of include("a.jl") goes through without a hitch. But then when I run, there is the error.
I find that confusing. I thought the embedded file b.jl would simply become part of the code that defines the function a?

EDIT: Actually I meant evaluation of

function a()
	var = 1;
	include("b.jl")
end

This works with no problems.

0 Likes

#4

https://docs.julialang.org/en/v1/base/base/#Base.include

Evaluate the contents of the input source file in the global scope

Include is just another function. You’re not running it by defining the function.

2 Likes

#5

I think I’m beginning to see the light. The compiler doesn’t actually copy the contents
of the included file into the function, but does this:

julia> @code_lowered a()                                                  
CodeInfo(                                                                 
1 ─      var = 1                                                          
│        (Main.include)("b.jl")                                           
│   %3 = Main.hey                                                         
│        value = %3                                                       
│   %5 = (Base.repr)(%3)                                                  
│        (Base.println)("hey = ", %5)                                     
└──      return value                                                     
)   

In other words, the inclusion of the file is in the code of a.

0 Likes

#6

What can I say, that was a wrong assumption. It parses it and evaluates the expression (and evals go into the current global scope unless given another module).

0 Likes

#7

So is there any way I could get that behavior: I am motivated by having a piece of code that I would like to incorporate into multiple pieces “by inclusion” instead of by defining a function and calling that function?
I suppose I am looking for a macro?

0 Likes

#8

It has a macro for this.

0 Likes

#9

Good find. No mystery after all :slight_smile: Thanks.

0 Likes

#10

This misconception probably isn’t entirely your doing. Folks (maybe including myself?) have often talked about include as a “copy-pasting” of code when discouraging others from trying to use it as a pseudo-packaging mechanism. It may be worth trying to steer away from that mental model.

0 Likes

#11

Indeed, you’re right. That’s the soundbite I remembered.

0 Likes

#12

I must confess to being tripped up by misunderstanding exactly what include does. Indeed, I think it is a common misconception.

I can’t help but feel that it is partly due to the name include which might be associated with pre-processor directives in other languages. And it is commonly used for the same or similar functionality.

For me the name eval_file would help remind me that it is a normal function executed at run time and which evals the contents of the file (in global scope since it is a normal function). Similarly, include_string could be named eval_string.

1 Like