# Creating a function that does not import outer scope variables

**URL:** <https://discourse.julialang.org/t/creating-a-function-that-does-not-import-outer-scope-variables/84481>\
**Category:** General Usage\
**Tags:** question, module, scope\
**Created:** [July 19, 2022, 5:11pm UTC](https://discourse.julialang.org/t/creating-a-function-that-does-not-import-outer-scope-variables/84481 "2022-07-19T17:11:36Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![raphaelchinchilla](https://avatars.discourse-cdn.com/v4/letter/r/bbce88/32.png) [@raphaelchinchilla](https://discourse.julialang.org/u/raphaelchinchilla)\
**Post date:** [July 19, 2022, 5:11pm UTC](https://discourse.julialang.org/t/creating-a-function-that-does-not-import-outer-scope-variables/84481/1 "2022-07-19T17:11:36Z")

</div>

Julia allows functions to see variables outside of their scope, something like

```julia
y=2
function f(x)
   x+y
end

```

I agree this can often be useful, but for me this is generally a source of bugs. A typical error that I do is

```julia
y=2
function f(x)
   y\hat=4
   x+y # I wrote y but I had intended my code to use y\hat   
end

```

This kind of error is terribly hard to catch, specially when `y` and `y\hat` are similar, which they tend to be. Is there a way to define a function such that variables can only be used if they are explicitely passed as arguments (or if they are `const`)? I tried to use `let` block, but in that case the defined function stayed in that local scope and I could not use it.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [July 19, 2022, 5:18pm UTC](https://discourse.julialang.org/t/creating-a-function-that-does-not-import-outer-scope-variables/84481/2 "2022-07-19T17:18:16Z")

</div>

Perhaps you could enclose the function in a `baremodule` and then import that method into your desired module.

[https://docs.julialang.org/en/v1/base/base/#baremodule](https://docs.julialang.org/en/v1/base/base/#baremodule)

```julia
julia> x = 5
5

julia> baremodule Foo
           f() = x
       end
Main.Foo

julia> import .Foo: f

julia> f()
ERROR: UndefVarError: x not defined

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [July 19, 2022, 5:28pm UTC](https://discourse.julialang.org/t/creating-a-function-that-does-not-import-outer-scope-variables/84481/3 "2022-07-19T17:28:39Z")

</div>

A standard module does the same, doesn’t it?

```julia
julia> x = 1
1

julia> module A
           f() = x
       end
Main.A

julia> A.f()
ERROR: UndefVarError: x not defined
Stacktrace:
 [1] f()
   @ Main.A ./REPL[2]:2
 [2] top-level scope
   @ REPL[3]:1

```

Maybe the advice here is the basic one: don’t use global variables (in this case, within the module being developed), or at least keep them to a minimum, to avoid this kind of scoping confusions.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [July 19, 2022, 5:45pm UTC](https://discourse.julialang.org/t/creating-a-function-that-does-not-import-outer-scope-variables/84481/4 "2022-07-19T17:45:20Z")

</div>

> [@lmiq](#):
>
> A standard module does the same, doesn’t it?

Yes, for `x`. I was thinking he might want as complete namespace isolation as possible. In a regular `module` you still have imports from `Base`. For example, `π`.

```julia
julia> module Foo
           f() = π
       end
Main.Foo

julia> Foo.f()
π = 3.1415926535897...

julia> baremodule Bar
           f() = π
       end
Main.Bar

julia> Bar.f()
ERROR: UndefVarError: π not defined

```

---

<div class="post-metadata">

**Author:** ![raphaelchinchilla](https://avatars.discourse-cdn.com/v4/letter/r/bbce88/32.png) [@raphaelchinchilla](https://discourse.julialang.org/u/raphaelchinchilla)\
**Post date:** [July 19, 2022, 10:18pm UTC](https://discourse.julialang.org/t/creating-a-function-that-does-not-import-outer-scope-variables/84481/5 "2022-07-19T22:18:33Z")

</div>

I think that a `(bare)module` is more restrictive than what I want, because I want to be able to call other functions from inside the function I defined. I could pass as a parameter to the function in the module other functions, but then it becomes a little bit too much I think.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [July 20, 2022, 2:24am UTC](https://discourse.julialang.org/t/creating-a-function-that-does-not-import-outer-scope-variables/84481/6 "2022-07-20T02:24:46Z")

</div>

You just need to import exactly what you want to use. Otherwise, the answer is simply do not use globals variables at all. Use a `let` block to create a local scope instead of assigning to a global variable.

```julia
let y=2
    # do something with y
    println(y)
end
function f(x)
    y\hat=4
    x+y # I wrote y but I had intended my code to use y\hat   
end

```

---

<div class="post-metadata">

**Author:** ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)\
**Post date:** [July 20, 2022, 5:49am UTC](https://discourse.julialang.org/t/creating-a-function-that-does-not-import-outer-scope-variables/84481/7 "2022-07-20T05:49:05Z")

</div>

The info that `f` uses a global can be accessed like:

```julia
julia> y = 2
2

julia> function f(x)
           x+y
       end
f (generic function with 1 method)

julia> code_typed(f, (Any,))[1]
CodeInfo(
1 ─ %1 = Main.y::Any
│ %2 = (x + %1)::Any
└── return %2
) => Any

```

so one option might be to write a macro like `@noglobals function f(x) ...` which defines the function, then calls `code_typed` on it with some valid set of argument types and crawls the codeinfo object to determine a global was used then errors. Its tricky though because if you call other functions like `x + sin(y)` you’ll get a `Main.sin` “global” in there so you’d have to differentiate that, assuming you want to allow it.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [July 20, 2022, 9:52am UTC](https://discourse.julialang.org/t/creating-a-function-that-does-not-import-outer-scope-variables/84481/8 "2022-07-20T09:52:26Z")

</div>

Alternatively, the `@noglobals` macro could identify all the variables and add unassigned `local` statements for them, so if a variable is never assigned, the method call would throw an `UndefVarError` instead of accessing a global variable. It wouldn’t require providing argument types to narrow down the call for inference, but it might be tricky making sure the `local` statements don’t change the method’s behavior. For example, you wouldn’t want to put `local x` inside a `for`-loop that accesses an outer local `x` just because the macro found an `x` in the block.
