为什么 Xcode 一直用“_”替换泛型
Why Xcode keeps substituting generics with '_'
我正在用 Swift 5 和 Vapor 3 制作一个服务器。在设置路由时,我想从我的控制器调用一个函数,returns 是一个可选的函数,如下所示:
//Person.swift
struct Person: Content {
...
}
//PersonController.swift
func update(_ request: Request) throws -> Future<Person> {
let uuid = try request.parameters.next(UUID.self)
return try request.content.decode(Person.self).flatMap { content in
request.withPooledConnection(to: DatabaseIdentifier<PostgreSQLDatabase>.psql) { connection in
/*
* No code completion beyond this point,
* even connection appears as type '_' instead of
* PostgreSQLConnection (not relevant to the question tho,
* just worth noting)
*/
if content.lastName != nil {
return connection.raw("Very long SQL query...")
.binds([...])
.first(decoding: Person.self)
}
return connection.raw("Other long SQL query")
.binds([...])
.first(decoding: Person.self)
}
}
}
router.put("people", UUID.parameter, use: personController.update)
但是我得到这个错误
Cannot convert value of type '(Request) throws -> EventLoopFuture<Person?>' to expected argument type '(Request) throws -> _'
我在使用 Vapor 时看到很多情况,其中 Xcode 只是放弃自动完成,所有内容都只是键入 _
。主要在用作回调的闭包内。这非常烦人,坦率地说,我不确定它是由于 Vapor、Swift 还是 Xcode 引起的。这是一个巨大的 PITA,但一旦我编译,它就会得到解决,类型就会被整理出来。但是在这种情况下它只是不起作用。
所以问题是:当 Request.put(_:use:)
的实际定义需要 (Request) throws -> T
时,为什么 Xcode 说预期类型是 (Request) throws -> _
以及这是如何造成的T
是 Future<Person>
和 Future<Person?>
之间的区别?
您在此处调用的 .first
方法:
return connection.raw("Other long SQL query")
.binds([...])
.first(decoding: Person.self)
Returns 一个 Future<Optional<Person>>
,或 Future<Person?>
。您路由处理程序的 return 类型是 Future<Person>
,因此您的 return 类型不正确。但即使您确实更改了处理程序的 return 类型,也无法修复它。
您的主要问题是您不能 return 路由处理程序中的可选项,因为 Optional
绝不会符合 ResponseEncodable
。如果需要,您可以自己添加一致性。
如果你不想添加一致性,你可以在解码查询结果后使用.unwrap(or:)
方法:
return connection.raw("Other long SQL query")
.binds([...])
.first(decoding: Person.self)
.unwrap(or: Abort(.notFound))
这将检查将来的值是否存在。如果是,则传递该值。否则,未来的链会收到您传入的错误,并且将改为 returned。
我正在用 Swift 5 和 Vapor 3 制作一个服务器。在设置路由时,我想从我的控制器调用一个函数,returns 是一个可选的函数,如下所示:
//Person.swift
struct Person: Content {
...
}
//PersonController.swift
func update(_ request: Request) throws -> Future<Person> {
let uuid = try request.parameters.next(UUID.self)
return try request.content.decode(Person.self).flatMap { content in
request.withPooledConnection(to: DatabaseIdentifier<PostgreSQLDatabase>.psql) { connection in
/*
* No code completion beyond this point,
* even connection appears as type '_' instead of
* PostgreSQLConnection (not relevant to the question tho,
* just worth noting)
*/
if content.lastName != nil {
return connection.raw("Very long SQL query...")
.binds([...])
.first(decoding: Person.self)
}
return connection.raw("Other long SQL query")
.binds([...])
.first(decoding: Person.self)
}
}
}
router.put("people", UUID.parameter, use: personController.update)
但是我得到这个错误
Cannot convert value of type '(Request) throws -> EventLoopFuture<Person?>' to expected argument type '(Request) throws -> _'
我在使用 Vapor 时看到很多情况,其中 Xcode 只是放弃自动完成,所有内容都只是键入 _
。主要在用作回调的闭包内。这非常烦人,坦率地说,我不确定它是由于 Vapor、Swift 还是 Xcode 引起的。这是一个巨大的 PITA,但一旦我编译,它就会得到解决,类型就会被整理出来。但是在这种情况下它只是不起作用。
所以问题是:当 Request.put(_:use:)
的实际定义需要 (Request) throws -> T
时,为什么 Xcode 说预期类型是 (Request) throws -> _
以及这是如何造成的T
是 Future<Person>
和 Future<Person?>
之间的区别?
您在此处调用的 .first
方法:
return connection.raw("Other long SQL query")
.binds([...])
.first(decoding: Person.self)
Returns 一个 Future<Optional<Person>>
,或 Future<Person?>
。您路由处理程序的 return 类型是 Future<Person>
,因此您的 return 类型不正确。但即使您确实更改了处理程序的 return 类型,也无法修复它。
您的主要问题是您不能 return 路由处理程序中的可选项,因为 Optional
绝不会符合 ResponseEncodable
。如果需要,您可以自己添加一致性。
如果你不想添加一致性,你可以在解码查询结果后使用.unwrap(or:)
方法:
return connection.raw("Other long SQL query")
.binds([...])
.first(decoding: Person.self)
.unwrap(or: Abort(.notFound))
这将检查将来的值是否存在。如果是,则传递该值。否则,未来的链会收到您传入的错误,并且将改为 returned。