为什么 Ruby setter 需要“self".班内资质? [英] Why do Ruby setters need "self." qualification within the class?

查看:45
本文介绍了为什么 Ruby setter 需要“self".班内资质?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Ruby setter——无论是由 (c)attr_accessor 创建还是手动创建——似乎是唯一需要在类本身中访问时需要 self. 限定的方法.这似乎让 Ruby 在语言世界中独树一帜:

Ruby setters—whether created by (c)attr_accessor or manually—seem to be the only methods that need self. qualification when accessed within the class itself. This seems to put Ruby alone the world of languages:

  • 所有方法都需要self/this(就像Perl,我认为是Javascript)
  • 没有方法需要 self/this is (C#, Java)
  • 只有 setter 需要 self/this (Ruby?)
  • All methods need self/this (like Perl, and I think Javascript)
  • No methods require self/this is (C#, Java)
  • Only setters need self/this (Ruby?)

最好的比较是 C# 与 Ruby,因为这两种语言都支持在语法上像类实例变量一样工作的访问器方法:foo.x = y, y = foo.x .C# 称它们为属性.

The best comparison is C# vs Ruby, because both languages support accessor methods which work syntactically just like class instance variables: foo.x = y, y = foo.x . C# calls them properties.

这是一个简单的例子;Ruby 和 C# 中的相同程序:

Here's a simple example; the same program in Ruby then C#:

class A
  def qwerty; @q; end                   # manual getter
  def qwerty=(value); @q = value; end   # manual setter, but attr_accessor is same 
  def asdf; self.qwerty = 4; end        # "self." is necessary in ruby?
  def xxx; asdf; end                    # we can invoke nonsetters w/o "self."
  def dump; puts "qwerty = #{qwerty}"; end
end

a = A.new
a.xxx
a.dump

去掉 self.qwerty =() 并且它失败了(Linux 和 OS X 上的 Ruby 1.8.6).现在 C#:

take away the self.qwerty =() and it fails (Ruby 1.8.6 on Linux & OS X). Now C#:

using System;

public class A {
  public A() {}
  int q;
  public int qwerty {
    get { return q; }
    set { q = value; }
  }
  public void asdf() { qwerty = 4; } // C# setters work w/o "this."
  public void xxx()  { asdf(); }     // are just like other methods
  public void dump() { Console.WriteLine("qwerty = {0}", qwerty); }
}

public class Test {
  public static void Main() {
    A a = new A();
    a.xxx();
    a.dump();
  }
}

问题:这是真的吗?除了需要 self 的 setter 之外,还有其他场合吗?即,是否还有其他场合不能在没有自我的情况下调用 Ruby 方法?

Question: Is this true? Are there other occasions besides setters where self is necessary? I.e., are there other occasions where a Ruby method cannot be invoked without self?

当然在很多情况下 self 变得是必要的.这不是 Ruby 独有的,只是要清楚:

There are certainly lots of cases where self becomes necessary. This is not unique to Ruby, just to be clear:

using System;

public class A {
  public A() {}
  public int test { get { return 4; }}
  public int useVariable() {
    int test = 5;
    return test;
  }
  public int useMethod() {
    int test = 5;
    return this.test;
  }
}

public class Test {
  public static void Main() {
    A a = new A();
    Console.WriteLine("{0}", a.useVariable()); // prints 5
    Console.WriteLine("{0}", a.useMethod());   // prints 4
  }
}

同样的歧义以同样的方式解决.但是虽然微妙,但我问的是

Same ambiguity is resolved in same way. But while subtle I'm asking about the case where

  • 一个方法已经被定义,并且
  • 未定义局部变量,并且
  • A method has been defined, and
  • No local variable has been defined, and

我们相遇

qwerty = 4

哪个不明确——这是一个方法调用还是一个新的局部变量赋值?

which is ambiguous—is this a method invocation or an new local variable assignment?

@麦克斯通

嗨!我理解并感谢你提出的观点和你的例子很棒.相信我,如果我有足够的声誉,我会投票赞成你的回应.然而我们仍然不同意:

Hi! I understand and appreciate the points you've made and your example was great. Believe me when I say, if I had enough reputation, I'd vote up your response. Yet we still disagree:

  • 在语义问题上,以及
  • 关于事实的中心点

首先我要声明,并非没有讽刺意味,我们正在就歧义"的含义.

First I claim, not without irony, we're having a semantic debate about the meaning of 'ambiguity'.

谈到解析和编程语言语义(主题这个问题),你肯定会承认这个概念的广泛性'歧义'.让我们采用一些随机符号:

When it comes to parsing and programming language semantics (the subject of this question), surely you would admit a broad spectrum of the notion 'ambiguity'. Let's just adopt some random notation:

  1. ambiguous: 词法歧义(lex 必须向前看")
  2. 歧义:语法歧义(yacc 必须遵循解析树分析)
  3. 模棱两可:在执行那一刻就知道一切的模棱两可

(2-3 之间也有垃圾).所有这些类别都由收集更多上下文信息,越来越全球化.所以当你说,

(and there's junk between 2-3 too). All these categories are resolved by gathering more contextual info, looking more and more globally. So when you say,

"qwerty = 4" 在 C# 中是明确的当没有定义变量时...

"qwerty = 4" is UNAMBIGUOUS in C# when there is no variable defined...

我完全同意.但出于同样的原因,我是说

I couldn't agree more. But by the same token, I'm saying

"qwerty = 4" 在 ruby​​ 中是明确的(现在已经存在)

"qwerty = 4" is un-Ambiguous in ruby (as it now exists)

"qwerty = 4" 在 C# 中是不明确的

"qwerty = 4" is Ambiguous in C#

而且我们还没有相互矛盾.最后,这是我们真正的地方不同意:红宝石可以或不能在没有任何进一步的情况下实施语言结构使得,

And we're not yet contradicting each other. Finally, here's where we really disagree: Either ruby could or could not be implemented without any further language constructs such that,

对于qwerty = 4",ruby 明确如果存在,则调用现有的 setter
没有定义局部变量

For "qwerty = 4," ruby UNAMBIGUOUSLY invokes an existing setter if there
is no local variable defined

你说不.我说是;另一个 ruby​​ 可能存在,其行为与各方面的当前,除了qwerty = 4"定义了一个新的当没有 setter 和 local 存在时变量,如果有,则调用 setter存在,如果存在,则分配给本地.我完全接受我可能是错的.事实上,我可能错的原因会很有趣.

You say no. I say yes; another ruby could exist which behaves exactly like the current in every respect, except "qwerty = 4" defines a new variable when no setter and no local exists, it invokes the setter if one exists, and it assigns to the local if one exists. I fully accept that I could be wrong. In fact, a reason why I might be wrong would be interesting.

让我解释一下.

假设您正在编写一种新的 OO 语言,其中的访问器方法看起来像像实例变量(像 ruby​​ & C#).你可能会开始概念语法类似于:

Imagine you are writing a new OO language with accessor methods looking like instances vars (like ruby & C#). You'd probably start with conceptual grammars something like:

  var = expr    // assignment
  method = expr // setter method invocation

但是解析器-编译器(甚至不是运行时)会呕吐,因为即使在所有输入都被理解了,无法知道哪种语法是相关的.你所面临的经典选择.我不能确定细节,但是基本上 ruby​​ 就是这样做的:

But the parser-compiler (not even the runtime) will puke, because even after all the input is grokked there's no way to know which grammar is pertinent. You're faced which a classic choice. I can't be sure of the details, but basically ruby does this:

  var = expr    // assignment (new or existing)
  // method = expr, disallow setter method invocation without .

这就是为什么它没有歧义,而 C# 是这样做的:

that is why it's un-Ambiguous, while and C# does this:

  symbol = expr // push 'symbol=' onto parse tree and decide later
                // if local variable is def'd somewhere in scope: assignment
                // else if a setter is def'd in scope: invocation

对于 C#,稍后"仍处于编译期.

For C#, 'later' is still at compile time.

我确信 ruby​​ 可以做同样的事情,但稍后"必须在运行时,因为正如本指出的那样,在执行语句之前您不知道哪种情况适用.

I'm sure ruby could do the same, but 'later' would have to be at runtime, because as ben points out you don't know until the statement is executed which case applies.

我的问题从来就不是我真的需要‘自我’吗?"还是什么正在避免潜在的歧义?"相反,我想知道这是为什么做了什么特别的选择?也许这不是性能.也许它只是得到了这份工作完成,或者被认为最好总是允许 1-liner local 覆盖方法(非常罕见的情况要求)...

My question was never intended to mean "do I really need the 'self.'?" or "what potential ambiguity is being avoided?" Rather I wanted to know why was this particular choice made? Maybe it's not performance. Maybe it just got the job done, or it was considered best to always allow a 1-liner local to override a method (a pretty rare case requirement) ...

但我有点建议最有活力的语言可能是那种将这个决定推迟最久,并根据最上下文选择语义信息:所以如果你没有本地并且你定义了一个setter,它会使用setter.是不是这就是为什么我们喜欢 ruby​​、smalltalk、objc,因为方法调用是在运行时决定的,提供最大的表现力?

But I'm sort of suggesting that the most dynamical language might be the one which postpones this decision the longest, and chooses semantics based on the most contextual info: so if you have no local and you defined a setter, it would use the setter. Isn't this why we like ruby, smalltalk, objc, because method invocation is decided at runtime, offering maximum expressiveness?

推荐答案

这里要记住的重要一点是 Ruby 方法可以在任何时候(取消)定义,因此要智能地解决歧义,每个分配都需要运行用于检查在赋值时是否存在具有赋值对象名称的方法的代码.

The important thing to remember here is that Ruby methods can be (un)defined at any point, so to intelligently resolve the ambiguity, every assignment would need to run code to check whether there is a method with the assigned-to name at the time of assignment.

这篇关于为什么 Ruby setter 需要“self".班内资质?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆