百度百科中将Julia描繪成是一個面向科學計算的高性能動态高級程序設計語言。是說Julia在科學計算和人工智能領域有很大優勢,如今這兩個領域可是熱門中的熱門。所以學習Julia前景還是不錯的。
對于任何語言了解變量的作用域都是很基礎而且是十分重要的。Julia的作用域是否和你熟知的其他語言一樣呢?
Julia1.0對于變量的作用域做了比較大的修改,本文隻關注Julia1.0的變量作用域。
我們要讨論的問題和下面的代碼有關:
上面這段代碼如果執行下去,a,b 的值會發生什麼變化?大家不妨先自己試一試,是否和自己理解的一樣。
答案是: 這段代碼會在運行func_a()的時候抛出異常:ERROR: UndefVarError: b not defined,換句話說代碼是有問題的。
我們首先來分析func_b, 然後再來分析func_a,然後再來總結,最後抛出兩個小問題,有興趣的朋友可以試一試想一想,然後在評論區說出你的答案,我鼓勵大家交流。
注:為了方便說明,我們假設下面的代碼都是在REPL中執行的,即全局變量都屬于模塊Main。
一。 分析 func_b()我們的理解(當然現在證明是錯誤的):
對于 b = 100, 我們的理解是等價于 b = Main.b 100。
右邊的Main.b應該是全局變量b,也就是1,變量有模塊前綴,表明它是某個模塊中的全局變量; 左邊的b因為在函數中被賦值,那麼它應該是一個局部變量。最後func_b()運行應該返回101,而Main.b不會發生改變,仍然是1。
實際的情況:
我們要看清楚,Julia是怎麼處理的,需要借助Julia為我們提供的工具,這裡我們用@code_lowered 宏,它生成一個CodeInfo對象,有助于我們查看Julia是怎麼處理一個表達式的。
%1是可以認為是臨時變量,那麼上面的CodeInfo表達的意思就是 b = b 100 ,然後返回 %1。這裡的b沒有任何前綴,說明左邊和右邊的b都是局部變量。那麼顯然b 100是不對的,因為b在這裡是未定義先使用了。
二。分析 func_a()我們的理解:
a . = 100 等價于 a = Main.a . 100。 “. ”是一個廣播操作,意思是對Main.a中的每一個元素加100。那麼最後賦值給一個局部變量a并返回,Main.a 不會發現改變。
實際情況:
上述CodeInfo可以表示為:
materialize!(Main.a, broadcasted(Main.: , Main.a, 100))
broadcasted(Main.: , Main.a, 100) 即 Main.a . 100。
而materialize!()則表示上面. 操作後的結果直接覆蓋Main.a。注意函數名稱是帶有"!"後綴的,在Julia中,調用這類函數,通常會改變原參數的。
最後的結果就是在函數func_a()中, a . = 100 等價于 Main.a = Main.a . 100,即全局變量a會被改變成:[101, 102]
三。結論:在Julia中:
對于不可變對象,行為都類似func_b()
對于可變對象,行為都類似func_a() 。
在《Julia 字符串是可變的還是不可變的?》中我提到過,Julai中的字符串是可以修改的,但是注意,Julia仍然是将字符串作為不可變對象看待的。
最後的兩小問題是:問題1: 如果将func_a做如下的改寫,會怎麼樣?
function func_a() a = a . 100 end
問題2: 如果我想讓func_b() 可以修改全局的變量b,func_b()應該怎麼寫?
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!