Set*_*sue 43 ruby string language-design mutable immutability
这与此问题相反:为什么字符串在Java和.NET中不可变?
这种选择是否仅仅因为操作(追加等)在可变字符串上有效,或者是否有其他原因而在Ruby中进行?
(如果它只是效率,那似乎很奇怪,因为Ruby的设计似乎不会高度重视促进有效的实施.)
rjh*_*rjh 32
正如您所说,这符合Ruby的设计.不可变字符串比可变字符串更有效 - 减少复制,因为字符串被重用 - 但使程序员更难工作.将字符串视为可变是直观的 - 您可以将它们连接在一起.为了解决这个问题,Java默默地将+两个字符串的连接(通过)转换为StringBuffer对象的使用,我确信还有其他类似的黑客攻击.Ruby选择默认情况下使字符串变为可变,但代价是性能.
Ruby也有许多破坏性的方法,比如String#upcase!依赖于字符串是可变的.
另一个可能的原因是Ruby受Perl的启发,而Perl碰巧使用了可变字符串.
Ruby有符号和冻结字符串,两者都是不可变的.作为额外的奖励,符号保证每个可能的字符串值是唯一的.
这些是我的意见,而不是Matz的意见.出于这个答案的目的,当我说一个语言有"不可变字符串"时,这意味着它的所有字符串都是不可变的,即无法创建一个可变的字符串.
"不可变字符串"设计将字符串视为标识符(例如,作为散列键和其他VM内部使用)和数据存储结构.这个想法是标识符可变是危险的.对我而言,这听起来像违反了单一责任.在Ruby中,我们有标识符的符号,因此字符串可以自由地充当数据存储.Ruby确实允许字符串作为哈希键,但我认为程序员很少将字符串存储到变量中,将其用作哈希键,然后修改字符串.在程序员的脑海中,有(或应该)2个字符串的分离.通常,用作散列键的字符串是文字字符串,因此几乎没有机会进行变异.使用字符串作为散列键与使用两个字符串的数组作为散列键没有太大区别.只要你的头脑能够很好地掌握你所使用的钥匙,那就没问题了.
从认知简单性的角度来看,将字符串作为数据存储是有用的.只考虑Java及其StringBuffer.这是一个额外的数据结构(在一个已经很大且通常不直观的标准库中),如果你正在尝试执行字符串操作,比如在另一个字符串的某个索引处插入一个字符串,则必须管理它.因此,一方面,Java认识到需要进行这些类型的操作,但是因为不可变的字符串暴露给程序员,所以它们必须引入另一个结构,因此操作仍然可行,而不会让我们重新发明轮子.这给程序员带来了额外的认知负担.
在Python中,似乎最简单的插入方法是在插入点之前和之后获取子串,然后在要插入的字符串周围连接它们.我想他们可以轻松地向插入并返回新字符串的标准库添加一个方法.但是,如果调用该方法insert,初学者可能会认为它会改变字符串; 为了描述它必须被称为new_with_inserted或类似的东西.在日常使用中,"插入"意味着您更改插入的内容(例如,将信封插入邮箱会更改邮箱的内容).同样,这提出了一个问题,"为什么我不能改变我的数据存储?"
Ruby提供了对象的冻结,因此可以安全地传递它们而不会引入微妙的错误.好处是Ruby像处理任何其他数据结构(数组,哈希,类实例)一样处理字符串; 他们都可以被冻结.一致性是程序员友好的.不可变的字符串使字符串作为"特殊"数据结构脱颖而出,如果不是真的,如果将它用作数据存储.
| 归档时间: |
|
| 查看次数: |
6224 次 |
| 最近记录: |