对不起,我的标题太含糊了——如果我能想出一个简洁的标题,我就不用问这个问题了。

假设我有一个不可变的列表类型。它有一个操作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#建议,如果你觉得语言很重要的话。这根本不是一个语言问题,但语言中的习语可能很重要。)

重要的是现有的列表不会被Foo改变,所以是空的。Count仍然返回0。

另一种(更习惯的)达到最终结果的方式是:

var list = new ImmutableList<string>().Foo("Hello")
                                      .Foo("immutable")
                                      .Foo("word");

我的问题是:Foo最好的名字是什么?

编辑3:正如我稍后所揭示的,类型的名称实际上可能不是ImmutableList<T>,这使得位置很清楚。相反,想象它是TestSuite,它是不可变的,因为它所在的整个框架是不可变的……

(编辑3结束)

到目前为止,我想到的选项是:

Add: common in .NET, but implies mutation of the original list Cons: I believe this is the normal name in functional languages, but meaningless to those without experience in such languages Plus: my favourite so far, it doesn't imply mutation to me. Apparently this is also used in Haskell but with slightly different expectations (a Haskell programmer might expect it to add two lists together rather than adding a single value to the other list). With: consistent with some other immutable conventions, but doesn't have quite the same "additionness" to it IMO. And: not very descriptive. Operator overload for + : I really don't like this much; I generally think operators should only be applied to lower level types. I'm willing to be persuaded though!

我选择的标准是:

给出方法调用结果的正确印象(即它是带有额外元素的原始列表) 尽可能清楚地表明它不会改变现有的列表 当像上面的第二个例子一样连接在一起时,听起来很合理

如果我说得不够清楚,请再问我一些细节。

编辑1:以下是我更喜欢Plus而不是Add的理由。考虑以下两行代码:

list.Add(foo);
list.Plus(foo);

在我看来(这是我个人的观点),后者显然是有问题的——它就像写“x + 5;”作为一个单独的语句。第一行看起来是可以的,直到您记得它是不可变的。事实上,加号操作符本身不改变操作数的方式是我最喜欢加号的另一个原因。没有操作符重载的麻烦,它仍然具有相同的含义,其中包括(对我来说)不改变操作数(在本例中是方法目标)。

编辑2:不喜欢添加的原因。

各种各样的回答都很有效:“使用Add。这就是DateTime所做的,而String有Replace方法等,这些方法不会使不可变性变得明显。”我同意,这里有优先权。然而,我见过很多人称之为DateTime。添加或字符串。替换并期待突变。有大量的新闻组问题(如果我仔细研究的话,可能会有这样的问题),这些问题的答案是“您忽略了String.Replace的返回值;字符串是不可变的,返回一个新的字符串"

现在,我应该揭示这个问题的一个微妙之处——类型实际上可能不是一个不可变列表,而是一个不同的不可变类型。特别是,我正在开发一个基准测试框架,在该框架中,您可以向套件中添加测试,并创建一个新的套件。这可能是显而易见的:

var list = new ImmutableList<string>();
list.Add("foo");

不会完成任何事情,但当你把它改成:

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);

理想情况下,我希望我的用户不必被告知测试套件是不可变的。我想让他们坠入成功的深渊。这可能是不可能的,但我想试试。

很抱歉,我只讨论了不可变的列表类型,过度简化了最初的问题。并非所有的集合都像ImmutableList<T>:)那样具有自描述性。


当前回答

我喜欢和()。我认为它最不可能含糊不清。我能想到的唯一冲突是逻辑上的,我不认为这是c#开发人员的问题,即使是VB,我认为上下文使它不太可能引起问题,任何问题都会在编译时迅速被发现。在英语中,“对这些和那个做点什么”或“把这些和那个放进盒子里”也很有效。

我想用()就可以了。我担心的是,它可能看起来有点像linq Where<>方法,特别是如果有一个lambda作为参数。我脑子里的英文也不太清楚,尤其是“Do something to These With That”。

我不喜欢. plus()。我不能忘记它是Add的同义词:加号=加号= + = Add。

其他回答

每当我在命名法上遇到麻烦时,我就会上网。

Thesaurus.com返回"add":

定义:相邻,增加;使 进一步的评论 同义词:词缀, Annex, ante, append, augment, beef 向上,提升,建立,充电, 继续,插入,插入,肉体 出去,热身,徒步,徒步,搭顺风车, 勾上,勾搭上,包括,杰克 振作起来,振作起来,团结起来, 利用,背上,插入,倒入 上,回答,跑上去,进一步说,拍 雪球,煮汤,加速, Spike, step up, supplement, sweet, 标签,标签

我喜欢Adjoin的发音,或者更简单地说,Join。这就是你在做的,对吧?该方法也可以应用于加入其他ImmutableList<>。

任何暗示将返回相同类型的对象的名称都可以使用。Plus是一个很好的名称,就好像你加了两个对象,希望返回结果。

不过,在这种情况下,Plus听起来不像是使用的正确名称,因为您正在将一个测试“Plus”到一个测试套件中。

对我来说,GetWith()听起来像是一个选项。或者GetTypeWith(),其中类型显然是您使用的类型。例如:

var list = new ImmutableList<String>();
var list2 = list.GetWith("First");
var list3 = list2.GetWith("Second");

// OR

var list2 = list.GetListWith("First");

Get表示您正在获取已经包含的列表,With表示您还需要另一个对象。CopyWith()也符合这个标准。

我认为GetWith的直接问题是它不容易被猜测。开发人员想要添加一个套件,而不是获得当前的套件。我会立即输入。add,希望情报显示的东西非常接近我的预期。

添加(),附加()

我喜欢对不可变对象的操作使用过去时。它传达的意思是,你并没有改变原来的对象,而且当你看到它时很容易认出它。

此外,因为改变方法名通常是现在时态的动词,所以它适用于您遇到的大多数需要不可变方法名的情况。例如,一个不可变堆栈有“push”和“pop”方法。

为了尽可能清楚,您可能需要使用更冗长的CopyAndAdd或类似的东西。

我不认为英语语言会让你在使用与“添加”意思相同的动词时,以一种明确无误的方式暗示不变性。“加”几乎就可以了,但人们仍然会犯错误。

防止用户将对象误认为可变对象的唯一方法是通过对象本身的名称或方法的名称(如“GetCopyWith”或“CopyAndAdd”等详细选项)显式地使其显式。

所以就用你最喜欢的"加"吧