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结束)
到目前为止,我已经提出了一些选择:
:在.NET中很常见,但意味着原始列表的变异Add
:我相信这是函数式语言中的正常名称,但对那些没有此类语言经验的人来说毫无意义Cons
:到目前为止我最喜欢的,它对我来说并不意味着突变。显然,这也是一个问题,但期望值略有不同(Haskell程序员可能希望它将两个列表添加到一起,而不是向另一个列表添加一个值)Plus
:与其他一些不变的约定一致,但在IMO中没有完全相同的“附加性”With
:描述性不强和
- 操作符重载为+:我真的不太喜欢这个;我一般认为运算符应该只应用于较低级别的类型。不过我愿意被说服李>
- 给出方法调用结果的正确印象(即,它是带有额外元素的原始列表)
- 尽可能清楚地表明它不会改变现有列表
- 在上面第二个例子中,链接在一起听起来很合理
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"];