是什么让Swift认为[String]是Int?

时间:2014-11-08 15:41:23

标签: arrays swift

我可以写一些简短有效的代码示例:

var array = ["one","two"];
var name = array[0];

一切都好。没有错误。 name现在包含one

现在假设我写道:

var array = ["one","two"];
var name = array["0"];

成为一个错误,并明确原因:数组不是字典,我应该通过索引访问它。

为什么错误说“类型 Int 不符合协议ExtendedGraphemeClusterLiteralConvertible

为什么Int,如果是[String]

<小时/> 顺便说一句,如果我以另一种方式产生错误

var array = ["one":0,"two":1];
var name = array[0];

很明显:“类型DictionaryIndex<String, Int>不符合协议IntegerLiteralConvertible

3 个答案:

答案 0 :(得分:2)

该错误消息是因为您提供字符串文字,而不是String类型的实例,编译器期望Int(因为那&#39} ; Array的下标方法接受的内容。编译器 将字符串文字转换为类型Int的实例的方式是使用StringLiteralConvertibleExtendedGraphemeClusterLiteralConvertible协议中的方法,因此它会检查查看Int类型是否符合其中之一。由于Int 不符合,您会收到您正在查看的错误消息。

这解释了Daniel T的其他信息:

var array = ["one","two"]
array["0"]                // trying to convert string literal to Int

var foo: Int = "0"        // trying to convert string literal to Int

var index = "0"
array[index]              // trying to convert String instance to Int

同样,您的最后一个示例显示编译器尝试相同的事情 - 尝试将整数文字转换为DictionaryIndex<String, Int>的实例,因为Dictionary实例&#39; s下标可以传递给该词典的一个实例Key类型一个DictionaryIndex<Key, Value>

答案 1 :(得分:1)

声明为subscript的{​​p> Array

struct Array<T> : MutableCollectionType, Sliceable {
    //... 
    subscript (index: Int) -> T

期望Int作为索引。如果你这样做:

array["0"]

这是错误的,因为"0"不是Int。但是,换句话说,如果"0"可以是Int,那就没问题。

在这里,"0"是什么在Swift?它的字符串,但实际上是ExtendedGraphemeClusterLiteral。 Swift有两种字符串文字类型,ExtendedGraphemeClusterLiteralStringLiteral

  • "" empty→StringLiteral
  • "A"只有一个字符→ExtendedGraphemeClusterLiteral
  • "AB"两个或多个字符→StringLiteral

无论如何,在Playground尝试这个:

extension Int: ExtendedGraphemeClusterLiteralConvertible {
    typealias ExtendedGraphemeClusterLiteralType = String
    public init(unicodeScalarLiteral value: String) {
        self = value.toInt() ?? 0
    }
    public init(extendedGraphemeClusterLiteral value: String) {
        self = value.toInt() ?? 0
    }
}

var array = ["one","two"];
var name = array["0"]; // -> "one"

&#34;输入&#39; Int&#39;不符合协议&#39; ExtendedGraphemeClusterLiteralConvertible&#39;&#34;意味着...

编译器:&#34;如果Int符合ExtendedGraphemeClusterLiteralConvertible,我可以编译它!&#34;

答案 2 :(得分:0)

有趣的是,如果你这样做:

var array = ["one","two"];
var index = "0"
var name = array[index];

错误将是'String' is not convertible to 'Int'

我认为这是因为系统试图将"0"转换为Int,这意味着要进行大量的协议检查。 Array的索引类型可以转换为Self.Index,这是一个ForwardIndexType ......好吧,事情变得很奇怪。

而Swift对隐式变量类型转换有强有力的规则。因此,如果您使用变量作为索引,则更清楚。

请注意,var foo: Int = "0"会产生与array["0"]相同的错误。