Neden hızlı bir şekilde alt çizgilere ihtiyacım var?


161

Burada "Not: _" Bu değer umurumda değil "anlamına gelir, ancak JavaScript'ten geliyor, bunun ne anlama geldiğini anlamıyorum.

Bu işlevleri yazdırmak için tek yolu parametrelerden önce alt çizgi kullanarak oldu:

func divmod(_ a: Int, _ b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

print(divmod(7, 3))
print(divmod(5, 2))
print(divmod(12,4))

Alt çizgiler olmadan herhangi bir hata önlemek için böyle yazmak zorunda:

func divmod(a: Int, b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

print(divmod(a: 7, b: 3))
print(divmod(a: 5, b: 2))
print(divmod(a: 12,b: 4))

Bu alt çizgi kullanımını anlamıyorum. Bu alt çizgileri ne zaman, nasıl ve neden kullanırım?

Yanıtlar:


354

Farklı kullanım durumları için birkaç nüans vardır, ancak genellikle alt çizgi "bunu görmezden gel" anlamına gelir.


Yeni bir işlev bildirirken, alt çizgi Swift'e parametrenin çağrıldığında etiketinin olmaması gerektiğini söyler - gördüğünüz durum budur. Daha dolgun bir işlev bildirimi şöyle görünür:

func myFunc(label name: Int) // call it like myFunc(label: 3)

"label" bir bağımsız değişken etiketidir ve işlevi çağırdığınızda bulunması gerekir. (Ve Swift 3'ten beri, varsayılan olarak tüm bağımsız değişkenler için etiketler gereklidir.) "Name", işlevin içinde kullandığınız bağımsız değişken için değişken adıdır. Daha kısa bir form şöyle görünür:

func myFunc(name: Int) // call it like myFunc(name: 3)

Bu, hem harici bağımsız değişken etiketi hem de dahili parametre adı için aynı kelimeyi kullanmanızı sağlayan bir kısayoldur. Eşdeğerdir func myFunc(name name: Int).

İşlevinizin parametre etiketleri olmadan çağrılabilir olmasını istiyorsanız _, etiketin hiçbir şey / yoksayılmasını sağlamak için alt çizgiyi kullanırsınız. (Bu durumda, parametreyi kullanabilmek için dahili bir ad sağlamanız gerekir.)

func myFunc(_ name: Int) // call it like myFunc(3)

Bir atama deyiminde alt çizgi "hiçbir şeye atama" anlamına gelir. Sonuç döndüren ancak döndürülen değeri umursamayan bir işlevi çağırmak istiyorsanız bunu kullanabilirsiniz.

_ = someFunction()

Veya, bağlandığınız makalede olduğu gibi, döndürülen bir grubun bir öğesini yok saymak için:

let (x, _) = someFunctionThatReturnsXandY()

Bazı tanımlanmış işlev türlerini uygulayan bir kapatma yazdığınızda, belirli parametreleri yok saymak için alt çizgiyi kullanabilirsiniz.

PHPhotoLibrary.performChanges( { /* some changes */ },
    completionHandler: { success, _ in // don't care about error
        if success { print("yay") }
    })

Benzer şekilde, bir protokolü benimseyen veya bir üst sınıf yöntemini geçersiz kılan bir işlevi bildirirken, _parametreleri yoksaymak için parametre adları için kullanabilirsiniz . Protokol / üst sınıf, parametrenin etiketi olmadığını da tanımlayabileceğinden, üst üste iki alt çizgi bile oluşturabilirsiniz.

class MyView: NSView {
    override func mouseDown(with _: NSEvent) {
        // don't care about event, do same thing for every mouse down
    }
    override func draw(_ _: NSRect) {
        // don't care about dirty rect, always redraw the whole view
    }
}

Son iki stille biraz ilgili: yerel bir değişkeni / sabiti bağlayan bir akış kontrol yapısı kullanırken _, onu yoksaymak için kullanabilirsiniz . Örneğin, üyelerine erişmeye gerek kalmadan bir diziyi yinelemek istiyorsanız:

for _ in 1...20 { // or 0..<20
    // do something 20 times
}

Bir anahtar ifadesinde demet vakaları bağlıyorsanız, alt çizgi, bu örnekte olduğu gibi joker karakter olarak çalışabilir ( Hızlı Programlama Dili'ndeki bir kısaltılmış ):

switch somePoint { // somePoint is an (Int, Int) tuple
case (0, 0):
    print("(0, 0) is at the origin")
case (_, 0):
    print("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
    print("(0, \(somePoint.1)) is on the y-axis")
default:
    print("(\(somePoint.0), \(somePoint.1)) isn't on an axis")
}

(Yorumlar tarafından da belirtildiği gibi) o zamandan beri ekleriz Son bir oldukça ilgisi olmayan şey, ama burada insanlara liderlik görünüyor: Bir çizgi halinde - örneğin bir tanımlayıcı var _foo, func do_the_thing(), struct Stuff_- Swift özellikle hiçbir vasıta, ancak birkaç kullanımları vardır programcılar arasında.

Bir ad içindeki alt çizgiler bir stil seçimidir, ancak türler için UpperCamelCase ve diğer tüm semboller için lowerCamelCase kullanma konusunda güçlü kurallara sahip olan Swift topluluğunda tercih edilmez.

Bir sembol adının alt çizgi ile ön eki veya son eki, geçmişte yalnızca özel / dahili kullanım sembollerini dışa aktarılan API'den ayırmak için kullanılan bir stil kuralıdır. Bununla birlikte, Swift'in bunun için erişim değiştiricileri vardır, bu nedenle bu sözleşme genellikle Swift'te deyimsel olmayan olarak görülür.

func __foo()Apple'ın SDK'larının derinliklerinde çift ​​alt çizgi önekleri ( ) bulunan birkaç sembol : Bunlar, Swift kullanılarak içe aktarılan (Obj) C sembolleri NS_REFINED_FOR_SWIFT. Apple bunu (Obj) C API'sinin "daha Swifty" bir sürümünü yapmak istediklerinde kullanır - örneğin, genel bir yönteme tip-agnostik bir yöntem yapmak için . Rafine edilmiş Swift sürümünü çalıştırmak için içe aktarılan API'yi kullanmaları gerekir, bu nedenle __çoğu araç ve dokümantasyondan gizlerken onu kullanılabilir tutmak için kullanırlar.


@rickster, Bir yöntemin başlangıcında alt çizginin önemi nedir, böyle bir-> func _copyContents (başlatıcı ptr: UnsafeMutableBufferPointer <Element>) -> (Yineleyici, UnsafeMutableBufferPointer <Element> .Index)} sekans protokolünden.
dev gr

@devgr: Tamamen ilgisiz, bu yüzden ayrı bir soru göndermenizi tavsiye ederim.
rickster

Tabii, ayrı bir soru göndereceğim.
dev gr

İşlev iadesi için "hiçbir şeye atama" için teşekkürler. Aradığım şey buydu.
Ocak'ta

8

Kabul edilen cevaba ek olarak, kullanım durumlarından biri _, kodda uzun bir sayı yazmanız gerektiğidir.

Daha okunabilir sayı

Bu kolay okunabilir değildir:

let x = 1000000000000

Daha _fazla okunabilir hale getirmek için numarayı ekleyebilirsiniz :

let x = 1_000_000_000_000

6

Swift 3'ten bu yana, işlev çağrılarında parametre adlarının belirtilmesi zorunlu hale geldi - birincisi için bile. Bu nedenle, bu, hızlı 2'de yazılan kodda büyük bir soruna neden olabileceğinden, çağrıda parametre adını yazmak zorunda kalmamak için bildirimde bir alt çizgi kullanabilirsiniz. Bu durumda, "dış parametre adı umurumda değil" diyor. Dış parametre adı, içinde değil fonksiyonun (çağrıda) dışındaki parametreleri çağırdığınız yerdir. Bu harici parametre adlarına bağımsız değişken etiketleri denir. http://ericasadun.com/2016/02/09/the-trouble-with-argument-labels-some-thoughts/ ... parametrenin iki ada nasıl verildiğini görüyor musunuz? İlki alt çizginin nereye gittiğini umuyorum. Bu yardımcı olur ve hala karışık olup olmadığını sor.


4
func divmod(_ a: Int, _ b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

func divmod(a: Int, b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

_Parametre adı için bir yer tutucudur. Örneğinizde, bunları farklı şekilde çağırırsınız, ikinci işlevde parametre adını yazmanız gerekir a: 1.

Swift'in işlev adı kuralıdır funcName(param1:param2:)ve işlevin adını _oluşturmak için bir yer tutucu olarak gerekir .

İlk adda, ad

divmod(_:_:)

Halbuki ikincisi

divmod(a:b:)
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.