# Clarification on Hard Scope within functions and function arguments

**URL:** https://discourse.julialang.org/t/clarification-on-hard-scope-within-functions-and-function-arguments/96044
**Category:** New to Julia
**Tags:** question, scope
**Created:** [March 14, 2023, 10:18am UTC](https://discourse.julialang.org/t/clarification-on-hard-scope-within-functions-and-function-arguments/96044 "2023-03-14T10:18:11Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![phantom](https://avatars.discourse-cdn.com/v4/letter/p/e0b2c6/32.png) [@phantom](https://discourse.julialang.org/u/phantom)
#### Post date: [March 14, 2023, 10:18am UTC](https://discourse.julialang.org/t/clarification-on-hard-scope-within-functions-and-function-arguments/96044/1 "2023-03-14T10:18:11Z")

</div>

I’m sure I am missing something simple here so I apologize in advance. But I am a little confused as to why this first assignment works.

```julia
using Dates

julia> function currentmin(minute = minute(now()))
              minute
              end
currentmin (generic function with 2 methods)

julia> currentmin()
22

```

whereas this one returns an error

```julia
julia> function currentmin1()
              minute = minute(now())
              end
currentmin1 (generic function with 1 method)

julia> currentmin1()
           
ERROR: UndefVarError: minute not defined

```

According to the documentation on [scope](https://docs.julialang.org/en/v1/manual/variables-and-scoping/), functions introduce a **Hard scope:** If `x` is _not already a local variable_ and assignment occurs inside of any hard scope construct (i.e. within a `let` block, function or macro body, comprehension, or generator), a new local named `x` is created in the scope of the assignment.

I thought maybe the assignment worked in `currentmin` because `minute` technically hadn’t been called until the assignment was made. But then why doesn’t it work for `currentmin1`?

Even if the arguments of the function are being made outside the hard scope of the function shouldn’t the assignment still fail because of the global scope of the module?

```julia
using Dates

julia> minute = 45

ERROR: cannot assign a value to variable Dates.minute from module Main

```

---

<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: [March 14, 2023, 11:43am UTC](https://discourse.julialang.org/t/clarification-on-hard-scope-within-functions-and-function-arguments/96044/2 "2023-03-14T11:43:04Z")

</div>

As far as I understand you can interpret the function parameter as this:

```julia
julia> x = 1
1

julia> f = let x = x
           x += 1
       end
2

julia> x
1

# the same as:
julia> x = 1
1

julia> g(x=x) = x += 1
g (generic function with 2 methods)

julia> g(x)
2

julia> x
1

```

meaning that the left side of the parameter assignment defines a variable local to the scope of the function, the right side is the global (or outer scope) variable. Thus, in your first function, the left side `minute` is a variable local to the scope of the function, the right side `minute` is a reference to the global `minute` function.

In your second example there is an ambiguity which raises an error, because you are assigning a local variable name and trying to call a function with the same label.

---

<div class="post-metadata">

### Author: ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)
#### Post date: [March 15, 2023, 8:38am UTC](https://discourse.julialang.org/t/clarification-on-hard-scope-within-functions-and-function-arguments/96044/3 "2023-03-15T08:38:33Z")

</div>

This is a well written explanation, which I was searching for yesterday, but all I was able to create was overly complex and even not understandable by myself 🙂

But I still want to add that this

> [@lmiq](#):
>
> left side of the parameter assignment defines a variable local to the scope of the function, the right side is the global (or outer scope) variable.

and this

> [@lmiq](#):
>
> second example there is an ambiguity which raises an error

can be easily shown by the code itself:

```julia
julia> @code_lowered currentmin()
CodeInfo(
1 ─ %1 = Main.now()
│ %2 = Main.minute(%1)
│ %3 = (#self#)(%2)
└── return %3
)

```

You see the call to `Main.minute(...)` versus in

```julia
julia> @code_lowered currentmin1()
CodeInfo(
1 ─ %1 = Main.now()
│ %2 = (minute)(%1)
│ minute = %2
└── return %2
)

```

where only local identifiers `minute` exist, with the ambiguity of it.  
The parser can do it right, as you probably expected it, with e.g.:

```julia
julia> function currentmin2()
          m = minute(now())
       end

julia> @code_lowered currentmin2()
CodeInfo(
1 ─ %1 = Main.now()
│ %2 = Main.minute(%1)
│ m = %2
└── return %2
)

```

Still, there is the question, that the parser could do it right for `currentmin1()` because the first usage of identifier `minute` must be the function `Main.minute(...)`, so why isn’t it happening like that?

I don’t know if it is as it is by purpose, but I think it is good, that an error is raised, because more complex functions can easily be a nightmare to debug if the parser tries to be overly smart in such cases.

---

<div class="post-metadata">

### Author: ![phantom](https://avatars.discourse-cdn.com/v4/letter/p/e0b2c6/32.png) [@phantom](https://discourse.julialang.org/u/phantom)
#### Post date: [March 15, 2023, 9:11am UTC](https://discourse.julialang.org/t/clarification-on-hard-scope-within-functions-and-function-arguments/96044/4 "2023-03-15T09:11:07Z")

</div>

Thanks! Really appreciate both your explanations! It took me awhile to really understand the dynamic but it really clears up a lot in terms of how the function arguments are being defined.

@oheil just to clarify I am reading this correctly when @code\_lowered returns an identifier in parenthesis followed by the identifier without as in as in `(minute)` `,minute` here

> [@oheil](#):
>
> ```julia-auto
> julia> @code_lowered currentmin1()
> CodeInfo(
> 1 ─ %1 = Main.now()
> │ %2 = (minute)(%1)
> │ minute = %2
> └── return %2
> )
> 
> ```

this means that there is an ambiguity which will raise an error?

---

<div class="post-metadata">

### Author: ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)
#### Post date: [March 15, 2023, 10:01am UTC](https://discourse.julialang.org/t/clarification-on-hard-scope-within-functions-and-function-arguments/96044/5 "2023-03-15T10:01:32Z")

</div>

The paranthesis around `(minute) ` don’t mean anything, it’s the same as

```julia
minute(%1)

```

and means call to function `minute(...)`. Don’t know why they are there.  
The ambiguity is not visible here, but the parser has seen the ambiguity and has decided to put a

```julia
minute(...)

```

instead of

```julia
Main.minute(...)

```

because, and this is a guess, the parser choose to use all identifiers `minute` as local, as it is a local variable, despite the obvious call to a global function. This is not mandatory, as you can see in `currentmin2()`, but it would mean, that the parser would need to differentiate between identifiers as variables and identifiers as functions. I don’t know if it is differentiated or how parsing works in this case.  
Anyways, the outcome is good in this case, as it helps to avoid using identifier `minute` as a variable name here.

By the way, the Dates API is more to using `minute()` as `Dates.minute()`. This is the way as it is used throughout the documents. The best way is sticking to the docs, like:

```julia
julia> function currentmin1()
            minute = Dates.minute(now())
       end

julia> @code_lowered currentmin1()
CodeInfo(
1 ─ %1 = Dates.minute
│ %2 = Main.now()
│ %3 = (%1)(%2)
│ minute = %3
└── return %3
)

```
