接受元组的 Swift 函数

问题描述 投票:0回答:10

只要类型匹配,是否可以将元组传递到函数中?

当我尝试时,我收到

missing argument in parameter
错误:

var myTuple = ("Text",10,"More Text")

func myFunction(a:String, b:Int, c:String) {
    // etc...
}

myFunction(myTuple)
swift
10个回答
13
投票

这是可能的,尽管在 Swift 2.2 中已弃用:

在 Swift 2.1 及更早版本中,可以使用精心设计的元组来填充函数的参数。因此,如果您有一个带有两个参数的函数,则可以使用二元素元组来调用它,只要该元组具有正确的类型和元素名称即可。

...

这种语法——被亲切地称为“tuple splat 语法”——是惯用的 Swift 的自记录、可读风格的对立面,因此它在 Swift 2.2 中已被弃用。

https://swift.org/blog/swift-2-2-new-features/


12
投票

我来这里想知道如何将元组作为函数参数传递。这里的答案集中在不同的案例上。我不太清楚 OP 的目的是什么。

无论如何,这里是如何传递元组作为参数。而且,为了更好地衡量,如何可变地做到这一点。

func acceptTuple(tuple : (Int, String)) {
    print("The Int is: \(tuple.0)")
    print("The String is '\(tuple.1)'")
}

acceptTuple((45, "zebras"))
// Outputs:
// The Int is: 45
// The String is 'zebras'

func acceptTuples(tuples : (Int, String) ...) {
    var index = 0

    // note: you can't use the (index, tuple) pattern in the for loop,
    // the compiler thinks you're trying to unpack the tuple, hence
    /// use of a manual index 

    for tuple in tuples {
        print("[\(index)] - Int is: \(tuple.0)")
        print("[\(index)] - String is '\(tuple.1)'")
        index++
    }
}

acceptTuples((45, "zebras"), (17, "armadillos"), (12, "caterpillars"))

//Outputs
//[0] - Int is: 45
//[0] - String is 'zebras'
//[1] - Int is: 17
//[1] - String is 'armadillos'
//[2] - Int is: 12
//[2] - String is 'caterpillars'

传递元组可能是一种快速方便的方法,使您不必创建包装器等。例如,我有一个用例,我传递一组令牌和参数来创建游戏关卡。元组让这一切变得美好而紧凑:

// function signature
class func makeLevel(target: String, tokens: (TokenType, String)...) -> GameLevel
// The function is in the class Level. TokenType here is an Enum. 
// example use:
let level = Level("Zoo Station", tokens:
            (.Label, "Zebra"),
            (.Bat, "LeftShape"),
            (.RayTube, "HighPowered"),
            (.Bat, "RightShape"),
            (.GravityWell, "4"),
            (.Accelerator, "Alpha"))

8
投票

是的,在这些条件下是可能的:

  • 元组必须是不可变的
  • 元组中值的数量、类型和顺序必须与函数期望的参数匹配
  • 命名参数必须与函数签名中的外部名称匹配
  • 非命名参数必须与函数签名中没有外部名称的参数匹配

所以,你的代码没问题,你唯一要做的就是将元组变成不可变的元组(即使用

let
而不是
var
):

let myTuple = ("Text", 10, "More Text")

func myFunction(a:String, b:Int, c:String) {
    // etc...
}

myFunction(myTuple)

还有一个带有外部名称的示例:

let myTuple = ("Text", paramB: 10, paramC: "More Text")

func myFunction(a:String, paramB b:Int,  paramC c:String) {
    // etc...
}

myFunction(myTuple)

3
投票

在您的元组中,似乎您必须命名它们,然后这样引用它们:

所以你的代码应该是

var myTuple = (val1: "Text", val2: 10, val3: "More Text")

    func myFunction(a:String, b:Int, c:String) {
        // etc...
    }


    myFunction(myTuple.val1, myTuple.val2, myTuple.val3)

元组具有您设置的命名值(val1、val2、val3),然后在将 myTuple 传递给函数 myFunction() 时引用它们,看起来好像您只是填充了 3 个可用参数中的 1 个 - 并且使用启动类型错误!这相当于将类型存储在元组中,然后取出它们进行函数调用。但是,如果您希望函数实际上采用元组作为参数,请参见下文:

var myTuple = (val1: "Text", val2: 10, val3: "More Text")

    func tupleFunc(a:(String, Int, String)) {

    }

    tupleFunc(myTuple)

2
投票

是的,但这是错误的结构:您传递的是三个名为

a
b
c
的变量,而不是包含这些组件的元组。

整个事情都需要括号:

var myTuple = ("Text", 10, "More Text")

func myFunction(a:(x: String, y: Int, z: String)) {
    println(a)
}

myFunction(myTuple)

2
投票

您可以使用以下功能:Swift 允许您将具有任意数量参数(但没有 inout 参数)的函数 (f1) 作为类型 (TIn) -> TOut 的参数传递给另一个函数。在这种情况下,TIn 将表示函数 f1 的参数的元组:

precedencegroup ApplyArgumentPrecedence {
    higherThan: BitwiseShiftPrecedence 
}

infix operator <- :ApplyArgumentPrecedence

func <-<TIn, TOut>(f: ((TIn) -> TOut), arg: TIn) -> TOut {
    return f(arg)
}

func sum(_ a: Int, _ b: Int) -> Int {
  return a + b
}

print(sum <- (40, 2))

1
投票

在 swift 3.0 中,我们不应该能够将元组直接传递给函数。如果我们这样做,它会显示错误消息“此类型已在 swift 3.0 中删除”

func sum(x: Int, y: Int) -> Int
return x+y } 

let params = (x: 1, y: 1)
let x = params.0
let y = params.1
sum(x: x, y: y)

希望对你有帮助!!


1
投票

目前最好的选择似乎是将其保存到复合变量或使用内置点语法

    let (val1, val2) = (1, 2)

    
    func f(first: Int, second: Int) { }
    
    f(first: val1, second: val2)

let vals = (1, 2)

f(first: vals.0, second: vals.1)

0
投票

名为

implicit tuple splat
的功能已在 swift 3 中删除。

您可以在此处

找到有关删除提案的更详细说明

继续使用元组作为参数的一些建议是这样做:

func f1(_ a : (Int, Int)) { ... }
let x = (1, 2)
f1(x)


func f2<T>(_ a : T) -> T { ... }
let x = (1, 2)
f2(x)

0
投票

尽管这已在 Swift 的更高版本中被删除,但您仍然可以到达那里,尽管它并不完全漂亮。数组函数map可以将函数应用于元组。 所以而不是

myFunction(myTuple)

你可以这样做:

[myTuple].map(myFunction)[0]
© www.soinside.com 2019 - 2024. All rights reserved.