2014-11-08 124 views
0

我可以写一些代码短而有效的例子:是什么让Swift认为[String]是Int?

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

一切正常。没有错误。 name现在包含one

现在假设我写:

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

是一个错误,它清楚为什么:数组不是一本字典,我应该通过索引来访问它的内容。

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

为什么Int,如果是[String]


顺便说一句,如果我产生另外一个错误way

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

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

+0

因为数组索引应该是一个String类型,并且传递一个类型为String的参数意味着(它符合“ExtendedWhatever”长协议名称,无论它是什么)它不会找到匹配协议一致性。你是对的,如果错误信息反过来(或者抱怨'String'不符合固有的'Int'-ish'),那么错误信息可能会更直观,但嘿就是它的实现方式。 – 2014-11-08 15:45:23

回答

2

该错误信息是因为你提供一个字符串字面,不是String类型,其中编译器期待一个Int(因为这就是Array的标方法接受)的一个实例。编译器将字符串文字转换为Int类型的实例的方式是使用StringLiteralConvertibleExtendedGraphemeClusterLiteralConvertible协议中的方法,因此它会检查Int类型是否符合其中的一种。由于Int不符合,您会收到您所看到的错误消息。

这就解释了丹尼尔·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实例的标可以通过该字典的Key类型的实例 a DictionaryIndex<Key, Value>

0

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

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

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

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

尽管Swift对隐式变量类型转换有强大的规则。所以如果你使用一个变量作为索引,那就更清楚了。

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

1

Arraysubscript声明:

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

它预计Int为指标。那么,如果你这样做:

array["0"] 

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

在这里,"0"是什么在斯威夫特?它是字符串,但实际上它是ExtendedGraphemeClusterLiteral。 Swift有2个字符串文字类型,ExtendedGraphemeClusterLiteralStringLiteral

  • ""空→字符串文字
  • "A"一个字符→ExtendedGraphemeClusterLiteral
  • "AB"两个或多个字符→字符串文字

不管怎样,试试这个操场:

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" 

“输入'Int'不符合协议“ExtendedGraphemeClusterLiteralConvertible””是指...

编译:‘如果Int符合ExtendedGraphemeClusterLiteralConvertible,我可以编译这个’!

相关问题