在不可变集合上使用不变异的“添加”方法的最佳名称是什么?


229

对不起,标题太小了-如果我能拿出一个简洁的标题,则不必提这个问题。

假设我有一个不变的列表类型。它具有一个操作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-因此empty.Count仍将返回0。

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

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

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

编辑3:正如我稍后会透露的那样,类型的名称实际上可能不是ImmutableList<T>,这使位置很明确。而是想象TestSuite它是不可变的,因为它所包含的整个框架都是不可变的...

(编辑结束3)

到目前为止,我已经提出的选项:

  • Add:.NET中常见,但表示原始列表已更改
  • Cons:我相信这是功能语言中的正常名称,但对没有使用这些语言经验的人来说毫无意义
  • Plus:到目前为止,我最喜欢的这并不意味着对我有所改变。显然,这在Haskell中使用过,但期望值稍有不同(Haskell程序员可能希望它将两个列表加在一起,而不是将一个值添加到另一个列表中)。
  • With:与其他一些不可变的约定一致,但与IMO的“附加性”并不完全相同。
  • And:不是很描述。
  • +的运算符重载:我真的不是很喜欢。我通常认为运算符应仅应用于较低级别的类型。我愿意被说服!

我要选择的标准是:

  • 给出方法调用结果的正确印象(即它是带有额外元素的原始列表)
  • 尽可能清楚地表明它不会对现有列表进行变异
  • 如上面的第二个示例中所述,当链接在一起时听起来很合理

如果我不够清晰,请询问更多详细信息...

编辑1:这是我倾向于Plus的原因Add。考虑以下两行代码:

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

在我看来(这个人的事情),后者显然是越野车-就像写“ x + 5;”一样。作为自己的陈述。第一行看起来还可以,直到您记住它是不可变的。实际上,加号运算符本身不会改变其操作数的方式Plus是我最喜欢的另一个原因。在没有轻微的运算符重载的情况下,它仍然具有相同的含义,包括(对我而言)不对操作数进行突变(在这种情况下为方法目标)。

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

各种答案都是有效的:“使用Add。这就是正确的方法DateTime,并且String具有Replace使不变性不明显的方法等。” 我同意-这里有优先权。然而,我见过很多人打电话DateTime.AddString.Replace期望突变。有许多新闻组问题(如果我深入研究,可能还有SO问题),它们的回答是“您忽略了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>:) 一样具有自我描述性:


2
@亚当:不,后者显然是越野车。他们俩实际上都是越野车(因为他们对结果什么也没做)-但第一个看上去对我来说不是越野车。
乔恩·斯基特

36
乱猫是狗吗?
迈克尔·迈尔斯

7
Concat / Condog ...对我有用!;)
gnovice

11
Uncat-那将是僵尸猫。
Erik Forbes,2009年

2
@陷阱:虽然使API变得流畅,这很糟糕。
乔恩·斯基特

Answers:


130

在这种情况下,我通常会选择Concat。在我看来,这通常意味着正在创建一个新对象。

var p = listA.Concat(listB);
var k = listA.Concat(item);

3
这就是我使用的,因为这就是System.Linq.Enumerable的用途-决定已经做出。:)我不能是唯一在IEnumerable上定义自己的Concat扩展的重载的人,以接受要附加的单个值。
Daniel Earwicker 09年

9
+1这是在框架内保持命名一致性正确答案。
山姆·哈威尔

除非我没有丢失它,否则System.Linq.Enumerable(通常是Linq)仅将Concat()用于“序列+序列”,而不是“项目+序列”。明确指出有人“可能希望它将两个列表加在一起而不是将一个值添加到另一个列表中”的问题是作为不使用其他原始选项之一的原因。
Ssswift

119

我会选择Cons,原因很简单:这就是您想要的。

  1. 我非常喜欢确切地说出我的意思,尤其是在源代码中。一个新手将只需要查询一次Cons的定义,然后阅读并使用它一千次。我发现,从长远来看,即使使前期成本稍高一些,使用使普通情况更容易的系统也更好。

  2. 对于没有FP经验的人来说,这将是“无意义的”,这实际上是一个很大的优势。正如您所指出的那样,您发现的所有其他单词已经具有某些含义,并且该含义有些许不同或不明确。一个新概念应有一个新词(或在本例中为一个旧词)。我宁愿有人必须查找Cons的定义,而不是错误地假设他知道Add的作用。

  3. 从功能语言借用的其他操作通常保持其原始名称,而不会造成明显的灾难。我还没有看到为非FPers听起来更熟悉的“ map”和“ reduce”同义词提出的任何推动力,也没有看到这样做的任何好处。

(完全公开:我是Lisp程序员,所以我已经知道Cons的含义。)


16
不过,请不要忘记可发现性很重要-如果我键入“ testSuite”。并查看方法列表,我想看看一个建议正确方法的方法。我可能不会在我想的时候找一个荒谬的(对我来说)名字。
乔恩·斯基特

33
如果我觉得很老套,我会做一个方法Add,它简单地抛出一个带有message =“ Use Cons to prepend to ImmutableList”的异常。:-)
肯(Ken)

2
它不会杀死任何人,只需阅读几行评论,解释其名称的真实含义,并引用它们,例如,Abelson&Sussman的“计算机程序的结构和解释”。
John R. Strohm

16
传统上,缺点在开头而不是结尾处添加。因此,它可能是所描述方法的误导性名称。
walkytalky

16
只是为了保存下一个非功能性程序员的单击或单击3 ... en.wikipedia.org/wiki/Cons中的“ construct”一词,表达式“ cons x to y”意味着使用(缺点(xs)
Myster 2010年

59

其实我喜欢And,尤其是惯用的方式。如果您对Empty列表有一个静态的只读属性,并且可能将构造函数设为私有,那么我特别喜欢它,因此您始终必须从Empty列表进行构建。

var list = ImmutableList<string>.Empty.And("Hello")
                                      .And("Immutable")
                                      .And("Word");

我喜欢空的想法。仍然不相信,虽然。只是有点等等。
乔恩·斯基特

似乎更像是我想如何用自然语言构造事物列表。如果您大声朗读,它似乎比“添加”或“加号”更直观。“列表”为空列表,“您好”,“不可变”和“单词”为空。我同意,尽管如此,孤立性尚不明确。
tvanfosson

52

每当我遇到术语命名的果酱时,我都会碰到互连网。

thesaurus.com将其返回“添加”:

定义:邻接,增加;发表进一步评论

同义词:词缀,附件,ante,附加,增加,增强,增强,建立,充电,继续,提示,计算,充实,加热,远足,远足,搭便车,钩,钩与,包括,顶起,爵士乐,加入一起,垫,拼写,背piggy式,插入,倒入,回复,跑起来,进一步说,巴掌,雪球,汤,加快,钉,踩,补充,甜味,增粘,标签

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


1
我也有点像“加入”,但是在大多数情况下,当您连接2个对象时,最终得到1。在这种情况下,如果您连接2个对象,则实际上是在创建一个新对象。
Outlaw程序员,

1
我不知道在.NET,Perl,PHP甚至VBScript中Join暗示突变的任何情况。这种设计使得A和B联合成为C,其中C始终是一个新实体。
spoulson

我喜欢Join,并且我完全同意thesaurus.com的观点:)如果对名称有疑问,请一直使用它。
Skurmedel

var suite = new TestSuite <string,int>().Join(x => x.Length);
狡猾的狮

3
和piggyback一起去吧。或HookUpWith。
克里斯·马拉斯蒂·乔治

48

就个人而言,我喜欢.With()。如果我使用的是对象,则在阅读文档或代码注释后,将清楚其作用,并且在源代码中显示为ok。

object.With("My new item as well");

或者,您添加“ Along” .. :)

object.AlongWith("this new item");

+1。“ WITH”是SETL中的中缀运算符,它执行相同的操作。如果SETL使用它,那么它必须是正确的:-)
finnw

1
Bah ...谁在使用VB?:)嗯..Op ..那声音很大吗?呵呵。。但是,完全不这样,这就是为什么我考虑使用“ AlongWith”,这将消除VB问题。他只能使用大约一百万种不同的方式...我的意思是,即使是疯狂的像:object.Plus()或Object.ExistingPlus()...等...这是一个该死的好问题贴出来,但是......嘿嘿..
LarryF

33

我最终为BclExtras中的所有不可变集合添加了Add。原因是它是一个易于预测的名称。我不担心人们将Add与mutable add混淆,因为类型的名称以Immutable为前缀。

有一段时间我考虑了Cons和其他功能样式名称。最终,我打折了它们,因为它们的知名度不高。当然,功能性程序员会理解的,但并不是大多数用户。

其他名称:您提到:

  • 加:我希望/正在为此洗。对我来说,这与Add一样,不再将其区分为不可变异的操作
  • 使用:将导致VB问题(双关语意)
  • 运算符重载:可发现性将是一个问题

我考虑的选项:

  • Concat:字符串是不可变的,并使用它。不幸的是,这只是增加结尾的好处
  • CopyAdd:复制什么?来源,清单?
  • AddToNewList:也许是List的好选择。但是收集,堆栈,队列等等呢?

不幸的是,似乎没有一个词是

  1. 绝对是一成不变的行动
  2. 大多数用户都可以理解
  3. 少于4个字即可代表

当您考虑List以外的集合时,它会变得更加奇怪。以堆栈为例。即使是第一年的程序员也可以告诉您Stacks具有Push / Pop对方法。如果您创建一个ImmutableStack并给它一个完全不同的名称,那么将其命名为Foo / Fop,您就为他们使用收藏添加了更多的工作。

编辑:对Plus的回应

我知道您在使用Plus。我认为一个更强的案例实际上是要删除的减号。如果我看到以下内容,我肯定会想知道程序员在想什么

list.Minus(obj);

我在使用正/负号或新配对时遇到的最大问题是感觉像是过分杀伤力。集合本身已经有一个专有名称,即Immutable前缀。为什么还要添加词汇表,以增加与Immutable前缀相同的区别呢?

我可以看到呼叫站点参数。从单个表达式的角度来看,它变得更加清晰。但是就整个功能而言,这似乎是不必要的。

编辑2

同意String.Concat和DateTime.Add确实使人们感到困惑。我已经看到几个非常聪明的程序员遇到了这个问题。

但是我认为ImmutableList是一个不同的论点。关于String或DateTime,没有什么可以将其确定为对程序员不可变的。您必须简单地知道它通过其他来源是不可变的。因此,这种混乱并不意外。

ImmutableList没有这个问题,因为名称定义了它的行为。您可能会说人们不知道什么是不可变的,我认为这也是有效的。我当然直到大学二年级才知道。但是,无论您选择什么名称而不是添加,都会遇到相同的问题。

编辑3:不可变但不包含单词的类型如TestSuite呢?

我认为这带动了您不应该发明新方法名称的想法。即,因为显然存在使类型不可变以便于并行操作的驱动力。如果您专注于更改集合方法的名称,则下一步将是使用的每种不可变类型上的方法名称更改。

我认为,将精力集中在使类型可识别为不可变上将是一项更有价值的工作。这样一来,您就可以解决问题,而无需重新考虑所有的变异方法模式。

现在如何将TestSuite识别为不可变的?在当今的环境中,我认为有几种方法

  1. 带不可变前缀:ImmutableTestSuite
  2. 添加一个描述免疫级别的属性。这当然是很难发现的
  3. 没什么。

我的猜测/希望是,开发工具将开始通过简单地通过视觉识别不可变类型(不同的颜色,更强的字体等)来开始解决此问题。但是我认为,尽管改变了所有方法名称,但这还是答案。


已为我选择加号而不是添加到问题添加了原因。欢迎对此推理发表评论。我真的很愚蠢。
乔恩·斯基特

@JaredPar:如果该类型称为TestSuite怎么办?
乔恩·斯基特

很想再给+1进行编辑3,但显然不能。(在我的情况下,我并不想尝试并行化-我相信不变性会导致更容易推理的代码。)我仍然不太相信Add是可行的方法,但是这里对in的支持有说服力。
乔恩·斯基特

如果您碰巧将这个问题放到工作中进行对话,顺便说一句,那也很棒。我从C#列表开始讨论,因此可能已经有一些同事参与了。可能也会在Google内部询问...
Jon Skeet

@Jon,我想我是个放下这个问题的好地方:)
JaredPar

27

我认为这可能是少数情况下可以让+操作员超载的情况之一。在数学术语中,我们知道+不会将某些内容附加到其他内容的末尾。它总是将两个值组合在一起,并返回一个新的结果值。

例如,很明显,当您说

x = 2 + 2;

x的结果值为4,而不是22。

同样,

var empty = new ImmutableList<string>();
var list1 = empty + "Hello";
var list2 = list1 + "immutable";
var list3 = list2 + "word";

应该弄清楚每个变量将要保存什么。应该清楚的list2是,最后一行没有更改,而是list3分配了将“ word”附加到的结果list2

否则,我只是将函数命名为Plus()。


如果您有一个通用列表,可以在其中合法地添加一个整数(例如)另一个整数列表,该怎么办?然后+的这种使用将与串联冲突。
finnw

@finnw:我不明白你的意思。无论您要添加一个元素还是多个元素,我总是希望列表带有+表示附加。
比尔蜥蜴

4
对于可重用的API,最好有一个命名方法,以防有人在使用某种语言的情况下使用您的类而不会导致运算符重载。
尼尔

“您要添加一个还是多个元素”-如果要将列表添加为单个元素怎么办?即,[1] + 2 = [1,2]但是[1] + [2] = [1,[2]]。您的建议是行为不一致。这可能就是为什么Python不允许您以这种方式添加一个元素的原因。
mpen 2010年

好吧,在像C#这样的静态类型语言中,您可以知道列表元素的类型是列表列表还是元素列表,因此您可以使用该类型来确定是添加一个元素还是列表或串联这两个列表。
Dobes Vandermeer 2014年

22

为了尽可能清晰,您可能希望使用wordier CopyAndAdd或类似的名称。


并非所有不可变集合都需要添加副本。考虑不可变的树,它们只需要一个新节点即可将现有的树用作叶子。
JaredPar

顺便说一句,我阅读了您的个人资料,然后按年龄排序,并对您的年龄感到惊讶。此后不久,理智就开始了。
JaredPar

重新评论:我很少使用树木,以至于我从未想到过这种想法。这是一个好点。
迈克尔·迈尔斯

关于第二个评论:我承认,我是为徽章做的!我只是不想透露自己的年龄。(我实际上比你还年轻,但如果需要的话,我可以打这只老顽童。而且,我并不是唯一一位年龄列在89岁的老者。)
Michael Myers

不变的树木论点是一个有力的优点。因此,EquivalentReferenceWithAdded(x)会与该参数抗衡,但听起来很愚蠢,并且很难推论。
TheBlastOne

21

如果您觉得自己很冗长,我会称其为Extend()ExtendWith()

扩展意味着将某些内容添加到其他内容而不进行更改。我认为这是C#中非常相关的术语,因为它类似于扩展方法的概念-它们将“新”方法添加到类中,而不用“接触”类本身。

否则,如果您真的想强调一点根本不修改原始对象,那么使用诸如Get-之类的前缀对于我来说是不可避免的。


1
还是有点暗示对基础对象做些什么。
混乱

18

已添加(),已添加()

我喜欢使用过去式进行不可变对象的操作。它传达了您无需更改原始对象的想法,并且在看到原始对象时很容易识别。

另外,由于变异方法名称通常是当前时态动词,因此它适用于您遇到的大多数不可变方法名称需要的情况。例如,一个不可变的堆栈具有方法“ pushed”和“ popped”。


1
Python也使用此约定。例如内置函数reversed()和sorted()。

18

我喜欢mmyers对CopyAndAdd的建议。为了与“变异”主题保持一致,也许您可​​以选择Bud(无性繁殖),GrowReplicateEvolve?=)

编辑:继续我的遗传主题,Procreate怎么样,这意味着基于上一个对象创建了一个新对象,但是添加了一些新对象。


14

这可能是一个延伸,但是在Ruby中,有一个常用的符号来区分:add不变异;不变异;不变异。add!变异。如果这是项目中普遍存在的问题,您也可以这样做(不一定使用非字母字符,而是始终使用表示法来表示变异/非变异方法)。


+1。这不是由语言强制执行的,而是作为约定达成的。我喜欢。
oma


13

可能是由于您希望一次执行两个操作而造成的困惑。为什么不将它们分开?DSL风格:

var list = new ImmutableList<string>("Hello");
var list2 = list.Copy().With("World!");

Copy将返回一个中间对象,该对象是原始列表的可变副本。With将返回一个新的不可变列表。

更新:

但是,围绕中间可变的集合不是一个好方法。中间对象应包含在Copy操作中:

var list1 = new ImmutableList<string>("Hello");
var list2 = list1.Copy(list => list.Add("World!"));

现在,该Copy操作将使用一个委托,该委托将接收一个可变列表,以便它可以控制复制结果。它除了添加元素(如删除元素或对列表进行排序)外,还可以做更多的事情。也可以在ImmutableList构造函数中使用它来组装初始列表,而无需中间不可变列表。

public ImmutableList<T> Copy(Action<IList<T>> mutate) {
  if (mutate == null) return this;
  var list = new List<T>(this);
  mutate(list);
  return new ImmutableList<T>(list);
}

现在,用户不再可能产生误解,他们自然会陷入成功的陷阱

另一个更新:

如果仍然不喜欢提到可变列表,即使现在已经包含可变列表,您也可以设计一个规范对象,该对象将指定script,复制操作将如何转换其列表。用法将是相同的:

var list1 = new ImmutableList<string>("Hello");
// rules is a specification object, that takes commands to run in the copied collection
var list2 = list1.Copy(rules => rules.Append("World!"));

现在,您可以使用规则名称来发挥创造力,并且只能公开要Copy支持的功能,而不是的全部功能IList

对于链接的用法,您可以创建一个合理的构造函数(当然,它不会使用链接):

public ImmutableList(params T[] elements) ...

...

var list = new ImmutableList<string>("Hello", "immutable", "World");

或在另一个构造函数中使用相同的委托:

var list = new ImmutableList<string>(rules => 
  rules
    .Append("Hello")
    .Append("immutable")
    .Append("World")
);

假设rules.Append方法返回this

这是您的最新示例的外观:

var suite = new TestSuite<string, int>(x => x.Length);
var otherSuite = suite.Copy(rules => 
  rules
    .Append(x => Int32.Parse(x))
    .Append(x => x.GetHashCode())
);

@Jordao:因为这种组合会导致更简单的初始化形式。当我只想要一个变量时,为什么要有两个单独的变量?同样,我也不想创建一个可变的副本-我希望所有内容在整个过程中都是不可变的,因为这会导致生成更容易理解的IMO代码。
乔恩·斯基特

与“加号”等相比,所有这些仍然比较笨拙。感谢涉及突变的想法,但是我绝对喜欢“保持不变”的方法。
乔恩·斯基特

也许到时候,对于操作的真正语义是什么总是会有误解。如果遵循规范对象路线,则不会发生任何突变(至少不是在外部发生),该对象仅指定新的不可变对象的外观。您所拥有的是从一个不变的对象到另一个不变的对象的操作,并且由于它被称为复制,所以没有误会的余地。
Jordão酒店

唯一适用于您的名称似乎是复合名称,例如CopyAndAppend,CopyAndAdd等。
Jordão2010年

1
实际上,我对这种方法(包括所有修改)越来越喜欢作为不可变集合的API。但是,我认为将这种方法与默认规范的辅助方法(例如Concat)结合使用,可以兼得两全。

11

一些随机的想法:

  • ImmutableAdd()
  • 附加()
  • ImmutableList <T>(ImmutableList <T> originalList,T newItem)构造函数

1
为ImmutableAdd +1;不热衷于Append(与StringBuilder.Append十分相似),构造器版本在链接方面很痛苦。
乔恩·斯基特

10

C#中的DateTime使用添加。那么为什么不使用相同的名称呢?只要您的班级用户了解班级是不可变的。


我认为众所周知DateTime.Add会使人们感到困惑...但是我同意它显示了优先级。
乔恩·斯基特

1
就像使字符串发生突变的方法一样,新开发人员也会感到困惑。但是很快每个人都知道“字符串是不可变的”
Tundey

9

我认为您要表达的关键点是难以排列,这就是非排列,因此其中可能包含生成词,例如CopyWith()或InstancePlus()。


9

我认为英语在使用动词与“添加”相同的含义时不会让您以明确的方式暗示不变性。“加号”几乎可以做到,但人们仍然会犯错误。

要防止用户将对象误认为是可变的对象,唯一的方法是通过对象本身的名称或方法的名称(例如“ GetCopyWith”或“ “ CopyAndAdd”)。

因此,只需加上您喜欢的“加号”即可。


9

首先,一个有趣的起点:http : //en.wikipedia.org/wiki/Naming_conventions_(编程) ...特别是,请检查底部的“另请参阅”链接。

实际上,我赞成Plus或And。

加号和加号在词源方面均基于数学。因此,两者都意味着数学运算。两者都产生一个自然读为可解析为值的表达式的表达式,该表达式适合具有返回值的方法。 And具有附加的逻辑含义,但是两个词都直观地应用于列表。 Add表示对对象执行的操作,该操作与方法的不可变语义冲突。

两者都很短,鉴于操作的原始性,这一点尤其重要。简单,经常执行的操作应使用较短的名称。

表达不变的语义是我更喜欢通过上下文进行的操作。也就是说,我只是简单地暗示整个代码块都具有功能感。假设一切都是不变的。但是,那可能只是我。我更倾向于不变性。如果完成了,那么它在同一个地方做了很多;可变性是个例外。


8

Chain()或Attach()呢?


1
附着肯定听起来像是在变异。也许WithAttached会更明智,但与上文已讨论过的WithAdded非常接近。
TheBlastOne 2011年

有趣的是,在描述尝试执行此操作时提到了“链接”多少次。(5次),但不作为建议!visualthesaurus.com当我搜寻时,这是第一件事(没有从属关系)concatenate
cod3monk3y 2014年

7

我更喜欢加号(和减号)。它们很容易理解,并直接映射到涉及众所周知的不可变类型(数字)的操作。2 + 2不会更改2的值,它会返回一个同样不变的新值。

其他一些可能性:

拼接()

接枝()

Accrete()


6

对于那些遵守的人,matemateWithcoitus怎么样。在繁殖方面,通常认为哺乳动物是不可变的。

也要把联盟扔在那里。从SQL借来的。


2
为联盟+1。但是,我直接从集合论中借用了它。:-)
Christoffer Lette 09年

SQL不会从集合论中获得很多术语吗?
杰森D

1
另外,Union表示区别。如果要包括重复项(至少在TSQL中),则必须显式使用Union All。

6

显然,我是第一个回答这个问题的Obj-C / Cocoa人。

NNString *empty = [[NSString alloc] init];
NSString *list1 = [empty stringByAppendingString:@"Hello"];
NSString *list2 = [list1 stringByAppendingString:@"immutable"];
NSString *list3 = [list2 stringByAppendingString:@"word"];

不会因此赢得任何代码高尔夫比赛。


[object]By[Verb]ing[Object]:对该方法的前缀+1 意味着将返回一个新字符串[verb][Object]:,而不是simple,这将就地改变对象。
Dave DeLong

3
+1。我不理解人们对冗长(又称自我证明)的厌恶。
hatfinch 2011年

5

我认为“添加”或“加号”听起来不错。列表本身的名称应足以传达列表的不变性。


没有清单,是一个测试套件。
tstenner'2

5

也许有些单词让我更想起我制作副本并向其中添加内容,而不是使实例发生变异(例如“连接”)。但是我认为,对于其他动作而言,使这些词语具有一定的对称性也是一件好事。我不知道与“删除”类似的词,就像“连接”一样。“加”对我来说听起来有点奇怪。我不希望它在非数字上下文中使用。但这也可能来自我的非英语背景。

也许我会用这个方案

AddToCopy
RemoveFromCopy
InsertIntoCopy

当我考虑这些的时候,它们都有自己的问题。有人可能会认为他们删除了某些内容或在给定的参数中添加了一些内容。完全不确定。我认为这些词在链接中也不能很好地发挥作用。太罗to了,无法输入。

也许我只是使用简单的“添加”和朋友。我喜欢它在数学中的用法

Add 1 to 2 and you get 3

好吧,当然,2仍然是2,您会得到一个新数字。这大约是两个数字,而不是列表和元素,但是我认为它具有一些类比。我认为,add并不一定意味着您要突变某些东西。我当然知道您的观点,即拥有仅包含an add且不使用返回的新对象的孤独语句看起来并不容易。但是我现在也考虑了使用“ add”以外的其他名称的想法,但我只是想不出另一个名称,除非让我认为“嗯,我需要查看文档以了解什么”。它是关于”,因为它的名称不同于我期望的“添加”名称。只是有些奇怪的想法,一点也不知道它是否有意义:)


但是在不可变集合中并非总是需要副本。以二叉树为例。添加新的根无需复制,只需复制一个新值,其中的叶子之一就是老树
JaredPar 2009年

吻-如果命名开始包含实现细节,则所有方法名称都将变得过长。“添加”非常简单,可以完成工作。
mP。

1
@mP:再次以我认为不合适的方式使用短语“实施细节”。无论是链接列表还是后台数组都是实现细节。我可以更改实现而无需更改API。不变的方面不是实现细节。
乔恩·斯基特

1
对。JaredPar,但我认为它是否实际上复制树还是仅使用现有树并将其用作返回的新树的叶子也并不重要。我的意思是,只是实现细节。(我相信)java的字符串类的子字符串操作是相同的。
Johannes Schaub-litb


5

我认为,Plus()Minus(),或者Including()Excluding()是在合理的暗示一成不变的行为。

但是,没有任何命名选择可以使每个人都完全清楚,因此我个人认为,一个好的xml doc注释在这里会走很长的路。当您在IDE中编写代码时,VS会将这些正确地呈现给您-很难忽略它们。


4

Append-因为,请注意,System.String方法的名称表明它们会使实例发生变异,但事实并非如此。

或者我很喜欢AfterAppending

void test()
{
  Bar bar = new Bar();
  List list = bar.AfterAppending("foo");
}

像之前的DateTime参数一样,如果不是因为这么多的程序员确实希望字符串方法可以完成工作,我也会同意优先级。必须(有时是反复地)告诉他们字符串是不可变的。我想吸引我的客户开发人员进入成功之路:)
Jon Skeet

我喜欢越来越多地追加。它可以区分您不是在变异集合,而是加入它。

4

list.CopyWith(element)

和Smalltalk一样:)

并且还list.copyWithout(element)删除所有出现的元素,这list.copyWithout(null)在删除未设置的元素时最有用。


3

我会去添加,因为我可以看到更好的名称的好处,但是问题是要为每个其他不可变的操作找到不同的名称,如果这有意义的话,这可能会使类非常陌生。


是的,我明白你的意思。我认为我仍然更喜欢Plus,但这是值得考虑的一点。
乔恩·斯基特

谢谢乔恩。我期待使用您的框架。我刚刚读了一下,看起来非常不错。再次感谢。
Joan Venge
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.