Language agnostic 什么';“s”是非变异基因的最佳名称;加上「;不可变集合上的方法?

Language agnostic 什么';“s”是非变异基因的最佳名称;加上「;不可变集合上的方法?,language-agnostic,naming-conventions,list,immutability,Language Agnostic,Naming Conventions,List,Immutability,很抱歉,这是一个空谈的标题——如果我能想出一个简洁的标题,我就不必问这个问题了 NNString *empty = [[NSString alloc] init]; NSString *list1 = [empty stringByAppendingString:@"Hello"]; NSString *list2 = [list1 stringByAppendingString:@"immutable"]; NSString *list3 = [list2 stringByAppendingS

很抱歉,这是一个空谈的标题——如果我能想出一个简洁的标题,我就不必问这个问题了

NNString *empty = [[NSString alloc] init];
NSString *list1 = [empty stringByAppendingString:@"Hello"];
NSString *list2 = [list1 stringByAppendingString:@"immutable"];
NSString *list3 = [list2 stringByAppendingString:@"word"];
假设我有一个不可变的列表类型。它有一个操作
Foo(x)
,该操作返回一个新的不可变列表,其中指定的参数作为末尾的额外元素。因此,要建立一个值为“Hello”、“immutable”、“world”的字符串列表,您可以编写:

var empty=newImmutableList();
var list1=empty.Foo(“Hello”);
var list2=list1.Foo(“不可变”);
var list3=list2.Foo(“单词”);
(这是C#代码,如果你觉得语言很重要,我最感兴趣的是C#建议。这根本不是语言问题,但语言的习惯用法可能很重要。)

重要的是,现有列表不会被
Foo
更改,因此
为空。Count
仍将返回0

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

var list=new ImmutableList().Foo(“你好”)
.Foo(“不可变”)
.Foo(“字”);
我的问题是:Foo最好的名字是什么?

edit3:正如我稍后所揭示的,类型的名称实际上可能不是
ImmutableList
,这就清楚了位置。相反,想象一下它是
TestSuite
,它是不可变的,因为它所属的整个框架是不可变的

(编辑3结束)

到目前为止,我已经提出了一些选择:

  • Add
    :在.NET中很常见,但意味着原始列表的变异
  • Cons
    :我相信这是函数式语言中的正常名称,但对那些没有此类语言经验的人来说毫无意义
  • Plus
    :到目前为止我最喜欢的,它对我来说并不意味着突变。显然,这也是一个问题,但期望值略有不同(Haskell程序员可能希望它将两个列表添加到一起,而不是向另一个列表添加一个值)
  • With
    :与其他一些不变的约定一致,但在IMO中没有完全相同的“附加性”
  • :描述性不强
  • 操作符重载为+:我真的不太喜欢这个;我一般认为运算符应该只应用于较低级别的类型。不过我愿意被说服
我选择的标准是:

  • 给出方法调用结果的正确印象(即,它是带有额外元素的原始列表)
  • 尽可能清楚地表明它不会改变现有列表
  • 在上面第二个例子中,链接在一起听起来很合理
如果我说得不够清楚,请询问更多细节

编辑1:以下是我选择
Plus
而不是
Add
的理由。考虑这两行代码:

list.Add(foo);
列表加(foo);
在我看来(这是个人的事情),后者显然是有缺陷的——就像写“x+5;”作为自己的陈述一样。第一行看起来没问题,直到你记住它是不可变的。事实上,
plus
是我最喜欢的另一个原因,原因是加号运算符本身不改变其操作数。没有操作符重载的轻微不适,它仍然给出了相同的含义,包括(对我来说)不改变操作数(在本例中是方法目标)

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

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

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

var list=newImmutableList();
列表。添加(“foo”);
不会有任何成就,但当您将其更改为:

var-suite=newtestsuite();
suite.Add(x=>x.Length);
看起来应该没问题。然而,对我来说,这让错误更为明显:

var-suite=newtestsuite();
suite.Plus(x=>x.Length);
这只是乞求:

var-suite=newtestsuite().Plus(x=>x.Length);
理想情况下,我希望我的用户不必被告知测试套件是不可变的。我希望他们落入成功的深渊。这可能不可能,但我想试试


我为只讨论不可变的列表类型而过分简化了原始问题而道歉。并不是所有的集合都像
不可变列表
:)

那样具有自描述性,我最终在中为所有不可变集合使用了Add。原因是它是一个容易预测的名字。我不太担心人们将Add与变异Add混淆,因为类型名称的前缀是Immutable

有一段时间,我考虑了Cons和其他功能性风格的名称。最后我打折了,因为他们不太出名。当然,函数式程序员会理解,但他们不是大多数用户

其他名称:您提到:

  • 另外:我对这件衣服很感兴趣。对我来说,这并不重要
    void test()
    {
      Bar bar = new Bar();
      List list = bar.AfterAppending("foo");
    }
    
    var list = ImmutableList<string>.Empty.And("Hello")
                                          .And("Immutable")
                                          .And("Word");
    
    object.With("My new item as well");
    
    object.AlongWith("this new item");
    
    AddToCopy
    RemoveFromCopy
    InsertIntoCopy
    
    Add 1 to 2 and you get 3
    
    var p = listA.Concat(listB);
    var k = listA.Concat(item);
    
    x = 2 + 2;
    
    var empty = new ImmutableList<string>();
    var list1 = empty + "Hello";
    var list2 = list1 + "immutable";
    var list3 = list2 + "word";
    
    var list = new ImmutableList<string>("Hello");
    var list2 = list.Copy().With("World!");
    
    var list1 = new ImmutableList<string>("Hello");
    var list2 = list1.Copy(list => list.Add("World!"));
    
    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);
    }
    
    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!"));
    
    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")
    );
    
    var suite = new TestSuite<string, int>(x => x.Length);
    var otherSuite = suite.Copy(rules => 
      rules
        .Append(x => Int32.Parse(x))
        .Append(x => x.GetHashCode())
    );
    
    NNString *empty = [[NSString alloc] init];
    NSString *list1 = [empty stringByAppendingString:@"Hello"];
    NSString *list2 = [list1 stringByAppendingString:@"immutable"];
    NSString *list3 = [list2 stringByAppendingString:@"word"];