为什么Matzselect使Ruby在默认情况下是可变的?
这是这个问题的反面: 为什么string不能在Java和.NET中变化?
在Ruby中做这个select只是因为操作(附加等)对可变string有效,还是有其他原因?
(如果只是效率,那看起来很奇怪,因为Ruby的devise似乎不会高效地促进高效实现。)
正如你所看到的,这与Ruby的devise是一致的。 不可变的string比可变string更有效率 – 因为string被重用,所以不需要复制 – 但是让程序员更加努力。 直观地看到string是可变的 – 你可以将它们连接在一起。 为了解决这个问题,Java默默地将两个string的连接(通过+
)转换为一个StringBuffer对象的使用,我确信还有其他的这样的黑客。 Rubyselect反而使string在默认情况下是可变的,这是以牺牲性能为代价的。
Ruby也有一些破坏性的方法,如String#upcase!
依赖于string是可变的。
另一个可能的原因是Ruby受Perl启发,而Perl碰巧使用可变string。
Ruby有符号和冻结string,都是不可变的。 作为额外的奖励,符号保证是唯一的每个可能的string值。
这些是我的意见,而不是马茨的。 为了这个答案的目的,当我说一个语言有“不可变的string”,这意味着它的所有string是不可变的,即没有办法创build一个可变的string。
-
“不可变string”devise将string视为两个标识符 (例如散列键和其他VM内部使用)和数据存储结构 。 这个想法是,标识符是可变的是危险的。 对我来说,这听起来像是违反了单一责任。 在Ruby中,我们有标识符的符号,所以string可以自由地充当数据存储。 确实Ruby允许string作为散列键,但是我认为程序员很less将string存储到variables中,将其用作散列键,然后修改string。 在程序员的脑海里,有(或者应该是)两个string的分离。 通常情况下,用作散列键的string是一个文字string,所以很less有可能被突变。 使用string作为散列键与使用两个string的数组作为散列键没什么两样。 只要你的头脑有一个很好的把握你所使用的关键,那么没有问题。
-
将string作为数据存储从认知简单的angular度来看是有用的。 只要考虑Java和它的
StringBuffer
。 这是一个额外的数据结构(在一个已经很大且通常不直观的标准库中),如果你想要执行string操作,例如在另一个string的某个索引处插入一个string,则必须进行pipe理。 所以一方面,Java认识到需要做这些操作,但是因为不可变的string暴露给程序员,所以他们不得不引入另一个结构,所以操作仍然是可能的,而不会让我们重新开始。 这给程序员带来了额外的认知负担。 -
在Python中,插入的最简单的方法似乎是在插入点之前和之后获取子string,然后将它们连接在要插入的string周围。 我想他们可以很容易地添加一个方法到标准库插入和返回一个新的string。 但是,如果该方法被称为
insert
,初学者可能会认为它改变了string; 描述性的,它将不得不被称为new_with_inserted
或类似的东西。 在日常使用中,“插入”意味着您更改插入内容的东西(例如,将信封插入邮箱中会更改邮箱的内容)。 这又提出了一个问题,“为什么我不能改变我的数据存储? -
Ruby提供了冻结对象,所以它们可以安全地传递,而不会引入细微的错误。 好处是,Ruby像对待任何其他数据结构(数组,哈希,类实例)一样处理string。 他们都可以被冻结。 一致性是程序员友好的。 不可变的string使string脱颖而出,作为一种“特殊的”数据结构,当它不是真正的,如果你使用它作为数据存储。