web-dev-qa-db-ja.com

Swiftの可変数の引数を使用して関数に配列を渡す

The Swift Programming Language では、次のように述べています。

関数は、可変数の引数を取り、配列に収集することもできます。

  func sumOf(numbers: Int...) -> Int {
      ...
  }

数値のコンマ区切りリスト( `sumOf(1、2、3、4))を使用してこのような関数を呼び出すと、関数内の配列として利用可能になります。

質問:この関数に渡したい数字の配列が既にある場合はどうなりますか?

let numbers = [1, 2, 3, 4]
sumOf(numbers)

これは、「指定された引数を受け入れる '__conversion'のオーバーロードを見つけることができませんでした」というコンパイラエラーで失敗します。既存の配列を、可変個の関数に渡すことができる要素のリストに変える方法はありますか?

138
Ole Begemann

スプラッティングはまだ言語ではありません 、開発者によって確認されています。現時点での回避策は、オーバーロードを使用するか、オーバーロードを追加できない場合に待機することです。

86
manojlds

これが私が見つけた回避策です。私はそれがあなたが望んでいるものとは正確に違うことを知っていますが、それは機能しているようです。

ステップ1:可変引数の代わりに配列を使用して、目的の関数を宣言します。

func sumOf(numbers: [Int]) -> Int {
    var total = 0
    for i in numbers {
        total += i
    }
    return total
}

ステップ2:可変機能関数内からこれを呼び出します。

func sumOf(numbers: Int...) -> Int {
    return sumOf(numbers)
}

ステップ3:いずれかの方法で呼び出す:

var variadicSum = sumOf(1, 2, 3, 4, 5)
var arraySum = sumOf([1, 2, 3, 4, 5])

奇妙に思えますが、私のテストでは機能しています。これが誰にも予期しない問題を引き起こすかどうかを教えてください。 Swiftは、同じ関数名を持つ2つの呼び出しの違いを区別できるようです。

また、この方法では、@ manojidの答えが示すようにAppleが言語を更新する場合、これらの関数を更新するだけで済みます。それ以外の場合は、多くの名前を変更する必要があります。

59
Logan

関数をキャストできます:

typealias Function = [Int] -> Int
let sumOfArray = unsafeBitCast(sumOf, Function.self)
sumOfArray([1, 2, 3])
13
Guoye Zhang

次のようなヘルパー関数を使用できます。

func sumOf (numbers : [Int])  -> Int { return numbers.reduce(0, combine: +) }
func sumOf (numbers : Int...) -> Int { return sumOf (numbers) }
12
GoZoner

私はこれをしました(ラッパー+アイデンティティマッピング):

func addBarButtonItems(types: REWEBarButtonItemType...) {
    addBarButtonItems(types: types.map { $0 })
}

func addBarButtonItems(types: [REWEBarButtonItemType]) {
    // actual implementation
}
1
schirrmacher

私はこの回答があなたの正確な質問に答えないことを知っていますが、私はそれが注目に値すると感じます。私もSwiftで遊び始めていましたが、すぐに同様の質問にぶつかりました。 Manojldsの答えはあなたの質問には良いと思いますが、私は同意しますが、もう一度、私が思いついた別の回避策です。私はたまたまローガンの方が好きです。

私の場合、配列を渡すだけでした。

func sumOf(numbers: Array<Int>) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum
}

var someNums = [8,7,2,9,12]
sumOf(someNums)
sumOf([10, 15, 20])

他の誰かが私のように考えている場合に備えて、共有したかっただけです。ほとんどの場合、このような配列を渡すことを好みますが、「Swiftly」はまだ考えていません。 :)

1
gregthegeek