# Simple usage question reading a file

**URL:** <https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908>\
**Category:** General Usage\
**Created:** [June 24, 2018, 1:46pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908 "2018-06-24T13:46:35Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![mkretlow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkretlow/32/16295_2.png) [@mkretlow](https://discourse.julialang.org/u/mkretlow)\
**Post date:** [June 24, 2018, 1:46pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/1 "2018-06-24T13:46:35Z")

</div>

Hi all. I have a very simple code snippet and I can’t figure out why I get this error:

Simple text file to read: test.dat contains

```julia
Fred 50
Mike 51
Ida 52

```

Code:

```julia
f = open("test.dat")

i = 1

for ln in eachline(f)

    if i == 1
        desigA, numA = ln[1:8],ln[9:end]
    else
        desigB, numB = ln[1:8],ln[9:end]
    end

    if i > 1
        println(desigA, desigB)
    end

    i+= 1

end

```

I know I could work with regex, split, readdlm etc., but it has a certain reason why I use slicing of the string (fixed column format) and I think it is not connected to the problem I am pointing here.

Running this example code (with Julia 0.6.3) I got the error, that desigA is not defined (after iteration 1). Why?

ERROR: LoadError: UndefVarError: desigA not defined  
Stacktrace:  
[1] macro expansion at /home/mike/astwork/ast/astapp/moid/jul/test.jl:14 [inlined]  
[2] anonymous at ./:?

Thanks, Mike

---

<div class="post-metadata">

**Author:** ![cormullion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cormullion/32/49131_2.png) [@cormullion](https://discourse.julialang.org/u/cormullion)\
**Post date:** [June 24, 2018, 3:28pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/2 "2018-06-24T15:28:13Z")

</div>

Variable is out of scope when the loop finishes would be my guess.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 24, 2018, 3:41pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/3 "2018-06-24T15:41:35Z")

</div>

To elaborate on what @cormullion said: you can simplify to reproduce the same problem with

```julia
for i in 1:3
    if i == 1
        desigA = true
    else
        desigB = true
    end
    if i > 1
        println(desigA, desigB)
    end
end

```

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [June 24, 2018, 3:44pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/4 "2018-06-24T15:44:35Z")

</div>

The name `desigA` only lives inside the first `if` clause. If you want it to be visible from the function scope, give it some value in that scope:

```julia
for (i, ln) in enumerate(eachline(f))
    desigA = desigB = ""
    if i == 1
        desigA, numA = ln[1:8],ln[9:end]
    else
        desigB, numB = ln[1:8],ln[9:end]
    end

    if i > 1
        println(desigA, desigB)
    end
end

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [June 24, 2018, 4:04pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/5 "2018-06-24T16:04:21Z")

</div>

No `desigA` does **NOT** only live inside the `if`. It does, however, only live in each iteration of the `for`. It is correct that in order for it to live outside the `for` loop you have to declare it in that (function or global) scope, though you code does not do that.

You also don’t need to give it a value, just use `local desigA, desigB` in the function scope is enough if the code is actually in a function. Otherwise, the outer scope of the loop will be the global scope and you need to use `global desigA, desigB` inside the loop body to make sure the global variables are used.

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [June 24, 2018, 4:05pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/6 "2018-06-24T16:05:31Z")

</div>

There’s no faster way to get a right answer than posting the wrong one! Thanks for the insights.

---

<div class="post-metadata">

**Author:** ![mkretlow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkretlow/32/16295_2.png) [@mkretlow](https://discourse.julialang.org/u/mkretlow)\
**Post date:** [June 24, 2018, 4:08pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/7 "2018-06-24T16:08:39Z")

</div>

But the print command is inside the loop. The same code as Python works like I expect it:

```julia
f = open("test.dat")

i = 1

for ln in f:

    if i == 1:
        desigA,numA = ln[0:7],ln[8:]
    else:
        desigB,numB = ln[0:7],ln[8:]

    if i > 1:
        print(desigA, desigB)

    i+= 1

```

```julia
python test.py 
Fred Mike   
Fred Ida    

```

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [June 24, 2018, 4:19pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/8 "2018-06-24T16:19:46Z")

</div>

Julia’s variable-scoping is different from Python’s in this instance: variables inside the for loop are freshly allocated at each iteration, and when an `if` clause isn’t evaluated for a particular iteration, any variable that’s only defined by that clause won’t exist for that iteration.

[https://docs.julialang.org/en/v0.6.2/manual/variables-and-scoping/#For-Loops-and-Comprehensions-1](https://docs.julialang.org/en/v0.6.2/manual/variables-and-scoping/#For-Loops-and-Comprehensions-1)

edit: per the manual, `while` blocks behave like Python `for` blocks in this respect:

```julia
i = 1
while !eof(f)
    ln = readline(f)
    
    if i == 1
        desigA, numA = ln[1:8],ln[9:end]
    else
        desigB, numB = ln[1:8],ln[9:end]
    end
    
    if i > 1
        println(desigA, desigB)
    end
    
    i += 1
end

```

---

<div class="post-metadata">

**Author:** ![mkretlow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkretlow/32/16295_2.png) [@mkretlow](https://discourse.julialang.org/u/mkretlow)\
**Post date:** [June 24, 2018, 4:35pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/9 "2018-06-24T16:35:22Z")

</div>

Wow, this is strange IMHO. Using the for loop my code cannot work, even with the globale/local keyword it doesn’t work because after the first iteration the value of desigA is lost forever. desigA (and numA) is set by the first line of the data file. Of course it can be read and set by a single statement before the loop.

Your solution with the while loop works like the Python code (BTW: and like I expected it).

Thanks for this good explanation and demonstrative example!

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [June 24, 2018, 4:43pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/10 "2018-06-24T16:43:53Z")

</div>

Reading the first line before the loop body is a lot cleaner, and it sidesteps the scoping issue:

```julia
ln = readline(f)
desigA, numA = ln[1:8],ln[9:end]

for ln in eachline(f)
    desigB, numB = ln[1:8],ln[9:end]
    println(desigA, desigB)
end

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [June 24, 2018, 5:06pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/11 "2018-06-24T17:06:25Z")

</div>

It appears that you did not add the local or global to the right place.

> [@yuyichao](#):
>
> use `local desigA, desigB` in the function scope is enough if the code is actually in a function

> [@yuyichao](#):
>
> use `global desigA, desigB` inside the loop body

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [June 24, 2018, 5:07pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/12 "2018-06-24T17:07:52Z")

</div>

Please don’t give a workaround to a non-issue. This is obviously not the right solution to solve the scope issue.

---

<div class="post-metadata">

**Author:** ![mkretlow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkretlow/32/16295_2.png) [@mkretlow](https://discourse.julialang.org/u/mkretlow)\
**Post date:** [June 24, 2018, 5:51pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/13 "2018-06-24T17:51:53Z")

</div>

I think I had the global/local statements at the right place but I didn’t defined the variables in the outer scope (you wrote: “You also don’t need to give it a value,…”), it was a misunderstanding by me. It is not necessary to give them a value, but necessary to “declare” them, e.g. desigA = … = “”. And neither in the global scope nor in the function scope it seems to be necessary to use global desigA, desigB or local local desigA, desigB.

So JUST putting the line: desigA = numA = desigB = numB = “” in the initial code I have posted is sufficient to fix the problem. Doesn’t matter if this script is in the global context or you put everything into a function, then you have also to initialize this variables (outside the loop).

```julia
desigA = numA = desigB = numB = ""

#function loop()
#desigA = numA = desigB = numB = ""

f = open("test.dat")
i = 1

for ln in eachline(f)

    if i == 1
        desigA, numA = ln[1:8], ln[9:end]
    else
        desigB, numB = ln[1:8], ln[9:end]
    end

    if i > 1
        println("$desigA $desigB")
    end

    i+= 1

end

#end
#loop()

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [June 24, 2018, 6:58pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/14 "2018-06-24T18:58:19Z")

</div>

> [@mkretlow](#):
>
> but necessary to “declare” them, e.g. desigA = … = “”

This is giving them values. Declaring them is just

> [@yuyichao](#):
>
> use `local desigA, desigB` in the function scope

> [@mkretlow](#):
>
> So JUST putting the line: desigA = numA = desigB = numB = “” in the initial code I have posted is sufficient to fix the problem.

If declaring works, of course assigning unnecessary values also works. If you don’t mind the extra work, that’s certainly fine.

> [@mkretlow](#):
>
> Doesn’t matter if this script is in the global context or you put everything into a function

They don’t work the same and that’s why the global version is deprecated on 0.7.

> [@mkretlow](#):
>
> then you have also to initialize this variables (outside the loop).

No you don’t have to, just declaring the variable is fine.

---

<div class="post-metadata">

**Author:** ![mkretlow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkretlow/32/16295_2.png) [@mkretlow](https://discourse.julialang.org/u/mkretlow)\
**Post date:** [June 24, 2018, 7:53pm UTC](https://discourse.julialang.org/t/simple-usage-question-reading-a-file/11908/15 "2018-06-24T19:53:31Z")

</div>

OK, thanks for the explanations. Now I got it right both using the global and the local scope variant.
