ruby 變量和方法的二義性辯論

關于變量和方法的二義性辯論

首先先看個類

[27] pry(main)* class Person
[27] pry(main)*   def current_user
[27] pry(main)*     "it from method"
[27] pry(main)*   end
[27] pry(main)*   def show
[27] pry(main)*     puts "1---> #{current_user}"
[27] pry(main)*     zz = 123
[27] pry(main)*     if false
[27] pry(main)*       var_1 = 123
[27] pry(main)*       var_2 = nil
[27] pry(main)*       current_user = nil
[27] pry(main)*       puts "6--->#{zz}"
[27] pry(main)*       zz = 2222222
[27] pry(main)*     end
[27] pry(main)*     puts "2--->#{var_1}"
[27] pry(main)*     puts "3--->#{var_2}"
[27] pry(main)*     puts "4--->#{current_user}"
[27] pry(main)*     puts "5--->#{zz}"
[27] pry(main)*   end
[27] pry(main)* end
=> nil
[28] pry(main)> p = Person.new
=> #<Person:0x007fb534ebb6d0>
[29] pry(main)> p.show
1---> it from method
2--->
3--->
4--->
5--->123
=> nil

兩個疑問
1、為啥 ‘1’處會有輸出,但是‘4’處沒有輸出?
2、為啥 ‘2’,‘3’ 沒有輸出?

參考 stackoverflow

In Ruby, because methods can be called without an explicit receiver and without parentheses, there is a syntactic ambiguity between a local variable reference and a receiverless argumentless method call:

翻譯:在Ruby中,由于方法可以在不明確的接收器和不帶括號調用,有一個局部變量的引用和receiverless argumentless方法調用之間就會產生句法歧義:

foo  

could either mean "call method foo on self with no arguments" or "dereference local variable foo".

翻譯:既可以指“自我調用方法foo不帶任何參數”或“間接引用本地變量foo”。

If there exists a local variable foo in scope, this is always interpreted as a local variable dereference, never as a method call.

翻譯:如果存在一個局部變量foo的范圍,這個總是被解釋為一個局部變量解引用,從來沒有作為一個方法調用。

So, what does it mean for a local variable to "be in scope"? This is determined syntactically at parse time, not semantically at runtime. This is very important! Local variables are defined at parse time: if an assignment to a local variable is seen by the parser, the local variable is in scope from that point on. It is, however, only initialized at runtime, there is no compile time evaluation of code going on:

翻譯:那么,是什么意思為一個局部變量要“范圍”?這是在分析時確定的語法,語義沒有在運行。這是非常重要的!局部變量在分析時定義:如果一個賦值給一個局部變量解析器看出,局部變量的作用域從該點。然而,只有在運行時進行初始化,則代碼將在沒有編譯時評價。

觀點:局部變量在解析的時候就確定了,只不過在運行的時候賦值和初始化!并且如果存在同名局部變量和方法名,那么就只會調用局部變量,而不會調用方法。從同名的局部變量定義那會兒開始,往后的都是他的作用域范圍。

if false
  foo = 42 # from this point on, the local variable foo is in scope
end

foo # evaluates to nil, since it is declared but not initialized

Why does it make sense for local variables to "shadow" methods and not the way around? Well, if methods did shadow local variables, there would no longer be a way to dereference those local variables. However, if local variables shadow methods, then there is still a way to call those methods: remember, the ambiguity only exists for receiverless argumentless methods calls, if you add an explicit receiver or an explicit argument list, you can still call the method:

翻譯:為啥局部變量覆蓋方法是有意義的,反之呢?好吧,如果方法覆蓋了實力變量,那么不會有一種方式來調用這些局部變量。但是,如果局部變量覆蓋方法方法,那么還有一個方法來調用這些方法:請記住,模糊只存在于receiverless argumentless方法的調用,如果你明確的添加一個接收器或一個明確的參數列表,你仍然可以調用方法:

def bar; 'Hello from method' end; public :bar

bar # => 'Hello from method'

bar = 'You will never see this' if false

bar # => nil

bar = 'Hello from local variable'

bar      # => 'Hello from local variable'
bar()    # => 'Hello from method'
self.bar # => 'Hello from method'

綜上所述

兩個疑問
1、為啥 ‘1’處會有輸出,但是‘4’處沒有輸出?
因為在‘1’位置處,ruby不清楚到底是局部變量,還是方法,所以先找局部變量,然后發現沒有定義,所以就找到方法,輸出方法的值。
由于Ruby是解釋執行,
并且在

if false
    ...
    current_user = nil
    ...
end  

中重新定義了 current_user的局部變量,所以在這之后,都是局部變量current_user的作用域,所以即使是 if flase,但是還是定義了current_user局部變量。最后根據

If there exists a local variable foo in scope, this is always interpreted as a local variable dereference, never as a method call

所以后面‘4’的位置調用的是局部變量 current_user,而非方法。所以‘4’的位置輸出為nil

2、為啥 ‘2’,‘3’ 沒有輸出?
道理如上,雖然定義了var_1,var_2 但是尚未初始化。

樓主博客

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,991評論 19 139
  • 原文:http://dmitrysoshnikov.com/ecmascript/javascript-the-c...
    jaysoul閱讀 489評論 0 0
  • 二十年前我的身體狀況一塌糊涂,那時候的我剛剛三十出頭,年齡不大,從頭到腳卻都是毛病。當時我們剛剛住上新樓房,單位統...
    閃亮人生閱讀 551評論 0 0
  • 世上除了生死,都是小事。 我們從今天開始,像孩子一樣,每天微笑吧。 寬恕人的過失,便是自己的榮耀。 笑一個吧! 在...
    愛中醫超塵閱讀 329評論 0 0
  • 近些年來,各種投資理財詐騙案例頻頻發生,涉案金額越發龐大。這些案件都有一個共同點,那就是被騙人群中老年人占一大部分...
    八條魚理財閱讀 158評論 0 0