Ruby 如何在语义上处理赋值?
How does Ruby handle assignment semantically?
在Ruby中,我们使用=
运算符为对象赋值。
将此与隐式类型结合起来,我们经常会遇到这样的情况:
myVar= :asymbol
上面这行既创建了一个新的符号对象,又将该对象绑定到变量名myVar
。
语义上,这是怎么做到的?
我已经在脑海中反复强调 =
运算符是 而不是 解释器内置的神奇语法,但实际上只是 [= 的语法糖16=] 方法。
考虑到这一点,我最好的猜测是当解释器看到我们试图给一个未定义的变量名赋值时,它首先创建一个特殊类型的新对象,比如 undefined
或null
之类的,然后将 :=
消息传递给该对象,有效负载是我们尝试分配的值。
但是,在未实例化的对象上调用 .class
只会抛出异常,因为 Ruby 认为我们正在尝试调用一个方法(其名称是您要调用的变量的名称)重新尝试在 self
上实现)
> obj.class
> NameError: undefined variable or method 'obj' for main:Object
因此,据我所知,我无法通过实验解决这个问题。
旁注:
在符号赋值的情况下,我认为赋值(A.K.A.实例化对象的object_id
方法返回的值,A.K.A.unsigned long VALUE
C 级别的变量)是一个数字,代表 table 某处的偏移量(我相信这就是 Ruby 为符号对象实现 'immediate value' 的方式)。
在其他情况下,该值可能是对象本身的直接编码,或者是要转换为引用 struct
.
的指针的值
无论如何,Ruby 表示对象的方式以及我们最终分配的是引用还是对象本身并不是我在这里要问的。
补充问题:
class继承自什么=
方法?我在 Object or BasicObject.
的规范中找不到它
从技术意义上讲,变量只是指向对象的指针。这没什么特别的,但是对现有对象的简单变量赋值不涉及任何方法调用或发送消息。
记住变量就在那里,这样程序员就可以通过名称而不是某种内部标识符或内存位置来引用对象。所以这里有一点 "magic",=
在进行赋值时很特别,因为在它的左侧和右侧有你可以做什么的规则。
您可以将消息发送到某物的唯一方法,即进行方法调用,如果您以编译器理解的方式定义它。 x = 1
就足够了,这意味着 x
指的是有问题的 Fixnum。
请注意,Ruby 解释器将需要确定 x
是指变量还是方法调用,因为 x=
可能是在对象上下文中定义的方法,其中这是评估。
例如:
class Example
def x=(value)
@x = value
end
def test
# Equivalent to send(:x=, 1) because x= is a method
x = 1
# Is a variable definition because y= is not a method
y = 2
# Is always a method call because self is referenced.
self.x = 3
end
end
# Is a variable definition because x= is not defined in this context
x = 4
如果您的对象没有 x=
方法,x
将被自动假定为一个变量。
您不能收到 :=
消息,因为这意味着您可以用一个对象替换另一个对象,这是不允许的。一旦一个对象被创建,它就不能神奇地改变类型。为此,您需要创建一个不同对象的新实例。变量看起来只是改变类型,但实际上,它们最终只是指向不同的对象。
所以简而言之,没有 :=
方法调用,但可能会有像 :x=
这样的特殊方法在非常特殊的情况下起作用。
在Ruby中,我们使用=
运算符为对象赋值。
将此与隐式类型结合起来,我们经常会遇到这样的情况:
myVar= :asymbol
上面这行既创建了一个新的符号对象,又将该对象绑定到变量名myVar
。
语义上,这是怎么做到的?
我已经在脑海中反复强调 =
运算符是 而不是 解释器内置的神奇语法,但实际上只是 [= 的语法糖16=] 方法。
考虑到这一点,我最好的猜测是当解释器看到我们试图给一个未定义的变量名赋值时,它首先创建一个特殊类型的新对象,比如 undefined
或null
之类的,然后将 :=
消息传递给该对象,有效负载是我们尝试分配的值。
但是,在未实例化的对象上调用 .class
只会抛出异常,因为 Ruby 认为我们正在尝试调用一个方法(其名称是您要调用的变量的名称)重新尝试在 self
> obj.class
> NameError: undefined variable or method 'obj' for main:Object
因此,据我所知,我无法通过实验解决这个问题。
旁注:
在符号赋值的情况下,我认为赋值(A.K.A.实例化对象的object_id
方法返回的值,A.K.A.unsigned long VALUE
C 级别的变量)是一个数字,代表 table 某处的偏移量(我相信这就是 Ruby 为符号对象实现 'immediate value' 的方式)。
在其他情况下,该值可能是对象本身的直接编码,或者是要转换为引用 struct
.
无论如何,Ruby 表示对象的方式以及我们最终分配的是引用还是对象本身并不是我在这里要问的。
补充问题:
class继承自什么=
方法?我在 Object or BasicObject.
从技术意义上讲,变量只是指向对象的指针。这没什么特别的,但是对现有对象的简单变量赋值不涉及任何方法调用或发送消息。
记住变量就在那里,这样程序员就可以通过名称而不是某种内部标识符或内存位置来引用对象。所以这里有一点 "magic",=
在进行赋值时很特别,因为在它的左侧和右侧有你可以做什么的规则。
您可以将消息发送到某物的唯一方法,即进行方法调用,如果您以编译器理解的方式定义它。 x = 1
就足够了,这意味着 x
指的是有问题的 Fixnum。
请注意,Ruby 解释器将需要确定 x
是指变量还是方法调用,因为 x=
可能是在对象上下文中定义的方法,其中这是评估。
例如:
class Example
def x=(value)
@x = value
end
def test
# Equivalent to send(:x=, 1) because x= is a method
x = 1
# Is a variable definition because y= is not a method
y = 2
# Is always a method call because self is referenced.
self.x = 3
end
end
# Is a variable definition because x= is not defined in this context
x = 4
如果您的对象没有 x=
方法,x
将被自动假定为一个变量。
您不能收到 :=
消息,因为这意味着您可以用一个对象替换另一个对象,这是不允许的。一旦一个对象被创建,它就不能神奇地改变类型。为此,您需要创建一个不同对象的新实例。变量看起来只是改变类型,但实际上,它们最终只是指向不同的对象。
所以简而言之,没有 :=
方法调用,但可能会有像 :x=
这样的特殊方法在非常特殊的情况下起作用。