为什么许多编程语言中的集合没有真正设置?

Der*_*k W 5 c# java logic programming-languages set

在几种编程语言中,存在集合集合,它们应该是有限集合的数学概念的实现.

但是,这不一定是真的,例如在C#和中Java,两种实现都HashSet<T>允许您添加任何HashSet<T>集合作为其自身的成员.其中一个数学集的现代定义是不允许的.

背景:

根据朴素集理论,集合的定义是:

集合是不同对象的集合.

然而,这个定义引人注目的是罗素的悖论以及其他悖论.为方便起见,Russel's Paradox是:

设R是不属于自己的所有集合的集合.如果R不是它自己的成员,那么它的定义规定它必须包含它自己,如果它包含它自己,那么它与它自己的定义相矛盾,因为它不是自身成员的所有集合的集合.

所以根据现代集合论(参见:ZFC),集合的定义是:

集合是不同对象的集合,其中没有一个是集合本身.

具体而言,这是规律性公理的结果.

那么什么呢?这有什么影响?为什么StackOverflow上有这个问题?

罗素悖论的一个含义是并非所有集合都是集合.此外,这是数学家将集合的定义作为通常的英语定义.所以我认为这个问题在编程语言设计方面有很大的重要性.

问题(S):

那么为什么编程语言,在某种形式下,在他们的设计中使用这些原则,只是在他们的语言库中实现Set时忽略它?

其次,这是否与数学概念的其他实现相同?

也许我有点挑剔,但如果这些是真正的集合实现,那么为什么部分定义会被忽略?

更新

添加C#和Java代码片段,例证行为:

Java代码段:

Set<Object> hashSet = new HashSet<Object>();
hashSet.add(1);
hashSet.add("Tiger");
hashSet.add(hashSet);
hashSet.add('f');

Object[] array = hashSet.toArray();
HashSet<Object> hash = (HashSet<Object>)array[3];

System.out.println("HashSet in HashSet:");       
for (Object obj : hash)
    System.out.println(obj);

System.out.println("\nPrinciple HashSet:");
for (Object obj : hashSet)
    System.out.println(obj);
Run Code Online (Sandbox Code Playgroud)

打印出来:

HashSet in HashSet:
f
1
Tiger
[f, 1, Tiger, (this Collection)]

Principle HashSet:
f
1
Tiger
[f, 1, Tiger, (this Collection)]
Run Code Online (Sandbox Code Playgroud)

C#代码段:

HashSet<object> hashSet = new HashSet<object>();
hashSet.Add(1);
hashSet.Add("Tiger");
hashSet.Add(hashSet);
hashSet.Add('f');

object[] array = hashSet.ToArray();
var hash = (HashSet<object>)array[2];

Console.WriteLine("HashSet in HashSet:");
foreach (object obj in hash)
     Console.WriteLine(obj);

Console.WriteLine("\nPrinciple HashSet:");
foreach (object obj in hashSet)
     Console.WriteLine(obj);
Run Code Online (Sandbox Code Playgroud)

打印出来:

HashSet in HashSet:
1
Tiger
System.Collections.Generic.HashSet`1[System.Object]
f

Principle HashSet:
1
Tiger
System.Collections.Generic.HashSet`1[System.Object]
f
Run Code Online (Sandbox Code Playgroud)

更新2

关于Martijn Courteaux的第二点,即它可以以计算效率的名义完成:

我在C#中创建了两个测试集合.它们是相同的,除了其中一个的Add方法 - 我添加了以下检查:要添加到集合中的项目在if (this != obj)哪里obj.

我将它们分别计时,以便添加100,000个随机整数:

带检查: ~28毫秒

没有检查: ~21毫秒

这是一个相当重要的性能跳跃.

Ale*_*nov 9

编程语言集实际上不像ZFC集,但原因与你想象的完全不同:

  1. 你不能通过理解形成一个集合(即所有对象的集合,如......).请注意,这已经阻止了所有(我相信)天真的集理论悖论,所以它们是无关紧要的.

  2. 他们通常不能无限.

  3. 存在不是集合的对象(在ZFC中只有集合).

  4. 它们通常是可变的(即您可以在集合中添加/删除元素).

  5. 它们包含的对象可以是可变的.

所以答案

那么为什么编程语言,在某种形式下,在他们的设计中使用这些原则,只是在他们的语言库中实现Set时忽略它?

是语言使用这些原则.

  • 使用#1轻微狡辩:你可以在现有的集合*中形成所有对象的集合*(我不知道Java/C#,但是像`set.filter(predicate)`这样的东西),这反映了ZFC的理解公理(并因此阻止悖论).但是,编程语言并没有(直接)在ZFC上找到它们. (2认同)
  • @ AntalS-Z,我相信它对应于分离的Axiom(模式),而不是理解.ZFC不允许(不受限制)理解. (2认同)