# Is calling \`x = @spawn f(x)\` a bad idea?

**URL:** <https://discourse.julialang.org/t/is-calling-x-spawn-f-x-a-bad-idea/89934>\
**Category:** General Usage\
**Tags:** multithreading\
**Created:** [November 8, 2022, 2:44pm UTC](https://discourse.julialang.org/t/is-calling-x-spawn-f-x-a-bad-idea/89934 "2022-11-08T14:44:22Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![artemsolod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/artemsolod/32/20704_2.png) [@artemsolod](https://discourse.julialang.org/u/artemsolod)\
**Post date:** [November 8, 2022, 2:44pm UTC](https://discourse.julialang.org/t/is-calling-x-spawn-f-x-a-bad-idea/89934/1 "2022-11-08T14:44:22Z")

</div>

I am a bit unclear on how and when variables are captured in `@spawn` call. For instance, the following errors

```julia
julia> using Base.Threads

julia> let x = 1
           x = @spawn x + 3
           fetch(x)
       end
ERROR: TaskFailedException
Stacktrace:
 [1] wait
   @ ./task.jl:349 [inlined]
 [2] fetch(t::Task)
   @ Base ./task.jl:369
 [3] top-level scope
   @ ./REPL[3]:3

    nested task error: MethodError: no method matching +(::Task, ::Int64)

```

Although I can not find it in the current docs, I remember some example using `$` when capturing variables. Trying it works

```julia
julia> let x = 1
           x = @spawn $x + 3
           fetch(x)
       end
4

```

I would appreciate if someone could post a reference to where the capturing logic is described. Thanks!

setup:  
ubuntu, julia 1.8.1

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [November 8, 2022, 2:58pm UTC](https://discourse.julialang.org/t/is-calling-x-spawn-f-x-a-bad-idea/89934/2 "2022-11-08T14:58:51Z")

</div>

Before any piece of code runs, macros are expanded. You can take a look at the `@macroexpand`ed version of your code to investigate why `x` is captured - if I remember correctly, `@spawn` just expands to an anonymous function, so the capturing rules should be the same.

---

<div class="post-metadata">

**Author:** ![Joseph\_Cognirobo](https://avatars.discourse-cdn.com/v4/letter/j/a3d4f5/32.png) [@Joseph\_Cognirobo](https://discourse.julialang.org/u/Joseph_Cognirobo)\
**Post date:** [November 13, 2022, 8:34am UTC](https://discourse.julialang.org/t/is-calling-x-spawn-f-x-a-bad-idea/89934/3 "2022-11-13T08:34:46Z")

</div>

The docs for [`@spawn`](https://docs.julialang.org/en/v1/base/multi-threading/#Base.Threads.@spawn) mention using `$` to interpolate variable values into the generated closure. If you look at the code, the macro gathers up all variables preceded by `$` into a `let` block around the task body. (The `@async` macro uses the same helper function).

In general, though, I would absolutely avoid reusing the variable like you have there. You can just put the `@spawn` inside the `fetch()` call if you want:

```julia
let x = 1
  fetch(@spawn $x + 3)
end

```

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [November 13, 2022, 9:17am UTC](https://discourse.julialang.org/t/is-calling-x-spawn-f-x-a-bad-idea/89934/4 "2022-11-13T09:17:01Z")

</div>

This still seems to be a bug, i.e., already when using closures:

```julia
julia> let x = 1; x = () -> x + 3; x() end
ERROR: MethodError: no method matching +(::var"#9#10", ::Int64)
Stacktrace:
 [1] (::var"#9#10")()
   @ Main ./REPL[46]:1
 [2] top-level scope
   @ REPL[46]:1

```

According to the docs, i.e., in particular _let always creates a new location_ and \*

```julia
help?> let
search: let delete! isletter deleteat! selectdim reflect! ismutabletype length

  let

  let statements create a new hard scope block and introduce new variable
  bindings each time they run. Whereas assignments might reassign a new value
  to an existing value location, let always creates a new location. This
  difference is only detectable in the case of variables that outlive their
  scope via closures. The let syntax accepts a comma-separated series of
  assignments and variable names:

  let var1 = value1, var2, var3 = value3
      code
  end

  The assignments are evaluated in order, with each right-hand side evaluated
  in the scope before the new variable on the left-hand side has been
  introduced. Therefore it makes sense to write something like let x = x,
  since the two x variables are distinct and have separate storage.

```

I would also expect the following to return 4 (not 6):

```julia
julia> let x = 1; f = () -> x + 3; x = 3; f() end
6

```

PS: It does work when using a comma separated variable list though:

```julia
julia> let x = 1, f = () -> x + 3, x = 3; f() end
4

```

and also the original threading example can be fixed like that

```julia
julia> let x = 1,
           x = @spawn x + 3
           fetch(x)
       end
4

```

I keep getting surprised by Julia’s syntax and imho that is not a good thing.

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [November 13, 2022, 9:24am UTC](https://discourse.julialang.org/t/is-calling-x-spawn-f-x-a-bad-idea/89934/5 "2022-11-13T09:24:03Z")

</div>

Ok, I get it now:

```julia
julia> let x = 1
           f = (y) -> x + y
           x = 3
           f(x)
       end
6

```

is equivalent to

```julia
let x = 1
           begin
               f = (y) -> x + y
               x = 3
               f(x)
           end
       end
6

```

i.e., the newline ends the let bindings and only the first variable is bound by let! If multiple variables are to be bound, they have to be separated by commas:

```julia
julia> let x = 1,
           f = (y) -> x + y,
           x = 3
           f(x)
       end
4

```

---

<div class="post-metadata">

**Author:** ![artemsolod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/artemsolod/32/20704_2.png) [@artemsolod](https://discourse.julialang.org/u/artemsolod)\
**Post date:** [November 14, 2022, 4:22pm UTC](https://discourse.julialang.org/t/is-calling-x-spawn-f-x-a-bad-idea/89934/6 "2022-11-14T16:22:24Z")

</div>

How did I miss that in the docs?! Thanks!
