Closed 。这个问题是基于意见的 /help/closed-questions 。目前不接受答案。
Locked 。这个问题及其答案是locked /help/locked-posts 因为这个问题是题外话,但却具有历史意义。目前不接受新的答案或互动。
抱歉这个华夫饼的标题——如果我能想出一个简洁的标题,我就不必问这个问题了。
假设我有一个不可变的列表类型。它有一个操作Foo(x)
它返回一个新的不可变列表,其中指定的参数作为末尾的额外元素。因此,要构建一个包含值“Hello”、“immutable”、“world”的字符串列表,您可以编写:
var empty = new ImmutableList<string>();
var list1 = empty.Foo("Hello");
var list2 = list1.Foo("immutable");
var list3 = list2.Foo("word");
(这是 C# 代码,如果您认为该语言很重要,我对 C# 建议最感兴趣。这从根本上来说不是一个语言问题,但该语言的习惯用法可能很重要。)
重要的是现有的列表是not 改变为Foo
- so empty.Count
仍然会返回 0。
获得最终结果的另一种(更惯用的)方法是:
var list = new ImmutableList<string>().Foo("Hello")
.Foo("immutable")
.Foo("word");
我的问题是:Foo 最好的名字是什么?
EDIT 3 :正如我稍后透露的,该类型的名称实际上可能不是ImmutableList<T>
,这使得立场明确。想象一下,它是TestSuite
它是不可变的,因为它所属的整个框架是不可变的......
(编辑3结束)
到目前为止我想到的选项:
Add
:在 .NET 中很常见,但意味着原始列表的变化
Cons
:我相信这是函数式语言中的正常名称,但对于那些没有此类语言经验的人来说毫无意义
Plus
:到目前为止我最喜欢的,这并不意味着突变to me 。显然这也是在哈斯克尔中使用 http://en.wikibooks.org/wiki/Haskell/MonadPlus 但期望略有不同(Haskell 程序员可能期望它将两个列表添加在一起,而不是向另一个列表添加单个值)。
With
:与其他一些不可变约定一致,但在我看来没有完全相同的“附加性”。
And
: 不太描述。
+ 的运算符重载:我真的不太喜欢这个;我通常认为运算符应该只应用于较低级别的类型。但我还是愿意被说服!
我选择的标准是:
给出方法调用结果的正确印象(即,它是带有额外元素的原始列表)
尽可能清楚地表明它不会改变现有列表
当像上面的第二个例子一样链接在一起时听起来很合理
如果我说得不够清楚,请询问更多细节......
EDIT 1: 这是我选择的理由Plus
to Add
。考虑这两行代码:
list.Add(foo);
list.Plus(foo);
在我看来(以及这个is 个人的事情)后者显然有错误 - 就像写“x + 5;”作为其本身的声明。第一行看起来没什么问题,直到您记住它是不可变的。事实上,加号运算符本身不会改变其操作数是另一个原因Plus
是我最喜欢的。没有操作符重载的轻微恶心,它仍然给出相同的含义,其中包括(对我来说)不改变操作数(或本例中的方法目标)。
EDIT 2: 不喜欢的原因添加。
各种答案都有效:“选择 Add。这就是DateTime
确实如此,并且String
has Replace
方法等不会使不变性变得明显。”我同意 - 这里有优先权。但是,我看到很多人打电话DateTime.Add
or String.Replace
and 期待突变 。有很多新闻组问题(如果我仔细研究的话,可能还有这样的问题),这些问题的答案是“你忽略了String.Replace
;字符串是不可变的,返回一个新字符串。”
现在,我应该揭示这个问题的微妙之处——类型可能not 实际上是一个不可变列表,但是是不同的不可变类型。特别是,我正在开发一个基准测试框架,您可以在其中将测试添加到套件中,然后创建一个新套件。很明显:
var list = new ImmutableList<string>();
list.Add("foo");
不会完成任何事情,但它会成为lot 当你将其更改为时更加模糊:
var suite = new TestSuite<string, int>();
suite.Add(x => x.Length);
这么看来应该没问题了。然而,对我来说,这使错误更加清晰:
var suite = new TestSuite<string, int>();
suite.Plus(x => x.Length);
这只是乞求:
var suite = new TestSuite<string, int>().Plus(x => x.Length);
理想情况下,我希望我的用户不必被告知测试套件是不可变的。我希望他们掉进成功的深渊。这may 不可能,但我想尝试一下。
我很抱歉通过仅讨论不可变列表类型来过度简化原始问题。并非所有集合都像ImmutableList<T>
:)