|
|
1
16
没有 一些 可变类型,你必须全力以赴地进行纯粹的函数式编程,这是一种完全不同于OOP和过程式编程的模式,后者目前最受欢迎,而且,虽然非常强大,但对很多程序员来说显然非常具有挑战性(当你 做 在没有什么是可变的语言中需要副作用,当然在现实的编程中不可避免地需要副作用,这是挑战的一部分——haskell的 Monads 例如,这是一种非常优雅的方法,但是您知道有多少程序员完全并且自信地理解它们,并且能够使用它们以及典型的OOP构造?-) 如果你不理解拥有多个范例的巨大价值(两个都是FP-One 和 最关键的是依赖可变数据),我建议学习哈里迪和范罗伊的杰作, Concepts, Techniques, and Models of Computer Programming ——“A” SICP “对于21世纪”,正如我曾经描述的那样;-)。 大多数程序员,无论是否熟悉Haridi和van Roy,都会欣然承认至少 一些 可变数据类型对它们很重要。尽管我从你的问题中引用了一个完全不同的观点的句子,但我相信这也可能是你困惑的根源: 不 “为什么每种都有”,而是“为什么有的” 不变的 “完全”。 “完全可变”方法曾(意外)在Fortran实现中获得。如果你有,说,
然后是一个程序片段,例如,
将打印23,然后打印0 23号 已经发生了变异,所以在程序的其余部分中对23的所有引用实际上都指向0。从技术上讲,这不是编译器中的一个错误:Fortran对程序是什么有着微妙的规则,并且不允许在将常量和变量传递给分配给其参数的过程中执行这些操作,而且这个代码段违反了那些鲜为人知的、非编译器可执行的规则,所以它只是程序中的一个,而不是编译器中的一个。当然,在实践中,这种方式导致的错误数量是不可接受的,因此在这种情况下,典型的编译器很快就转向破坏性较低的行为(如果操作系统支持,将常量放入只读段以获取运行时错误;或者,传递新的 复制 而不是常量本身,尽管有开销;等等),即使从技术上来说,它们是程序错误,允许编译器“正确”地显示未定义的行为;-)。
在其他语言中执行的另一种选择是增加参数传递的多种方式的复杂性——最明显的可能是C++,用值、引用、常数引用、指针、常量指针、…当然,您会看到程序员被诸如
实际上,algol-68可能沿着这个方向走得更远(如果您可以有一个值和一个引用,为什么不引用一个引用呢?还是参考参考?&C--algol 68对此没有任何限制,定义正在发生的事情的规则可能是“真正使用的”编程语言中发现的最微妙、最难的混合。早期的C(只通过值和显式指针——不
Java和Python(在其他语言中)用一个简单的强大的弯刀穿过这个灌木丛:所有的参数传递, 和 所有赋值都是“按对象引用”(从不引用变量或其他引用,从不语义上隐式复制,&c)。将(至少)数字定义为语义上不可变的数字,通过避免“oopse”(如上面的Fortran代码所示),可以保持程序员的理智(以及语言简单性的这一宝贵方面)。 把字符串看作原语就像数字一样,与语言的高语义水平非常一致,因为在现实生活中,我们 做 需要与数字一样简单的字符串;将字符串定义为字符列表(haskell)或字符数组(c)等替代方法对编译器(在这种语义下保持高效的性能)和程序员(有效地忽略这种任意结构,以使字符串能够作为simp使用)都构成了挑战。le原语,正如现实编程经常需要的那样)。
通过添加一个简单的不可变容器,python做得更进一步。(
|
|
|
2
2
不过,我不确定这是否符合非技术条件:如果字符串是可变的,那么大多数(*)集合都需要对其字符串键进行私有复制。 否则,将“foo”键从外部更改为“bar”将导致“bar”位于集合的内部结构中,而“foo”是预期的。这样,“foo”查找会找到“bar”,这不是一个问题(什么也不返回,重新索引有问题的键),但“bar”查找找不到任何问题,这是一个更大的问题。 (*)在每次查找时对所有键进行线性扫描的哑集合不必这样做,因为它自然会适应键的更改。 |
|
|
3
1
没有 总体的、基本的 不具有可变字符串的原因。对于它们的不可变性,我发现最好的解释是它促进了一种更为实用、副作用更小的编程方式。最后变得更干净,更优雅,更像是蟒蛇。
从语义上讲,它们应该是不变的,不是吗?弦
|
|
|
4
1
不确定您是否会将其视为“技术低级别”的好处,但不可变字符串隐式线程安全这一事实为您节省了大量线程安全编码工作。 有点玩具的例子… 线程A-检查登录名为foo的用户有权执行某些操作,返回true 线程B-将用户字符串修改为登录名栏 线程A-由于以前对foo的权限检查,使用登录名栏执行一些操作。 字符串不能更改的事实为您节省了防范这种情况的努力。 |
|
|
5
1
如果你想要完全一致,你只能 一切不变 因为可变的bools或ints根本没有意义。事实上,有些函数语言就是这样做的。 python的哲学是“简单胜于复杂”。在C语言中,您需要意识到字符串会发生变化,并思考这会如何影响您。python假设字符串的默认用例是“将文本放在一起”——您完全不需要了解字符串来完成这项工作。但是如果你 希望 要更改字符串,只需使用更合适的类型(即列表、字符串IO、模板等)。 |
|
|
6
1
在具有用户定义类型的引用语义的语言中,具有可变字符串将是一个desaster,因为每次分配一个字符串变量时,都要对可变字符串对象进行别名,并且必须在各处进行防御性复制。这就是为什么字符串在爪哇和C中是不可变的——如果字符串对象是不可变的,那么它指向多少变量并不重要。 注意,在C++中,两个字符串变量从不共享状态(至少在概念上)——技术上,可能存在。 写上拷贝 继续,但由于多线程场景中的效率低下,这已经过时了)。 |
|
|
7
1
如果字符串是可变的,那么字符串的许多使用者将不得不对其进行复制。如果字符串是不可变的,那么这就不那么重要了(除非不可变是由硬件互锁强制实现的,否则对于一些具有安全意识的字符串使用者来说,如果给定的字符串没有它们应该的那样不可变,那么制作它们自己的副本可能不是一个坏主意)。 StringBuilder类非常好,不过我认为如果它有一个“value”属性(read相当于toString,但它会出现在对象检查器中;write允许直接设置整个内容)和默认的扩展转换为字符串的话会更好。从理论上讲,将可变字符串类型派生自具有字符串的公共祖先是很好的,因此可以将可变字符串传递给一个不关心字符串是否可变的函数,尽管我怀疑依赖于字符串具有特定固定实现这一事实的优化可能不太有效。 |
|
|
8
1
程序员的主要优点是,使用可变字符串时,您不必担心谁会更改您的字符串。因此,您不必有意识地决定“我应该在这里复制这个字符串吗?”. |
|
|
Emanuel Pinho · 无不变目标push的角度变化检测策略 7 年前 |
|
|
MingtyeP · 如何使用不可变js取消移动列表中的每个元素? 7 年前 |
|
|
Brannon · 让赋值运算符在申报时工作 7 年前 |
|
|
Javallion · JAVA中的不可变对象初始化 7 年前 |
|
|
Ankush Pandit · 字符串与字符串数组元素之间的比较 7 年前 |
|
|
plamkata__ · Swift到Kotlin,管理不可变列表 8 年前 |