Swift에서 가변 개수의 인수를 가진 함수에 배열 전달


151

에서 스위프트 프로그래밍 언어 , 그것은 말합니다 :

함수는 가변 개수의 인수를 가져 와서 배열로 수집 할 수도 있습니다.

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

쉼표로 구분 된 숫자 목록 (`sumOf (1, 2, 3, 4)으로 이러한 함수를 호출하면 함수 내부에서 배열로 사용할 수 있습니다.

질문 :이 함수에 전달할 숫자 배열이 이미 있으면 어떻게합니까?

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

"제공된 인수를 허용하는 '__conversion'에 대한 과부하를 찾을 수 없습니다."라는 컴파일러 오류와 함께 실패합니다. 기존 배열을 가변성 함수에 전달할 수있는 요소 목록으로 바꾸는 방법이 있습니까?


1
정수 배열을 대신 사용하도록 함수를 구성하지 않는 이유는 무엇입니까?
Mick MacCallum 2018 년

27
물론, 나는 그 기능의 저자가 아니며 그것을 바꾸고 싶지 않거나 바꾸고 싶지 않을 수도 있습니다.
올레 Begemann

답변:


97

개발자들이 확인한 바에 따르면 튀어 오르는 언어는 아직 없습니다 . 현재 해결 방법은 과부하를 사용하거나 과부하를 추가 할 수없는 경우 기다리는 것입니다.


3
언어에 아직 뿌려지고 있습니까? 전화하려고 해요sumOf(...numbers)
Noitidart

너무 실망합니다! 내 자신의 로그 호출을 아래로 위임하는 것처럼 간단한 것으로도이 문제를 해결했습니다 print!
Mark A. Donohoe

65

내가 찾은 해결 방법이 있습니다. 나는 그것이 당신이 원하는 것이 아니라는 것을 알고 있지만 작동하는 것 같습니다.

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는 동일한 함수 이름으로 두 호출의 차이점을 분리 할 수있는 것으로 보입니다.

또한이 방법을 사용하면 @manojid의 답변에서 알 수 있듯이 Apple이 언어를 업데이트하면 이러한 기능 만 업데이트하면됩니다. 그렇지 않으면 많은 변경 작업을 거쳐야합니다.


고마워, 나는 해결책을 좋아한다. 이 기능을 아직 사용할 수 없다는 공식 확인 링크를 찾은 것에 대해 manojlds에 대한 "올바른"답변을 계속 수여합니다. 난 당신이 이해 바랍니다.
올레 Begemann

당신은 아마 가이드와 함께 당신의 func sumOf (numbers : [Int])-> Int 실제로 평균을 계산하고 있습니다
gfelisberto

18

함수를 캐스트 할 수 있습니다.

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

큰! 이것은 여러 개의 명명 된 매개 변수에도 적용됩니다. 예 : func sumOf(foo numbers: Int..., bar: Bool) -> Int {};요구 사항typealias Function = (foo: [Int], bar: Bool) -> Int;
ThomasR

큰! 내 생명을 구하십시오.
JerryZhou

AnyObject와 비슷한 작업을 수행하려면 어떻게해야합니까? stackoverflow.com/questions/42016358/… 감사합니다.
JerryZhou

이것은 매우 나쁜 생각입니다. 이것이 작동한다는 보장은 전혀 없습니다.
idmean

1
@MattMc 물론입니다. 내가 알 수있는 한을 사용하여 호출 가능한 유형을 다른 유형으로 캐스팅 할 수있는 것은 없습니다 unsafeBitCast. 이것은 오늘 작동 할 수 있지만 참조가 명시하지 않는 한 다음 버전의 컴파일러는 문자 그대로 여기에서 아무것도 할 수 있습니다 (컴파일러 오류 / 충돌 / 무작위 실행 코드 ...). unsafeBitCast 에 대한 심각한 경고를 살펴보십시오 .
idmean

15

다음과 같은 도우미 기능을 사용할 수 있습니다.

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

12
배열 버전이 제공됩니다. 나는 그 질문의 전제가 원래의 기능을 취하고 Int...(쉽게) 바꿀 수 없다는 것이라고 생각했다 .

2
@ 델난 : 맞습니다. variadic 인수가 어쨌든 배열로 바뀌면 배열을 variadic 함수에 전달하는 방법이 있어야합니다.
Ole Begemann

1
Scheme과 같은 함수에서 가변 개수의 인수를 허용하는 언어에는 apply프로 시저가 있습니다. 나는 사람들이 그것을 '튀는 것'이라고 부르고 있습니다.
GoZoner 2016 년

1
여기서 무엇을 sumArray참조합니까?
Rob

2

이 답변이 귀하의 정확한 질문에 대한 답변이 아니라는 점을 알고 있습니다. 나도 스위프트와 놀기 시작했고 즉시 비슷한 질문에 부딪쳤다. 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

나는 이것을했다 (Wrapper + Identity Mapping) :

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

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

0

스위프트 5

이것은 @dynamicCallable과부하를 피할 수 있는 기능을 갖춘 접근법 unsafeBitCast이지만 struct전화를 구체적으로 해야합니다.

@dynamicCallable
struct SumOf {
    func dynamicallyCall(withArguments args: [Int]) -> Int {
        return args.reduce(0, +)
    }
}

let sum = SumOf()

// Use a dynamic method call.
sum(1, 2, 3) // 6

// Call the underlying method directly.
sum.dynamicallyCall(withArguments: [1, 2, 3]) // 6
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.