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 但是尚未初始化。

楼主博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,596评论 18 139
  • 原文:http://dmitrysoshnikov.com/ecmascript/javascript-the-c...
    jaysoul阅读 472评论 0 0
  • 二十年前我的身体状况一塌糊涂,那时候的我刚刚三十出头,年龄不大,从头到脚却都是毛病。当时我们刚刚住上新楼房,单位统...
    闪亮人生阅读 514评论 0 0
  • 世上除了生死,都是小事。 我们从今天开始,像孩子一样,每天微笑吧。 宽恕人的过失,便是自己的荣耀。 笑一个吧! 在...
    爱中医超尘阅读 299评论 0 0
  • 近些年来,各种投资理财诈骗案例频频发生,涉案金额越发庞大。这些案件都有一个共同点,那就是被骗人群中老年人占一大部分...
    八条鱼理财阅读 125评论 0 0