【问题标题】:Why do variable prefixes in ruby allow omission of parenthesis in method invocations?为什么ruby中的变量前缀允许在方法调用中省略括号?
【发布时间】:2016-05-16 00:32:48
【问题描述】:

David Flanagan 的《Ruby 编程语言》;松本幸弘,they state that the variable prefixes ($, @, @@) are one price we pay for being able to omit parentheses around method invocations。谁可以给我解释一下这个?

【问题讨论】:

  • 其实是个好问题。严格来说,我不确定这种说法是否属实。我一直认为前缀是指定范围(即本地、实例、类、全局),而不是区分变量和方法(显然,本地变量名称与解释器的方法调用区分开来)。
  • 当你询问具体的参考资料时,如果它可以在线获得,至少要给出它的链接。
  • @sawa: link

标签: ruby semantics


【解决方案1】:

这是我不成熟的意见。如果我错了,请纠正我。

假设实例变量没有@前缀,那我们如何声明实例变量呢?

class MyClass
  def initialize
    # Here foo is an instance variable
    self.foo = 'bar'
  end

  # Here foo is an instance method
  def foo
  end

  def bar
    # Call method. No doubt.
    self.foo()

    # Call method? Access instance variable?
    self.foo
  end
end

在上述情况下,实例变量foo 使用假设语法进行初始化

self.foo = 'bar'

因为我们必须有办法告诉 ruby​​ 解释器 foo 属于当前实例,而不是局部变量。

那么在方法bar中,如果在方法调用中没有强制括号,解释器如何判断self.foo是方法调用还是实例变量访问?

也许我们可以在缺少括号时让实例变量隐藏实例方法,但这会导致语言本身的语法不一致。例如,从MyClass 定义之外:

obj = MyClass.new

# Call instance method
obj.foo

这是一个实例方法调用,因为所有实例变量从外部都是不可见的(至少在不使用元编程的情况下)。但是bar方法中的self.foo(不带括号)是一个实例变量访问。这种语法不一致可能会导致错误。同时,也给解释器本身的实现带来了困难。

那么让实例方法隐藏实例变量呢?然后程序员必须确保实例变量名称不会与实例方法名称冲突,否则实例变量将变得不可访问。如果一个类有一个很长的祖先链,这将非常困难,因为不仅要检查当前类定义中的冲突,还要检查其祖先中的冲突,这会破坏封装。

无论哪种方式,价格都比给实例变量加前缀要高很多。对于类和全局变量,情况类似。

【讨论】:

    【解决方案2】:

    让我们看一个例子:

    def foo
        10
    end
    
    p foo
    #=> 10
    foo = 'hi'
    p foo
    #=> hi
    p foo()
    #=> 10
    

    如果我们在同一作用域中定义了一个名称与方法名称相同的局部变量,那么我们将失去与方法名称的绑定,因为变量名称优先。为了消除歧义,我们将强制使用括号。

    这本书似乎详细阐述了这一现象,并做出了设计决策以提供灵活性,其中需要使用 @ 之类的符号来定义实例变量,以便可以使用相应的访问器方法(varvar=)在没有括号的情况下调用,并且给人一种正在访问变量的印象,即使实际上是在调用一种方法。

    ...您会注意到 Ruby 变量开头的标点符号 名称:全局变量以 $ 为前缀,实例变量以 以@为前缀,类变量以@@为前缀。这些 前缀可能需要一点时间来适应,但过一段时间你可能会 来欣赏这样一个事实,即前缀告诉你的范围 多变的。前缀是必需的,以消除 Ruby 的歧义 非常灵活的语法。考虑变量前缀的一种方法是 它们是我们为能够省略括号而付出的代价 方法调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-03
      • 2015-06-22
      • 2016-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多