Let expression problem

        x=1
        y=2
        z=3
        u=4
        a=5
        v=6
        let x=11, y=11, z::Int=11, u::Int=11, v=(a=11; 22)
            x=22
            println("x = ", x)
            println("y = ", y)
            println("z = ", z)
            println("u = ", u)
            println("a = ", a)
            println("v = ", v)
            println(x+y+z+u+v+a)
         end
         x=11
         println("x = ", x)
         println("y = ", y)
         println("z = ", z)
         println("u = ", u)
         println("a = ", a)
         println("v = ", v)
         println(x+y+z+u+a+v)

I would expect a to be 11, after the let but when I run it , it says it is 5. Here is the output. Is this expected?

julia> x=1
1

julia> y=2
2

julia> z=3
3

julia> u=4
4

julia> a=5
5

julia> v=6
6

julia> let x=11, y=11, z::Int=11, u::Int=11, v=(a=11; 22)
           x=22
           println("x = ", x)
           println("y = ", y)
           println("z = ", z)
           println("u = ", u)
           println("a = ", a)
           println("v = ", v)
           println(x+y+z+u+v+a)
        end
x = 22
y = 11
z = 11
u = 11
a = 11
v = 22
88

julia> x=11
11

julia> println("x = ", x)
x = 11

julia> println("y = ", y)
y = 2

julia> println("z = ", z)
z = 3

julia> println("u = ", u)
u = 4

julia> println("a = ", a)
a = 5

julia> println("v = ", v)
v = 6

julia> println(x+y+z+u+a+v)
31
1 Like

Yes, the assignment happens within a let block so outside it is unaffected. See

https://docs.julialang.org/en/v1/manual/variables-and-scoping/

1 Like

I thought about this too, and hesitated to answer after I tried the following:

julia> function test()
           a=5
           v=5
           println("a=",a," v=",v)
           let v=(a=11;22)
               println("a=",a," v=",v)
           end
           println("a=",a," v=",v)
       end
test (generic function with 1 method)

julia> test()
a=5 v=5
a=11 v=22
a=11 v=5

Is there a difference between let in the REPL and let inside a function? Apparently, but is there something written about this difference? Didn’t found something detailed.

This is my mental model of how let works:

let v = (a = 11, 22)
end

can be written as by expanding the (;) as

let
    a = 11
    tmp1 = 22
    let v = tmp1
    end
end

Then within a function, a = 11 updates the outer local scope, while within the global scope the a inside let is global.

If updating in the latter case is desired,

v, a = 5, 5
let v = (global a = 11; 22)
end
v, a     # 5, 11
1 Like

I think the subtlety here is that:

let x = ...

behaves differently than

let
  x = ...

For example:

julia> let
         x = 1
         let x = 2
           x = 3
         end
         @show x
       end
x = 1
1

julia> let
         x = 1
         let 
           x = 2
           x = 3
         end
         @show x
       end
x = 3
3

The same issue is discussed in Variable declarations within let blocks

I actually don’t think the manual is very clear on this topic: https://docs.julialang.org/en/v1/manual/variables-and-scoping/#Let-Blocks-1

In particular, it says

An assignment modifies an existing value location, and let creates new locations. This difference is usually not important, and is only detectable in the case of variables that outlive their scope via closures.

I think something like the answer from Variable declarations within let blocks would be a good addition to that section of the manual.

4 Likes

So

let v=(a=11;22)
    ...
end

is equivalent to

let v=22
    a=11
    ...
end

?
If yes, all is clear.
Actually I can check myself:

julia> function test()
       a=5
       v=5
       let v=(a=11;22)
       end
       (a,v)
       end
test (generic function with 1 method)

julia> function test2()
       a=5
       v=5
       let v=22
       a=11
       end
       (a,v)
       end
test2 (generic function with 1 method)

julia> @code_lowered test()
CodeInfo(
1 ─      a = 5
β”‚        v@_3 = 5
β”‚        a = 11
β”‚        v@_4 = 22
β”‚   %5 = Core.tuple(a, v@_3)
└──      return %5
)

julia> @code_lowered test2()
CodeInfo(
1 ─      a = 5
β”‚        v@_3 = 5
β”‚        v@_4 = 22
β”‚        a = 11
β”‚   %5 = Core.tuple(a, v@_3)
└──      return %5
)

Answer is yes :slight_smile:

1 Like

Please consider making a PR to the docs.