美文网首页Coding程序员码农的世界
ruby 变量和方法的二义性辩论

ruby 变量和方法的二义性辩论

作者: AQ王浩 | 来源:发表于2014-08-17 12:45 被阅读98次

关于变量和方法的二义性辩论

首先先看个类

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

楼主博客

相关文章

  • ruby 变量和方法的二义性辩论

    关于变量和方法的二义性辩论 首先先看个类 两个疑问1、为啥 ‘1’处会有输出,但是‘4’处没有输出?2、为啥 ‘2...

  • From Objective-C to Ruby(4)-类和模块

    类 定义类 OC: ruby: 初始化方法 OC: ruby: 实例变量和属性 OC: ruby: 类方法和对象方...

  • ruby基础

    一、Ruby 类中的变量(Ruby 提供了四种类型的变量) 局部变量:局部变量是在方法中定义的变量。局部变量在方...

  • Ruby类(二)

    类 Ruby是一种面向对象语言 定义类 类中的变量 Ruby 提供了四种类型的变量: 局部变量:局部变量是在方法中...

  • Ruby 变量的命名方法

    以变量名的开头来决定变量的种类, 这个 Ruby 中对变量命名时唯一要坚决遵守的规则. 虽然如此, 但是根据以往的...

  • 方法 method

    有个奇怪的语法,就是ruby方法直接赋值给一个变量,然后输出这个变量,变量有值?function/method可以...

  • Vim技能修炼教程(13) - 变量

    VimScript变量 上节我们介绍了Python和Ruby来编写Vim插件的方式。不过,Python和Ruby并...

  • From Objective-C to Ruby(0)-常量变量

    变量 & 常量 OC: ruby: 注释 OC: ruby:

  • Ruby类、方法和变量的使用及命名

    类和方法### 命名##### 驼峰式类名首字母大写,方法名首字母小写方法名以?结尾表示返回布尔值方法名以!结尾一...

  • 编译器笔记17-语法分析-二义性文法的LR分析

    二义性文法的特点 每个二义性文法都不是LR的 某些类型的二义性文法在语言的描述和实现中很有用更简短、更自然 二义性...

网友评论

    本文标题:ruby 变量和方法的二义性辩论

    本文链接:https://www.haomeiwen.com/subject/kgbetttx.html