從matlab遷移過來的使用者會覺得julia的作用域有點迷。說實話我也繞了幾個彎子。為了避免把讀者帶進概念的漩渦中,本文列舉幾個典型情況,幫助讀者迅速解決作用域的問題。
matlab的作用域包括乙個全域性域和各個函式的區域性域。julia相對更繁瑣,有乙個全域性域和許多態別的區域性域。迴圈體就是一種區域性域,例如:
a =
1for i=1:
2 a +=1
end
會報錯error: loaderror: undefvarerror: a not defined
,證明全域性域的變數沒有自動繼承到區域性域中。實際上,julia會智(zhi)能(zhang)地判斷哪些變數自動繼承,規則是:
為解決報錯,增加乙個global
標識:
a =
1for i=1:
2 global a
a +=1
end
得到了a = 3
。有趣的是global
語句放在區域性域的任一位置都可以。
多層迴圈只需要在最外層標識,例如:
a =
1for i=1:
2 global a
for j=1:
3 a +=1
endend
但global
絕不能放在迴圈體外面,像這樣就會報錯:
a =
1global a
for i=1:
2for j=1:
3 a +=1
endend
這麼一看的確挺迷的,反正記住就行。如果要強行歸納的話,大概就是:global
能使迴圈體的區域性域」向外看「,也能使外層迴圈」向裡看「,但不能使全域性域」向裡看「。想刨根問底的話,請參閱let
語法的相關文件。
如果只是把全域性變數當作迴圈變數,那就不必加global
標識,原因在於我們沒有修改它。例如:
m =
3; n =
0for i=1:m
global n
n +=1
endn
函式的區域性域比迴圈體更複雜一點點,包括兩種情況:(1)函式與迴圈體遵循相同的自動繼承規則,可以直接繼承全域性變數,只要你不在函式裡修改它。例如:
n =
1function g()
return n+
1endg(
)
這時候要注意,如果函式裡有迴圈體,迴圈體會在函式的區域性域中劃分出乙個新的區域性域。例如:
m =
3; n =
0function g
(m)for i=1:m
global n
n +=1
endreturn n
endg
(m)
假如去掉global n
就會報錯。所以要時刻提防迴圈體。
(2)如果某個變數被當作引數傳遞,那麼函式會在區域性域中建立乙個同名區域性變數,即按照」傳值「的方式進行傳遞。這樣建立的區域性變數不會影響同名的全域性變數,與上面的」放棄自動繼承「是乙個意思。例如:
t =
1; w =
0function y
(w) w = t
endprintln
("y=",y
(w),
" w="
,w)
輸出是:
julia>
include
("demo.jl")y=
1 w=
0
當然,global
標識也可以用在這裡,例如:
t =
1; w =
0function y()
global w
w = t
endprintln
("y=",y
()," w="
,w)
輸出是:
julia>
include
("demo.jl")y=
1 w=
1
struct atomuv
endw = array
(undef,2,
2)function y
(w) w[1,
2]=atom
(0.1
,0.2
) w
endprintln
("y[1]=",y
(w)[1,
2]," w[1]="
,w[1,2
])w
輸出是:
julia>
include
("demoparallel_1.jl")y[
1]=atom
(0.1
,0.2
) w[1]
=atom
(0.1
,0.2
)2×2 array
:#undef atom(0.1, 0.2)
#undef #undef
可見確實是引用而不是傳值。有趣的是,當採取引用策略時,會無視規則強行繼承,例如:
struct atomuv
endn =
10w = array
(undef,2,
2)function y()
w[1,
2]=atom
(0.1
,0.2
) w
endprintln
("y[1]=",y
()[1
,2],
" w[1]="
,w[1,2
])w
經過測試,julia會把結構體、結構體陣列視為」複雜的「,而把普通的數值、數值陣列、共享陣列視為」簡單的「,無論規模大小。舉個結構體的例子:
mutable
struct atomuv
endw =
atom
(0.1
,0.2
)function y
(w) w.u =
0.5 w
endprintln
("y[1]=",y
(w).u,
" w[1]="
,w.u)
有個特別的語法begin...end
可以把若干表示式湊在一起。例如:
w = begin
w =1 w +
=0.1
end
它實際上等價於w = ( w = 1; w += 0.1)
,是後者的分行寫法。這種結構是沒有區域性域的。
這個也不廢話了,跟別的語言乙個意思。
掌握函式執行過程,作用域鏈
我們在了解了全域性 的執行和作用域的提公升後,我們接下來理解比較特殊的函式執行和作用域鏈。被解析,開闢函式記憶體空間,go中引用函式位址。通過全域性 的變數提公升我們知道,在 解析過程中,會生成全域性物件global object go 並在其中對全域性的變數進行定義,函式在這個期間也會被定義,並生...
Javascript的作用域域作用域鏈的理解
如何解析一段可執行 分了兩個階段 解析 和執行 其中解析 可以理解為記名字,就是先把關鍵字var和function定義的變數名登記了下來,這也就有了變數提公升這一說。在執行 階段才是真正的執行賦值,運算等操作。暫不解析這幾個名詞,先來看乙個例子。var scope global function f...
作用域 的作用
1 作用域符號 的前面一般是類名稱,後面一般是該類的成員名稱,c 為例避免不同的類有名稱相同的成員而採用作用域的方式進行區分 如 a,b表示兩個類,在a,b中都有成員member。那麼 a member就表示類a中的成員member b member就表示類b中的成員member 2 全域性作用域符...