"表达式的类型是不明确的,没有更多的上下文" Swift闭包中的错误

时间:2016-01-05 20:24:22

标签: swift cocoa compiler-errors swift2

我在Swift代码中遇到了与类型相关的奇怪错误:

  

表达式的类型是不明确的,没有更多的上下文。

即使我提供了完整的类型信息,也会发生这种情况。

这是复制它的代码。

我有2个结构:

struct Person{
    let name_ : String
    let address_ : Address
}

struct Address {
    let street_ : String
    let city_ : String
}

然后我创建一个包含2个函数的结构来获取和设置address的{​​{1}}:

Person

当我尝试创建一个获取并设置地址的Lens实例时(在后面的例子中它返回一个带有新地址的新Person),我在第一个闭包中得到了错误。

struct Lens<A,B> {
    let extract: (A)->B
    let create: (B,A) -> A
}

不仅在镜头类型中指定了第一个闭包的参数类型,而且在闭包本身中也是如此。

发生了什么????

2 个答案:

答案 0 :(得分:3)

虽然它表明错误在extract,但它确实在create$0$1是向后的。您引用的是$0.name_,但$0关闭的createBAddress,但name_属性Person。我想你的意思是:

let lens : Lens<Person, Address> = Lens(
    extract: { $0.address_ },
    create: { Person(name_: $1.name_, address_: Address(street_: $0.street_, city_: $1.address_.city_)) }
)

或者您可以重新定义Lens

struct Lens<A, B> {
    let extract: (A) -> B
    let create: (A, B) -> A   // note, A & B swapped
}

然后你可以这样做:

let lens : Lens<Person, Address> = Lens(
    extract: { $0.address_ },
    create: { Person(name_: $0.name_, address_: Address(street_: $1.street_, city_: $0.address_.city_)) }
)

或许,你的意思是:

let lens : Lens<Person, Address> = Lens(
    extract: { $0.address_ },
    create: { Person(name_: $0.name_, address_: $1) }
)

这样,create同时使用所提供地址的街道和城市。 (使用地址的街道,但不是城市,对我来说没有意义。)

答案 1 :(得分:2)

lens的初始化将使用如下表单:

let lens = Lens<Person, Address>(
    extract: {p in p.address_},
    create: {(a,p) in Person(name_: p.name_, address_: Address(street_: a.street_, city_: p.address_.city_))})

正如Martin R所说,唯一的错误实际上是create关闭。当您为结构调用默认初始值设定项时,默认情况下需要为所有自变量(即使是第一个)提供外部名称(=内部名称)(这与常规函数不同,在常规函数中可省略第一个的外部名称函数参数)。还要确保为初始化程序提供正确的参数类型。

请注意,您无需提供闭包类型((p:Person)->Address in ...),因为Swift可以从闭包中推断(并期望这一点):p in ...就足够了(参见上面的示例)。或者,更加精简,在闭包中省略显式变量名称,并使用$0$1(预期参数)引用,就像在Robs解决方案中一样。