【问题标题】:Tuple and Function Argument in SwiftSwift 中的元组和函数参数
【发布时间】:2015-07-09 14:37:53
【问题描述】:

在 Swift 中,元组与函数参数有什么关系?

在下面的两个示例中,函数返回相同的类型,即使一个采用元组,而另一个采用两个参数。从调用者的角度来看(不看代码),函数接受元组参数还是常规参数没有区别。

函数参数在某些方面与元组相关吗?

例如

func testFunctionUsingTuple()->(Int, String)->Void {
    func t(x:(Int, String)) {
        print("\(x.0) \(x.1)")
    }

    return t
}

func testFuncUsingArgs()->(Int, String)->Void {
    func t(x:Int, y:String) {
        print("\(x) \(y)")
    }

    return t
}

do {
    var t = testFunctionUsingTuple()
    t(1, "test")
}

do {
    var t = testFuncUsingArgs()
    t(1, "test")
}

在常规函数(而不是返回函数)中在函数参数中声明元组时,行为也存在不一致:

func funcUsingTuple(x:(Int, String)) {
    print("\(x.0) \(x.1)")
}

func funcUsingArgs(x:Int, _ y:String) {
    print("\(x) \(y)")
}

// No longer works, need to call funcUsingTuple((1, "test")) instead
funcUsingTuple(1, "test")   
funcUsingArgs(1, "test3")

更新:

Chris Lattner 对元组的澄清:

"x.0" 其中 x 是一个标量值产生该标量值,由于奇 涉及标量和标量之间过度隐式转换的行为 元组。这是一个待修复的错误。

在“let x = (y)”中,x 和 y 具有相同的类型,因为 (x) 是 括号(即分组)运算符的语法,而不是元组 编队运算符。没有单一元素这样的东西 未标记的元组值。

在“(foo: 42)”中——最常见于参数列表中—— 您正在生成一个带有元素标签的单个元素元组。 编译器目前正在努力消除它们并降级 它们是标量,但不一致(这也是一个错误)。 也就是说,单元素标记的元组是一回事。

【问题讨论】:

  • 在这个函数func funcUsingTuple(x:(Int, String))中你必须明确地传递一个元组:funcUsingTuple((1, "test"))
  • @Antonio 是的,我已经注意到了。问题是为什么当从函数返回相同的确切函数时我不需要做同样的事情? (见前面的例子)
  • @Boon,说真的,甚至连对相关讨论的每个实质性答案都投赞成票?
  • @GoZoner 感谢您的提醒,仍在进行中的积极讨论。赞成你的答案。尚未选择答案,因为没有答案涵盖问题的第二部分。

标签: swift tuples


【解决方案1】:

每个函数都只接受一个包含函数参数的元组。这包括没有参数的函数,它们将 () - 空元组 - 作为其一个参数。

以下是 Swift 编译器如何将各种括号形式转换为内部表示:

() -> Void
(x) -> x
(x, ...) -> [Tuple x ...]

并且,如果有 tuple? 函数,它将在以下位置返回 true:VoidX[Tuple x ...]

这是你的证明:

let t0 : () = ()
t0.0 // error

let t1 : (Int) = (100)
t1.0 -> 100
t1.1 // error

let t2 : (Int, Int) = (100, 200)
t2.0 -> 100
t2.1 -> 200
t2.2 // error

[大胆声明,目前没有 Swift 解释器。]

来自AirSpeedVelocity

但是等等,你会问,如果我传入除了元组以外的东西怎么办? 好吧,我回答(以一种深刻的哲学语气),什么是真正的 如果不是一个元素的元组,变量? Swift 中的每个变量都是 1 元组。事实上,每个非元组变量都有一个 .0 属性,即 该变量的值。4 打开一个游乐场并尝试一下。因此,如果 你传入一个非元组变量到 TupleCollectionView,它是合法的 让它像一个集合一样。如果您不相信,请阅读 用听起来很真实的人的声音再次证明了这一点 自信。

记住“哲学语气”,因为我们已经达到了“我说土豆;你说土豆的阶段。

【讨论】:

  • 似乎不是这样,因为你不能有一个单元素元组,一个函数可以接受一个参数。
  • 这是一种优化——X 的一个元组就是 X。
  • 所以 X 的一个元组不再是一个元组? reflect(x) 似乎暗示了这一点。元组是一个实际的类型,单个元素的元组怎么会失去它的类型呢?
  • 检查thisoneSimple 变为 @_Tv4main9oneSimpleSioneTuple 变为 @_Tv4main8oneTupleSi。根据Mike's postSiSwift.Int。没有T(= 元组)。仅适用于空元组 (T_) 或 2 个(或更多)元素 TSiSi_emptyTuple 变为 @_Tv4main10emptyTupleT_twoTuple 变为 @_Tv4main8twoTupleTSiSi_
  • @Boon 这不是反汇编。它是 SIL(Swit 中间语言)和 LLVM IR。只需将 -emit-sil 或 -emit-ir 传递给 swiftc。编译包括几个阶段 - Swift -> Swift AST -> SIL -> LLVM IR -> 汇编 -> 二进制。为什么是.0?不知道原因,问 Chris Lattner,但根据 Rob 链接的 Airspeed Velocity 撰写的文章 Swift 中的每个变量都是一个 1 元组。事实上,每个非元组变量都有一个 .0 属性,它是该变量的值。我现在把它当作事实。
【解决方案2】:

Swift 中的函数接受一个元组作为参数,它可以包含零个或多个值。无参数函数接受一个没有值的元组,一个有一个参数的函数接受一个有1个值的元组,等等。

您可以通过单独传递参数或将它们分组到一个不可变元组中来调用一个函数。例如,所有这些调用都是等价的:

do {
    let t1 = testFunctionUsingTuple()
    let t2 = testFuncUsingArgs()

    let params = (1, "tuple test")

    t1(params)
    t1(2, "test")

    t2(params)
    t2(3, "test")
}

【讨论】:

  • 一个元组必须至少有两个元素。您不能拥有单个元素元组。一个函数可以接受一个参数,那么“Swift 中的一个函数接受一个元组作为参数”这句话准确吗?此外,我发布了与常规 func 采用元组(与返回的 func)不一致的行为示例,这很有趣。
  • () 是一个元组——只是一个没有值的元组。一个元组中值的最小数量是零,而不是两个——想想(Int) -> () 中的():返回值是一个没有值的元组(即 void)
  • 检查developer.apple.com/library/prerelease/ios/documentation/Swift/… - 搜索元组类型 - 元组类型是零个或多个类型的逗号分隔列表,括在括号中。 - () 没有特殊情况, 空元组。
  • 但是let x = 1; print(x.0) 有效,这意味着x 既是Int 又是一个元组
  • 每种类型都可以自动提升为包含该类型的单元组。这与每个类型都可以自动提升为该类型的 Optional 的事实非常相似。元组和可选项仍然是类型;他们只是有促销规则。 Airspeed Velocity 在此处对元组进行了出色的编写:airspeedvelocity.net/2014/08/02/tuple-wrangling
猜你喜欢
  • 1970-01-01
  • 2018-07-03
  • 1970-01-01
  • 2012-07-21
  • 1970-01-01
  • 2014-12-25
  • 2014-08-16
  • 2013-01-31
相关资源
最近更新 更多