推断常量 'spacesLeft' 具有类型 '()',这可能是 Swift 的意外

Posted

技术标签:

【中文标题】推断常量 \'spacesLeft\' 具有类型 \'()\',这可能是 Swift 的意外【英文标题】:Constant 'spacesLeft' inferred to have type '()', which may be unexpected Swift推断常量 'spacesLeft' 具有类型 '()',这可能是 Swift 的意外 【发布时间】:2017-07-20 15:19:32 【问题描述】:

我正在使用 Xcode 8 和 Swift 构建一个带有 AI 的井字游戏。以下是我正在使用的导致错误的相关变量:

var allSpaces: Set<Int> = [1,2,3,4,5,6,7,8,9]
var playerOneMoves = Set<Int>()
var playerTwoMoves = Set<Int>()
var nextMove: Int? = nil

在定义 AI 将如何播放的函数内部有以下变量:

var count = 0

let spacesLeft = allSpaces.subtract(PlayerOneMoves.union(playerTwoMoves))

后者导致编译器警告:

推断常量 'spacesLeft' 具有类型 '()',这可能是意料之外的

下面有一个 if 语句说:

if allSpaces.subtract(playerOneMoves.union(playerTwoMoves)).count > 0 
nextMove = spacesLeft[spacesLeft.startIndex.advancedBy(Int(arc4random_uniform(UInt32(spacesLeft.count))))]


条件给出以下错误:

元组类型'()'的值没有成员'count'

该语句给出以下错误:

类型'()'没有下标成员

我正在努力寻找解决方案。

【问题讨论】:

【参考方案1】:

subtract原地修改Set不返回值,你要使用subtracting

【讨论】:

【参考方案2】:

对于第一个警告,subtract 返回Void,所以使用subtracting

let spacesLeft = allSpaces.subtracting(playerOneMoves.union(playerTwoMoves))

对于第二个错误,advancedBy 已弃用,您可以这样更改:

if spacesLeft.count > 0 
    nextMove = spacesLeft[spacesLeft.index(spacesLeft.startIndex, offsetBy: Int(arc4random_uniform(UInt32(spacesLeft.count))))]

【讨论】:

【参考方案3】:

Set.subtract 是一个变异函数,所以它修改了Set,它的返回值是Void,这只是一个空元组() 的类型别名,因此是警告。

您应该调用Set.substracting,这是subtract 的非变异版本并返回Set&lt;Set.Element&gt;

【讨论】:

【参考方案4】:

subtract(_:) 函数是一个变异函数,所以它会变异你用来调用函数的 Set

来自Apple Docs:

subtract(_:)

从这个集合中移除给定集合的元素。

你得到错误的原因是因为这个函数返回Void,它在Swift中是一个空元组的类型别名(from Swift's source code)。因为Void没有下标也没有count你得到的属性/变量那些错误。

也许你应该看看subtracting(_:) 函数,它返回一个不同的Set

来自Apple Docs:

subtracting(_:)

返回一个新集合,其中包含该集合中未出现在给定集合中的元素。

【讨论】:

以上是关于推断常量 'spacesLeft' 具有类型 '()',这可能是 Swift 的意外的主要内容,如果未能解决你的问题,请参考以下文章

KotlinKotlin 变量与常量 ( 变量声明 | 只读变量 | 类型推断 | 编译时常量 | Kotlin 字节码查看面板 | Kotlin 引用数据类型 )

2.5.2节练习

在 TypeScript 中,如何在具有多个类型参数的方法中推断出泛型类型参数?

为啥泛型 T 仅在具有约束时才被推断为文字类型?

值限制 - 该值已被推断为具有泛型类型

Kotlin 变量和常量的声明(var和val)