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

How do I create a mutable string in Ruby?

提问人:Iulian Onofrei 提问时间:9/5/2019 更新时间:12/2/2019 访问量:2064

问:

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

string = 'hello'

string << ' world'

因为它错误地显示:

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

红宝石 字符串 可变

评论

1赞 Jörg W Mittag 9/5/2019
当你不希望你的琴弦被冻结时,你为什么要打开冻结的琴弦?
0赞 Iulian Onofrei 9/5/2019
因为,如前所述,它默认由 RuboCop 强制执行,我倾向于信任它们,并且因为我确实希望某些字符串是不可变的。

答:

14赞 Iulian Onofrei 9/5/2019 #1

在字符串前添加一个,如下所示:+

string = +'hello'

string << ' world'

puts(string)

世界您好

评论

3赞 cremno 9/5/2019
向后兼容的替代方案:或String.new('hello')'hello'.dup
5赞 jamesc 9/5/2019 #2

您还可以使用:+=

s = 'H'
s += 'ello

=> “你好”

0赞 Conturbo 9/5/2019 #3

启用后,无法“更改”任何字符串。# 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

但是,您可以通过使用 来解决此问题。 为什么?因为是速记重新分配。而不是 muting,创建一个全新的字符串(具有全新的 object_id)并将其存储在相同的变量名称下(在本例中为 str)。str += ' world'+=+=

需要证据吗?在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赞 Iulian Onofrei 9/5/2019
启用后,您可以使用代替您提到的字符串来“更改”字符串。# frozen_string_literal: truestring << 'string'string += 'string'
0赞 Conturbo 9/5/2019
这段代码给了我一个错误...... ''' 回溯(最近一次调用最后一次):frozen_strings.rb:4:in '<main>':无法修改冻结的字符串 (FrozenError) '''ruby # frozen_string_literal: true str = 'hello' str << ' world'
0赞 Conturbo 9/11/2019
此外,该示例证明您不能在启用时更改字符串,但在您的第一条评论中,您断言您可以。# frozen_string_literal: true
2赞 Iulian Onofrei 9/11/2019
我不想表现得很粗鲁。但是您上次的回复仍然不正确。同样,即使设置为 ,也可以更改字符串,前提是使用 ,而不是简单地 。frozen_string_literaltrue= +=
3赞 Weihang Jian 12/2/2019 #4

frozen_string_literal表示字符串文本。若要创建可变的 String 实例,请在字符串文本中使用或预置 a。String#new+

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

评论

1赞 Iulian Onofrei 12/2/2019
这个答案与这个 anwer这个评论有什么不同?
0赞 Weihang Jian 4/16/2022
1)我通常不会阅读所有其他答案的所有评论,有些人也是如此。2)我的答案是此线程中其他答案的唯一答案。