# How to return in-place two variables from fetch?

**URL:** <https://discourse.julialang.org/t/how-to-return-in-place-two-variables-from-fetch/92880>\
**Category:** General Usage\
**Tags:** question\
**Created:** [January 12, 2023, 3:29pm UTC](https://discourse.julialang.org/t/how-to-return-in-place-two-variables-from-fetch/92880 "2023-01-12T15:29:28Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Amro](https://avatars.discourse-cdn.com/v4/letter/a/4491bb/32.png) [@Amro](https://discourse.julialang.org/u/Amro)\
**Post date:** [January 12, 2023, 3:29pm UTC](https://discourse.julialang.org/t/how-to-return-in-place-two-variables-from-fetch/92880/1 "2023-01-12T15:29:29Z")

</div>

I have two issues please:  
1- How can I mutate in-place `x_1`&`x_2` by the returns of `fetch` ( `Z` and `Y` ) to avoid the below error?

```julia
A = [1,2,3,4,5]
x_1 = zeros(5); x_2 = zeros(5);
thr = Threads.@spawn begin
  Z = A .+ 1;
  Y = A .+ 2;
  Z, Y
end
x_1, x_2 = fetch(thr); # it works
x_1, x_2 .= fetch(thr); # it gives error
ERROR: MethodError: no method matching copyto!(::Tuple{Vector{Int64}, Vector{Int64}}, ::Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple}, Tuple{Base.OneTo{Int64}}, typeof(identity), Tuple{Tuple{Vector{Int64}, Vector{Int64}}}})
Closest candidates are:

```

2- Another issue related to variable scope. Why `Z`&`Y` were not updated in the snippet code in case-1 while they were updated when the code was put in function `f` in case-2?

```julia
# Case-1
##### snippet Code
Z = zeros(5); Y = zeros(5);
thr = Threads.@spawn begin
  Z = A .+ 1;
  Y = A .+ 2;
end
fetch(thr)
# Here Z,Y are not updated (still zeros)
##### snippet Code

# Case-2
function f(A)
  ##### snippet Code
  Z = zeros(5); Y = zeros(5);
  thr = Threads.@spawn begin
    Z = A .+ 1;
    Y = A .+ 2;
  end
  fetch(thr)
  # Here Z,Y are updated
  ##### snippet Code
  Z, Y  
end
Z, Y = f(A)

```

---

<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:** [January 12, 2023, 5:24pm UTC](https://discourse.julialang.org/t/how-to-return-in-place-two-variables-from-fetch/92880/2 "2023-01-12T17:24:11Z")

</div>

The `@spawn` introduces a local scope block, if you want to assign to globals from local scopes, you need to use `global` to do so. But ideally, don’t assign to globals at all. Note that you are not mutating `Y` and `Z` but reassigning newly allocated arrays to those bindings.

---

<div class="post-metadata">

**Author:** ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)\
**Post date:** [January 12, 2023, 5:24pm UTC](https://discourse.julialang.org/t/how-to-return-in-place-two-variables-from-fetch/92880/3 "2023-01-12T17:24:25Z")

</div>

Your first problem has nothing to do with threads or `fetch`. The error tells you that the broadcast doesn’t know how to copy the contents of the right hand side, a tuple, into the left hand side, a tuple too. That makes sense because tuples are immutable.

Either stick with the assignment, or better yet, write your threaded code to update `x_1, x_2` in place.

> [@Amro](#):
>
> Why `Z`&`Y` were not updated in the snippet code in case-1 while they were updated when the code was put in function `f` in case-2?

Because `Y,Z` are local to the task created by `@spawn`. There is an anonymous function created that wraps the code. Within that function, e.g. `Z = ...` is a local assignment and shadows the global variable. You need to annotate with `global`

```julia
Z = zeros(5); Y = zeros(5);
thr = Threads.@spawn begin
  global Z = A .+ 1;
  global Y = A .+ 2;
end

```

The task created in the function on the other hand is actually a closure capturing the local `A,Y,Z`.

---

<div class="post-metadata">

**Author:** ![Amro](https://avatars.discourse-cdn.com/v4/letter/a/4491bb/32.png) [@Amro](https://discourse.julialang.org/u/Amro)\
**Post date:** [January 12, 2023, 6:46pm UTC](https://discourse.julialang.org/t/how-to-return-in-place-two-variables-from-fetch/92880/4 "2023-01-12T18:46:03Z")

</div>

Thanks for your reply.

> [@skleinbo](#):
>
> Either stick with the assignment, or better yet, write your threaded code to update `x_1, x_2` in place.

How can I update `x_1, x_2` in place in the threaded code?

> [@skleinbo](#):
>
> The task created in the function on the other hand is actually a closure capturing the local `A,Y,Z`.

So function `f` actually makes the locals of `Z,Y` inside the task created by `@spawn` seen in its scope, right?

---

<div class="post-metadata">

**Author:** ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)\
**Post date:** [January 13, 2023, 8:37am UTC](https://discourse.julialang.org/t/how-to-return-in-place-two-variables-from-fetch/92880/6 "2023-01-13T08:37:47Z")

</div>

```julia
julia> A = [1,2,3,4,5];

julia> x_1 = zeros(5); x_2 = zeros(5);

julia> function f!(Y,Z,A)
         Threads.@spawn begin
           Z .= A .+ 1;
           Y .= A .+ 2;
         end
       end
f! (generic function with 1 method)

julia> f!(x_1, x_2, A) |> wait

julia> x_1
5-element Vector{Float64}:
 3.0
 4.0
 5.0
 6.0
 7.0

```

---

<div class="post-metadata">

**Author:** ![Amro](https://avatars.discourse-cdn.com/v4/letter/a/4491bb/32.png) [@Amro](https://discourse.julialang.org/u/Amro)\
**Post date:** [January 13, 2023, 1:39pm UTC](https://discourse.julialang.org/t/how-to-return-in-place-two-variables-from-fetch/92880/7 "2023-01-13T13:39:49Z")

</div>

Ah, it is the same as using dot.  
Thank you very much for your reply.
