为什么缺少赋值运算符允许我修改Ruby常量而没有编译器警告?

时间:2021-05-11 05:27:37

In the following two examples I do the same thing, creating a constant String and using the concat method to modify it. Because it's a constant, I expect a compiler warning but only receive one in the second example when I use the assignment operator. Why is this?

在以下两个示例中,我执行相同的操作,创建一个常量String并使用concat方法对其进行修改。因为它是一个常量,我期望编译器警告,但在我使用赋值运算符时只在第二个例子中接收一个。为什么是这样?

X = "hello"
X.concat(" world")
puts X # no warning

X = "hello"
X = X.concat(" world")
puts X # warning: already initialized

Since the concat method modifies the string in place, that's normally what I would do, since there's no need to use an assigment operator. So, why does the presence of the assignment operator cause the compiler to identify these two operations as being different?

由于concat方法修改了字符串,这通常是我要做的,因为不需要使用分配运算符。那么,为什么赋值运算符的存在会导致编译器将这两个操作识别为不同?

4 个解决方案

#1


6  

This is because you're re-defining a new X. When you redefine a constant it gives you the "already initialized" error. The first example does not give this error because you're not redefining X, you're modifying it.

这是因为你正在重新定义一个新的X.当你重新定义一个常量时,它会给你“已经初始化”的错误。第一个例子没有给出这个错误,因为你没有重新定义X,你正在修改它。

#2


7  

In Ruby, variables are essentially pointers to a place in a memory containing an object -- not the object itself. In the second example, you are initializing a constant X to point to an object in the first line (X = "hello"), and in the second line, you are again initializing the constant -- but it already points to an object, so you get the error.

在Ruby中,变量本质上是指向包含对象的内存中的位置的指针 - 而不是对象本身。在第二个示例中,您正在初始化常量X以指向第一行中的对象(X =“hello”),而在第二行中,您将再次初始化常量 - 但它已经指向一个对象,所以你得到错误。

A constant's immutability doesn't mean you can't alter the object -- it just means you can't change the constant to point to another object.

常量的不变性并不意味着你不能改变对象 - 它只是意味着你不能改变常量来指向另一个对象。

#3


4  

If you want to make your string "real" constant, try 'freeze':

如果你想让你的字符串“真实”不变,试试'冻结':

X = "foo".freeze        # => "foo" 
X.concat("bar")

TypeError: can't modify frozen string
    from (irb):2:in `concat'
    from (irb):2

I really encourage you to read The Ruby Programming Languge.

我真的很鼓励你阅读Ruby Programming Languge。

#4


0  

This is because the constant X is storing a reference to a String object. In your first example, you are modifying the internal state of the String object, but not the reference stored by the constant. In the second example, you are changing the reference stored by the constant to a new String object which is returned from the concat method.

这是因为常量X存储对String对象的引用。在第一个示例中,您正在修改String对象的内部状态,但不修改常量存储的引用。在第二个示例中,您将常量存储的引用更改为从concat方法返回的新String对象。

The PickAxe book explains this here.

PickAxe书在这里解释了这一点。

#1


6  

This is because you're re-defining a new X. When you redefine a constant it gives you the "already initialized" error. The first example does not give this error because you're not redefining X, you're modifying it.

这是因为你正在重新定义一个新的X.当你重新定义一个常量时,它会给你“已经初始化”的错误。第一个例子没有给出这个错误,因为你没有重新定义X,你正在修改它。

#2


7  

In Ruby, variables are essentially pointers to a place in a memory containing an object -- not the object itself. In the second example, you are initializing a constant X to point to an object in the first line (X = "hello"), and in the second line, you are again initializing the constant -- but it already points to an object, so you get the error.

在Ruby中,变量本质上是指向包含对象的内存中的位置的指针 - 而不是对象本身。在第二个示例中,您正在初始化常量X以指向第一行中的对象(X =“hello”),而在第二行中,您将再次初始化常量 - 但它已经指向一个对象,所以你得到错误。

A constant's immutability doesn't mean you can't alter the object -- it just means you can't change the constant to point to another object.

常量的不变性并不意味着你不能改变对象 - 它只是意味着你不能改变常量来指向另一个对象。

#3


4  

If you want to make your string "real" constant, try 'freeze':

如果你想让你的字符串“真实”不变,试试'冻结':

X = "foo".freeze        # => "foo" 
X.concat("bar")

TypeError: can't modify frozen string
    from (irb):2:in `concat'
    from (irb):2

I really encourage you to read The Ruby Programming Languge.

我真的很鼓励你阅读Ruby Programming Languge。

#4


0  

This is because the constant X is storing a reference to a String object. In your first example, you are modifying the internal state of the String object, but not the reference stored by the constant. In the second example, you are changing the reference stored by the constant to a new String object which is returned from the concat method.

这是因为常量X存储对String对象的引用。在第一个示例中,您正在修改String对象的内部状态,但不修改常量存储的引用。在第二个示例中,您将常量存储的引用更改为从concat方法返回的新String对象。

The PickAxe book explains this here.

PickAxe书在这里解释了这一点。