Swift'te değişken sayıda bağımsız değişkeni olan bir işleve dizi aktarma


151

In Swift Programlama Dili , diyor:

İşlevler ayrıca bir dizi halinde toplanan değişken sayıda argüman alabilir.

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

Virgülle ayrılmış bir sayı listesiyle (`sumOf (1, 2, 3, 4) böyle bir işlevi çağırdığımda, bunlar işlevin içinde bir dizi olarak kullanılabilir hale getirilir.

Soru: Bu işleve geçmek istediğim bir dizi sayım varsa ne olur?

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

Bu derleyici hatasıyla başarısız olur, "Sağlanan argümanları kabul eden '__conversion' için aşırı yük bulunamadı". Var olan bir diziyi, değişken bir işleve iletebileceğim öğeler listesine dönüştürmenin bir yolu var mı?


1
Neden işlevi sadece bir tamsayı dizisi alacak şekilde yapılandırmıyorsunuz?
Mick MacCallum

27
Elbette, ancak işlevin yazarı olmayabilirim ve işlevi değiştiremeyebilir (veya değiştirmek isteyemeyebilir).
Ole Begemann

Yanıtlar:


97

Splatting, geliştiriciler tarafından onaylandığı gibi henüz dilde değil . Şimdilik geçici bir aşırı yük kullanmak veya aşırı yük ekleyemiyorsanız bekleyin.


3
Splatting henüz bir dilde mi? Aramaya çalışıyorumsumOf(...numbers)
Noitidart

Çok hayal kırıklığı! Bunu kendi günlük çağrılarımı devretmeye çalışmak kadar basit bir şeyle bile vurdum print!
Mark A. Donohoe

65

İşte bulduğum bir çalışma. Tam olarak ne istediğini biliyorum, ama çalışıyor gibi görünüyor.

Adım 1: Değişken argümanlar yerine bir dizi ile istediğiniz işlevi bildirin:

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

Adım 2: Bunu değişken fonksiyonunuzdan arayın:

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

3. Adım: Her İki Şekilde Arayın:

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

Tuhaf görünüyor, ama testlerimde çalışıyor. Bunun kimseye öngörülemeyen sorunlara neden olup olmadığını bildirin. Swift, aynı işlev adına sahip iki çağrı arasındaki farkı ayırabiliyor gibi görünüyor.

Ayrıca, bu yöntemle Apple dili @ manojid'in cevabının önerdiği şekilde güncellerse, sadece bu işlevleri güncellemeniz gerekir. Aksi takdirde, geçip yeniden adlandırma yapmak zorunda kalacaksınız.


Teşekkürler, geçici çözümü seviyorum. Özelliğin henüz mevcut olmadığına dair resmi teyit bağlantısını bulmak için yine de manojld'lere "doğru" yanıtı vereceğim. Umarım anlarsın.
Ole Begemann

Muhtemelen Kılavuzu ve func sumOf (sayıları: [Int]) -> Int aslında ortalama
gfelisberto

18

İşlevi atabilirsiniz:

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

Harika! Bu, çoklu (adlandırılmış) parametrelerle de çalışır; örneğin: func sumOf(foo numbers: Int..., bar: Bool) -> Int {};gerektirirtypealias Function = (foo: [Int], bar: Bool) -> Int;
ThomasR

Harika! hayatımı kurtar.
JerryZhou

Benzer şeyleri AnyObject ile nasıl yapabilirim? stackoverflow.com/questions/42016358/… Teşekkürler.
JerryZhou

Bu çok kötü bir fikir. Bunun işe yarayacağının kesinlikle sıfır garantisi vardır.
idmean

1
@MattMc Elbette. Bildiğim kadarıyla, sadece bir çağrılabilir türü kullanarak başka bir çağrıya izin verecek hiçbir şey yoktur unsafeBitCast. Bu bugün işe yarayabilir, ancak bir referans böyle söylemedikçe, derleyicinin bir sonraki sürümü tam anlamıyla burada bir şey yapmakta özgürdür (derleyici hatası / çökme / rastgele yürütme kodu ...). Güvenli olmayanBitCast ile ilgili ciddi görünümlü uyarılara bir göz atın .
idmean

15

Bir yardımcı işlevi şu şekilde kullanabilirsiniz:

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

12
Diziler için bir sürüm olması koşuluyla. Sorunun önermesi, orijinal işlevin Int...(kolayca) değiştirilip değiştirilemeyeceğini düşündüm ?

2
@delnan: Doğru. Bana öyle geliyor ki, varyasyon argümanlarının yine de bir diziye dönüştürüldüğü göz önüne alındığında, bir diziyi varyasyon fonksiyonuna geçirmenin bir yolu olmalı.
Ole Begemann

1
Şema gibi işlevlerde değişken sayıda bağımsız değişkeni kabul eden dillerin bir applyyordamı vardır. Bazı insanları buna 'sıçramak' olarak adlandırıyorum.
GoZoner

1
sumArrayBurada atıfta bulunulan nedir ?
Rob

2

Bu cevabın tam sorunuza cevap vermediğini biliyorum, ama kayda değer olduğunu hissediyorum. Ben de Swift ile oynamaya başladım ve hemen benzer bir soruya girdim. Manojlds cevabı sorunuz için daha iyi, katılıyorum, ama yine, başka bir geçici çözüm buldum. Logan'ın da daha iyi olmasını isterdim.

Benim durumumda sadece bir dizi geçmek istedim:

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])

Başka birinin benim gibi düşünmesi ihtimaline karşı paylaşmak istedim. Çoğu zaman böyle diziyi geçmek tercih ediyorum, ama henüz "Hızlı" sanmıyorum. :)


1

Bunu yaptım (Wrapper + Kimlik Eşleme):

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

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

0

Hızlı 5

Bu, @dynamicCallableaşırı yüklenmeyi önlemeye izin veren unsafeBitCastbir özelliktir structveya aramak için belirli bir şey yapmalısınız :

@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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.