# Placing variables in array makes a copy of the variables?

**URL:** <https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397>\
**Category:** General Usage\
**Tags:** question\
**Created:** [October 7, 2021, 9:30pm UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397 "2021-10-07T21:30:29Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [October 7, 2021, 9:30pm UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397/1 "2021-10-07T21:30:30Z")

</div>

Maybe this is a scoping issue? I am trying to define defaults in an outer constructor by looping over a list of variables and setting defaults if they are `NaN` as follows:

```julia
julia> struct S x::Float64 end

julia> function S1(;x::Float64 = NaN) 
         args = [x]
         for arg in args
           if isnan(arg)
             arg = 4
           end
         end
         @info x, args[1], args[1] === x
         S(x)
       end
S1 (generic function with 1 method)

julia> S1()
[ Info: (NaN, NaN, true)
S(NaN)

```

I would expect to get back `S(4)`. So I tried:

```julia
julia> function S2(;x::Float64 = NaN) 
         args = [x]
         for i in 1:length(args)
           if isnan(args[i])
             args[i] = 4
           end
         end
         @info x, args[1], args[1] === x
         S(x)
       end
S2 (generic function with 1 method)

julia> S2()
[ Info: (NaN, 4.0, false)
S(NaN)

```

which gets me one step closer? Not looping over a vector of `args` works:

```julia
julia> function S3(;x::Float64 = NaN) 
         if isnan(x) x = 4 end 
         S(x)
       end
S3 (generic function with 1 method)

julia> S3()
S(4)

```

So a couple questions: why doesn’t `for arg in args` work the same as indexing into the `args` array? And why is `args = [x]` making a copy of `x`? Or I assume that is my issue (big shrug)???

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [October 7, 2021, 9:40pm UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397/2 "2021-10-07T21:40:45Z")

</div>

`[x]` does _not_ make a copy of `x`.

Rather, inside the for loop, `arg` is just a variable named assigned to elements of `x`. By writing `arg = 4`, you are just assigning the variable name, which only exists inside the scope of that loop, to `4`. In a sense, `arg` forgets that it was ever assigned to elements of `args`.

For the second example, you are just filling in the `ith` entry of `args` with `4`. This does not modify `x` in any way.

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [October 7, 2021, 10:43pm UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397/3 "2021-10-07T22:43:46Z")

</div>

> [@pdeffebach](#):
>
> elements of `x`

I think you meant `[x]`` because `x``` is a Float64 in the OP’s code, so it has no elements.

Somehow OP expects changing the contents of `args` aka `[x]` should change the value of the x variable, as if the Vector contained a pointer to x. `[x]` does make a copy of the value of `x` in a different location in memory.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 8, 2021, 12:12am UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397/4 "2021-10-08T00:12:00Z")

</div>

> [@nlaws](#):
>
> (big shrug)???

ok.

`NaN` is a immutable, actually, it’s a (compiler) constant, but what’s more important is Julia does pass-by-sharing.

```julia
julia> x = 3
3

julia> function f(_x)
           _x = 10
           return nothing
       end
f (generic function with 1 method)

julia> x
3 # would you expect 10 here?

```

or maybe another example:

```julia
julia> xs = [3]
1-element Vector{Int64}:
 3

julia> xs[1] = 4;

julia> 3
3 # would you expect 4 here?

```

This may also be a helpful reading:

> <https://stackoverflow.com/questions/58150295/how-to-pass-an-object-by-reference-and-value-in-julia>

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [October 8, 2021, 1:17am UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397/5 "2021-10-08T01:17:39Z")

</div>

Definitely not a scoping issue.

---

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [October 8, 2021, 3:32am UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397/6 "2021-10-08T03:32:05Z")

</div>

Ok I think that I get what’s going on: the vector is getting the value of `x` but not the pointer to `x`, so it _is_ copying `x` when I put it in an array, right? How do I create a vector of variable pointers so that I can loop over them, and change their values (conditionally, based on their values like the examples)?

And why doesn’t the `for arg in args` provide pointers to the values in `args`? (What use does `for arg in args` have if it is creating a new variable `arg` that is unrelated to `args`?)

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 8, 2021, 3:36am UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397/7 "2021-10-08T03:36:19Z")

</div>

> [@nlaws](#):
>
> copying `x` when I put it in an array, right

not quite, immutables can often be stack-allocated, so “copying” is not a good picture IMO. When you write `x=3`, 3 is constant in source code (i.e. hard-coded at LLVM/asm level), you don’t think of it as “copy” since it never got address on heap. `x` is not a pointer of Int64

> [@nlaws](#):
>
> why doesn’t the `for arg in args` provide pointers to the values in `args`

please read that SO post I posted above, it should then be clear what’s pass-by-sharing and how is that different from pass by reference (as in C++)

> [@nlaws](#):
>
> How do I create a vector of variable pointers

the closest you can get is `Ref()` but this is an anti-pattern for most part, just return the values from function when you’re dealing with scalars like this.

---

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [October 8, 2021, 3:45am UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397/8 "2021-10-08T03:45:04Z")

</div>

Thank you @jling but I did read the SO post and I understand pass-by-sharing vs. pass-by-reference, but I don’t see how that explains the `for arg in args`, unless I should think of `for` as a function that I’m passing something to?

Is there any way to loop over a vector of function keyword arguments and modify their values as needed?

I could write out individual blocks for each variable, e.g.

```julia
function outer_S_constructor(;x1::Float64=NaN, ..., xN::Float64=Nan)
    if isnan(x1)
        x1 = x1_default_that_depends_on_other_kwargs_so_I_cant_assign_it_in_function_signature
    end
    ...
    if isnan(xN)
        xN = xN_default_that_depends_on_other_kwargs_so_I_cant_assign_it_in_function_signature
    end
    S(x1, ..., xN)
end

```

But this is tedious and does not follow the DRY principle.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 8, 2021, 3:50am UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397/9 "2021-10-08T03:50:11Z")

</div>

> [@nlaws](#):
>
> `for arg in args`

you’re iterating over values:

```julia
julia> for i in 1:3
           @show i,typeof(i)
       end
(i, typeof(i)) = (1, Int64)
(i, typeof(i)) = (2, Int64)

```

there’s no connection back whatsoever, in fact `1:3` is immutable (and doesn’t even have `2` stored in it), forget about pointers, there are just values.

> [@nlaws](#):
>
> `;x1::Float64=NaN, ..., xN::Float64=Nan`

you can get all of your keyward arguments as a `NamedTuple`?

I’m not entirely sure what you _really_ want to do

---

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [October 8, 2021, 4:02am UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397/10 "2021-10-08T04:02:06Z")

</div>

Ah I see: `arg` is a value in `args` but does not point to the same value in `args`.

What I would like to do is loop over a vector of keyword arg pointers so that I can change their values. So my last example would become:

```julia
function outer_S_constructor(;x1::Float64=NaN, ..., xN::Float64=Nan, <some_other_kwargs...>)
    args_to_check = [x1, ..., xN]
    for arg in args_to_check
        if isnan(arg)
            arg = arg_default_that_depends_on_other_kwargs_so_I_cant_assign_it_in_function_signature
    end
    S(x1, ..., xN)
end

```

which we know does not work. Do I change `args_to_check` to `[Ref(x1), ..., Ref(xN)]` ? If so, how do I check the value of each reference in `args_to_check`?

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 8, 2021, 4:03am UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397/11 "2021-10-08T04:03:45Z")

</div>

> [@nlaws](#):
>
> ```julia
> args_to_check = [x1, ..., xN]
> for arg in args_to_check
> if isnan(arg)
> 
> ```

if we start with this, a common pattern is:

```julia
julia> a = [1,2,3,4]
4-element Vector{Int64}:

julia> for (i, v) in enumerate(a)
           if iseven(v)
               a[i] = 0
           end
       end

julia> a
4-element Vector{Int64}:
 1
 0
 3
 0

```

* * *

also btw, you can `splat` in the end to reduce typing:

```julia
S(args_to_check...)

```

also you can make function definition such as `S(...; kwargs...)` and then you don’t have to type a whole bunch of x1, x2. (although in this case you want to check length and what’s in `kwargs` first

---

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [October 8, 2021, 4:20am UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397/12 "2021-10-08T04:20:43Z")

</div>

Ok now I see that I will need to unpack `args_to_check` into the struct `S` and I cannot use the keywords to fill out `S` since `args_to_check` contains pointers different from the keywords (such as `x1`).

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 8, 2021, 4:22am UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397/13 "2021-10-08T04:22:46Z")

</div>

> [@nlaws](#):
>
> `args_to_check` contains pointers

no, it doesn’t, there’s no pointer, really, pointer (as in C++) is not a useful concept in normal Julia code. (internally there are pointer to be used to for passing to `ccall()` but this is not one of those cases)

If you want to think of `x1` as a pointer as synonymous with a label, it’s fine, but just note you can’t rewrite “`x1`’s content/data it points to” when you pass `x1` to a function (or when you iterate over an array that contains `x1`) – because all you get is a value, when `x1` is an immutable/scalar. Again, this is what pass-by-sharing entails.

---

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [October 8, 2021, 2:43pm UTC](https://discourse.julialang.org/t/placing-variables-in-array-makes-a-copy-of-the-variables/69397/14 "2021-10-08T14:43:51Z")

</div>

Just want to add my solution in the end: I am using a dictionary because I want to keep argument labels in order to reference the argument values

```julia
function outer_S_constructorouter_S_constructor(;x1::Float64=NaN, ..., xN::Float64=Nan, <some_other_kwargs...>)
    args_to_check = Dict(
        :x1 => x1,
        ...
        :xN => xN
    )
    for (key, val) in args_to_check
        if isnan(val)
           args_to_check[key] = arg_default_that_depends_on_other_kwargs_so_I_cant_assign_it_in_function_signature
        end
    end
    S(
        args_to_check[:x1],
        ...,
        args_to_check[:xN],
        ...,
        other_args
    )
end
```
