On Wed, 2015-03-11 at 10:24, Wendell Zheng <[email protected]> wrote:
> I did more experiments.
>
> *Input 1:*
> y = 0
> begin 
>     y = 10 
> end
> y
> *Output 1:*
> 10
>
> *Input 2:*
> y = 0
> begin 
>     local y = 10 
> end
> y
> *Output 2:*
> 0
>
> It's the same for *if *block. 

begin-end and if-end blocks do not introduce a new scope:
http://docs.julialang.org/en/latest/manual/variables-and-scoping/

So above is the same as not having any blocks.  But the behaviour of
local at the REPL is strange:

julia> local y = 10
10

julia> y
ERROR: y not defined

So, what is y local to then?  Shouldn't the first line either throw an
error or be equivalent to `y = 10`?

> May I conclude that:
> 1) *Function *introduces *hard scope, *where the assignment introduce new 
> local variables;
> 2) Other blocks (including *if*, *begin-end*) introduce soft scope, where 
> the assignment either refers to an outer variable 
>     or introduces an variable which can be conveyed into an outer scope;
> 3) The keyword *global *used in a hard scope turns the hard scope soft;
> 4) The keyword *local *used in a soft scope turns the soft scope hard.

Rule 2 is not right:

julia> for i=1:10
           j = 10
       end

julia> j
ERROR: j not defined

julia> j = 1
1

julia> for i=1:10
           j = 10
       end

julia> j
10

So, I think, the rules are these:

In a soft scope:
s1) normal assignment `x = 5`
  1) if a binding exists in the global scope, assign to that
  2) if no binding exists, make a new *local* binding
s2) local assignment `local x=5`
  1) make a new local binding
s3) global assignment `global x=5`
  1) make a new global binding

In a hard scope
h1) normal assignment `x = 5` 
  1) make a new *local* binding
h2) local assignment `local x=5`
  2) make a new local binding (i.e. equivalent to h1.1)
h3) global assignment `global x=5`
  3) make a new global binding

If no assignment happens, just reading, then hard and soft are equivalent.

The confusing bit about soft scopes are that its rules are dependent on
the outer scopes.  I guess the reason for these more complicated rules
are typical usage of loops: being able to modify outside bindings but
newly introduced bindings will go out of scope once the loop terminates.

Another caveat is that these rule seem to break down in nested
functions.  Here an example from
https://github.com/JuliaLang/julia/issues/423#issuecomment-4100869

function namespace()
    x = 0
    function f()
        x = 10
    end
    f()
    println(x)
end
namespace() # prints 10, which suggests that the inner function has a soft 
scope!!!

> By the way, I find the describe of Python's scope in Wikipedia 
> <http://en.wikipedia.org/wiki/Scope_%28computer_science%29#Lexical_scoping_vs._dynamic_scoping>
>  
> is quite clear, Could you write the same thing about Julia in Wikipedia?

Well, this is about lexical vs dynamic scope, which is (I think) a
different issue to soft and hard scope.

I'll move some of this discussion to 
https://github.com/JuliaLang/julia/issues/9955

> On Tuesday, March 10, 2015 at 10:40:53 PM UTC+1, Mauro wrote:
>>
>> I think this is the soft vs hard scope issue.  See: 
>> https://github.com/JuliaLang/julia/issues/9955 
>>
>> That issue could use some fleshing out though... 
>>
>> On Tue, 2015-03-10 at 20:03, Wendell Zheng <[email protected] 
>> <javascript:>> wrote: 
>> > *Input 1:* 
>> > y = 0 
>> > function foo() 
>> >     y = 10 
>> > end 
>> > foo() 
>> > y 
>> > 
>> > *Output 1:* 
>> > 0 
>> > 
>> > *Input 2:* 
>> > y = 0 
>> > for i = 1:1 
>> >     y = 10 
>> > end 
>> > y 
>> > 
>> > *Output 2:* 
>> > 10 
>> > 
>> > In the first example, y introduces a local variable. 
>> > In the second example, y is still a global variable. 
>> > 
>> > This is not consistent to what the official document said. 
>> > 
>> > I tried these examples in JuliaBox. 
>>
>>

Reply via email to