什么是“一些"?Swift(UI) 中的关键字? [英] What is the "some" keyword in Swift(UI)?

查看:28
本文介绍了什么是“一些"?Swift(UI) 中的关键字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

新的 SwiftUI 教程有以下代码:

struct ContentView: View {
    var body: some View {
        Text("Hello World")
    }
}

第二行单词some,并在他们的网站上突出显示,就好像它是一个关键字.

The second line the word some, and on their site is highlighted as if it were a keyword.

Swift 5.1 似乎没有将 some 作为关键字,而且我看不出 some 这个词还能在那里做什么,因为它出现在类型通常去.是否有新的未宣布的 Swift 版本?它是以我不知道的方式在类型上使用的函数吗?

Swift 5.1 does not appear to have some as a keyword, and I don't see what else the word some could be doing there, since it goes where the type usually goes. Is there a new, unannounced version of Swift? Is it a function that's being used on a type in a way I didn't know about?

关键字some有什么作用?

推荐答案

some View不透明结果类型types.md" rel="noreferrer">SE-0244 并且在 Swift 5.1 和 Xcode 11 中可用.您可以将其视为反向"通用占位符.

some View is an opaque result type as introduced by SE-0244 and is available in Swift 5.1 with Xcode 11. You can think of this as being a "reverse" generic placeholder.

与调用方满足的常规通用占位符不同:

Unlike a regular generic placeholder which is satisfied by the caller:

protocol P {}
struct S1 : P {}
struct S2 : P {}

func foo<T : P>(_ x: T) {}
foo(S1()) // Caller chooses T == S1.
foo(S2()) // Caller chooses T == S2.

不透明结果类型是实现满足的隐式通用占位符,所以你可以这样想:

An opaque result type is an implicit generic placeholder satisfied by the implementation, so you can think of this:

func bar() -> some P {
  return S1() // Implementation chooses S1 for the opaque result.
}

看起来像这样:

func bar() -> <Output : P> Output {
  return S1() // Implementation chooses Output == S1.
}

事实上,此功能的最终目标是允许以这种更明确的形式进行反向泛型,这也可以让您添加约束,例如 -><T:收藏>T 其中 T.Element == Int.查看此帖子了解更多信息.

In fact, the eventual goal with this feature is to allow reverse generics in this more explicit form, which would also let you add constraints, e.g -> <T : Collection> T where T.Element == Int. See this post for more info.

主要的一点是,返回 some P 的函数是返回符合 的特定 single 具体类型的值的函数P.尝试在函数内返回不同的符合类型会产生编译器错误:

The main thing to take away from this is that a function returning some P is one that returns a value of a specific single concrete type that conforms to P. Attempting to return different conforming types within the function yields a compiler error:

// error: Function declares an opaque return type, but the return
// statements in its body do not have matching underlying types.
func bar(_ x: Int) -> some P {
  if x > 10 {
    return S1()
  } else {
    return S2()
  }
}

由于隐式泛型占位符不能被多种类型满足.

As the implicit generic placeholder cannot be satisfied by multiple types.

这与返回P的函数形成对比,它可以用来表示both S1S2> 因为它代表一个任意的 P 符合值:

This is in contrast to a function returning P, which can be used to represent both S1 and S2 because it represents an arbitrary P conforming value:

func baz(_ x: Int) -> P {
  if x > 10 {
    return S1()
  } else {
    return S2()
  }
}

好的,那么不透明结果类型有什么好处->一些 P 有超过协议返回类型 ->P?

Okay, so what benefits do opaque result types -> some P have over protocol return types -> P?

协议当前的一个主要限制是 PAT(具有关联类型的协议)不能用作实际类型.尽管这一限制很可能会在该语言的未来版本中取消,因为不透明结果类型实际上只是通用占位符,它们现在可以与 PAT 一起使用.

A major current limitation of protocols is that PATs (protocols with associated types) cannot be used as actual types. Although this is a restriction that will likely be lifted in a future version of the language, because opaque result types are effectively just generic placeholders, they can be used with PATs today.

这意味着您可以执行以下操作:

This means you can do things like:

func giveMeACollection() -> some Collection {
  return [1, 2, 3]
}

let collection = giveMeACollection()
print(collection.count) // 3

<小时>

2.不透明的结果类型具有标识

因为不透明的结果类型强制返回单个具体类型,所以编译器知道对同一个函数的两次调用必须返回两个相同类型的值.


2. Opaque result types have identity

Because opaque result types enforce a single concrete type is returned, the compiler knows that two calls to the same function must return two values of the same type.

这意味着您可以执行以下操作:

This means you can do things like:

//   foo() -> <Output : Equatable> Output {
func foo() -> some Equatable { 
  return 5 // The opaque result type is inferred to be Int.
}

let x = foo()
let y = foo()
print(x == y) // Legal both x and y have the return type of foo.

这是合法的,因为编译器知道 xy 具有相同的具体类型.这是 == 的重要要求,其中Self 类型的两个参数.

This is legal because the compiler knows that both x and y have the same concrete type. This is an important requirement for ==, where both parameters of type Self.

protocol Equatable {
  static func == (lhs: Self, rhs: Self) -> Bool
}

这意味着它需要两个与具体符合类型相同类型的值.即使 Equatable 可用作类型,您也无法比较两个任意的 Equatable 符合值,例如:

This means that it expects two values that are both the same type as the concrete conforming type. Even if Equatable were usable as a type, you wouldn't be able to compare two arbitrary Equatable conforming values with each other, for example:

func foo(_ x: Int) -> Equatable { // Assume this is legal.
  if x > 10 {
    return 0
  } else {
    return "hello world"      
  }
}

let x = foo(20)
let y = foo(5)
print(x == y) // Illegal.

由于编译器无法证明任意两个 Equatable 值具有相同的底层具体类型.

As the compiler cannot prove that two arbitrary Equatable values have the same underlying concrete type.

以类似的方式,如果我们引入另一个不透明类型返回函数:

In a similar manner, if we introduced another opaque type returning function:

//   foo() -> <Output1 : Equatable> Output1 {
func foo() -> some Equatable { 
  return 5 // The opaque result type is inferred to be Int.
}

//   bar() -> <Output2 : Equatable> Output2 {
func bar() -> some Equatable { 
  return "" // The opaque result type is inferred to be String.
}

let x = foo()
let y = bar()
print(x == y) // Illegal, the return type of foo != return type of bar.

示例变得非法,因为虽然 foobar 都返回 some Equatable,但它们的反向"通用占位符 Output1Output2 可以满足不同的类型.

The example becomes illegal because although both foo and bar return some Equatable, their "reverse" generic placeholders Output1 and Output2 could be satisfied by different types.

与常规协议类型值不同,不透明结果类型与常规通用占位符组合得很好,例如:

Unlike regular protocol-typed values, opaque result types compose well with regular generic placeholders, for example:

protocol P {
  var i: Int { get }
}
struct S : P {
  var i: Int
}

func makeP() -> some P { // Opaque result type inferred to be S.
  return S(i: .random(in: 0 ..< 10))
}

func bar<T : P>(_ x: T, _ y: T) -> T {
  return x.i < y.i ? x : y
}

let p1 = makeP()
let p2 = makeP()
print(bar(p1, p2)) // Legal, T is inferred to be the return type of makeP.

如果 makeP 刚刚返回 P,这将不会起作用,因为两个 P 值可能具有不同的底层具体类型,例如:

This wouldn't have worked if makeP had just returned P, as two P values may have different underlying concrete types, for example:

struct T : P {
  var i: Int
}

func makeP() -> P {
  if .random() { // 50:50 chance of picking each branch.
    return S(i: 0)
  } else {
    return T(i: 1)
  }
}

let p1 = makeP()
let p2 = makeP()
print(bar(p1, p2)) // Illegal.

<小时>

为什么在具体类型上使用不透明的结果类型?

此时你可能会想,为什么不把代码写成:


Why use an opaque result type over the concrete type?

At this point you may be thinking to yourself, why not just write the code as:

func makeP() -> S {
  return S(i: 0)
}

好吧,使用不透明的结果类型允许您通过仅公开 P 提供的接口来使类型 S 成为实现细节,从而使您可以灵活地更改后面的具体类型不会破坏任何依赖于函数的代码.

Well, the use of an opaque result type allows you to make the type S an implementation detail by exposing only the interface provided by P, giving you flexibility of changing the concrete type later down the line without breaking any code that depends on the function.

例如,您可以替换:

func makeP() -> some P {
  return S(i: 0)
}

与:

func makeP() -> some P { 
  return T(i: 1)
}

不破坏任何调用 makeP() 的代码.

without breaking any code that calls makeP().

请参阅语言指南的不透明类型部分Swift 进化提案 了解更多信息关于此功能.

See the Opaque Types section of the language guide and the Swift evolution proposal for further information on this feature.

这篇关于什么是“一些"?Swift(UI) 中的关键字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆