如何在Ruby中创建可变字符串?

6

我正在使用 RuboCop 默认强制执行的 # frozen_string_literal: true 魔术注释,并且无法向字符串追加内容:

string = 'hello'

string << ' world'

因为它会出现错误信息:

无法修改冻结的字符串 (RuntimeError)


1
当你不想让字符串被冻结时,为什么要打开冻结字符串? - Jörg W Mittag
因为正如所提到的,它是由RuboCop默认实施的,我倾向于信任他们,并且我确实希望某些字符串是不可变的。 - Iulian Onofrei
4个回答

14
你可以在字符串前加上+,像这样:
string = +'hello'

string << ' world'

puts(string)

你好世界


3
向后兼容的替代方案:String.new('hello')'hello'.dup - cremno

5
你也可以使用+=
s = 'H'
s += 'ello

=> "你好"


3

frozen_string_literal是用于字符串字面量的。如果要创建一个可变的字符串实例,请使用String#new或在字符串字面量前加上+

# frozen_string_literal: true
'foo'.frozen? # => true
String.new.frozen? # => false
(+'foo').frozen? # => false

1
这个答案与此答案此评论有何不同之处? - Iulian Onofrei
  1. 我通常不会阅读所有其他答案的评论,有些人也是如此。
  2. 我的答案与本主题中的其他答案不同。
- Weihang Jian

0

当启用# frozen_string_literal:true时,您不能“更改”任何字符串。

需要证明吗? 使用以下脚本...

# frozen_string_literal: true

str = 'hello'
str << ' world'

你会收到以下错误信息...

Traceback (most recent call last):
frozen_strings.rb:4:in `<main>': can't modify frozen String (FrozenError)

'Mutate'的意思是改变对象的值。 因此,您的示例失败了,因为<<会突变字符串,并且它正在突变您的字符串string,因为您正在使用<<运算符。

需要证明吗? 进入irb! 输入以下内容:

str = 'hello' # => 'hello'
obj_id1 = str.object_id # => some number, ex: 12345
str << ' world' # => 'hello world'
obj_id2 = str.object_id # => some number, ex: 12345
obj_id1 == obj_id2 # this should return true, proving that you mutated the object

然而,您可以通过使用str + =' world'来解决这个问题。

为什么?因为+=是一种简写的重新赋值方式。与变异不同,+=创建一个全新的字符串(具有全新的object_id),并将其存储在相同的变量名称下(在本例中为str)。

想要证明吗?在irb中试试吧!

str = 'hello' # => 'hello'
obj_id1 = str.object_id # => some number, ex: 12345
str += ' world' # => ' world'
obj_id2 = str.object_id # => some other number, ex: 356456345
obj_id1 == obj_id2 # => this returns false!

如果这有帮助,请告诉我!


1
当启用 # frozen_string_literal: true 时,您可以使用 string << 'string' 而不是您提到的 string += 'string' 来“改变”字符串。 - Iulian Onofrei
这段代码给了我一个错误...# frozen_string_literal: true str = 'hello' str << ' world' 跟踪最近的调用(上次): frozen_strings.rb:4:
:无法修改冻结字符串(FrozenError) - Conturbo
此外,该示例证明了在启用# frozen_string_literal: true时无法更改字符串,但在您的第一条评论中,您断言可以这样做。 - Conturbo
2
我不想显得无礼。但是你上次的回复仍然是错误的。再次强调,如果你使用= +进行初始化,而不是简单地使用=, 即使frozen_string_literal设置为true,你仍然可以改变字符串。 - Iulian Onofrei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接