Mengapa saya perlu menggarisbawahi dengan cepat?

161

Di sini tertulis, "Catatan: _berarti" Saya tidak peduli dengan nilai itu "", tetapi berasal dari JavaScript, saya tidak mengerti apa artinya itu.

Satu-satunya cara saya mendapatkan fungsi-fungsi ini untuk dicetak adalah dengan menggunakan garis bawah sebelum parameter:

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

Tanpa garis bawah saya harus menulis seperti ini untuk menghindari kesalahan:

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

Saya tidak mengerti penggunaan garis bawah ini. Kapan, bagaimana dan mengapa saya menggunakan garis bawah ini?

Michael Rader
sumber

Jawaban:

354

Ada beberapa nuansa untuk berbagai kasus penggunaan, tetapi umumnya garis bawah berarti "abaikan ini".


Ketika mendeklarasikan fungsi baru, garis bawah memberi tahu Swift bahwa parameter seharusnya tidak memiliki label saat dipanggil - itulah kasus yang Anda lihat. Deklarasi fungsi yang lebih lengkap terlihat seperti ini:

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

"label" adalah label argumen, dan harus ada saat Anda memanggil fungsi. (Dan sejak Swift 3, label diperlukan untuk semua argumen secara default.) "Name" adalah nama variabel untuk argumen yang Anda gunakan di dalam fungsi. Bentuk yang lebih pendek terlihat seperti ini:

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

Ini adalah jalan pintas yang memungkinkan Anda menggunakan kata yang sama untuk label argumen eksternal dan nama parameter internal. Ini setara dengan func myFunc(name name: Int).

Jika Anda ingin fungsi Anda dapat dipanggil tanpa label parameter, Anda menggunakan garis bawah _untuk membuat label menjadi tidak ada / diabaikan. (Dalam hal ini Anda harus memberikan nama internal jika Anda ingin dapat menggunakan parameter.)

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

Dalam pernyataan penugasan, garis bawah berarti "jangan tetapkan apa pun". Anda dapat menggunakan ini jika Anda ingin memanggil fungsi yang mengembalikan hasil tetapi tidak peduli dengan nilai yang dikembalikan.

_ = someFunction()

Atau, seperti pada artikel yang Anda tautkan, untuk mengabaikan satu elemen dari tuple yang dikembalikan:

let (x, _) = someFunctionThatReturnsXandY()

Saat Anda menulis penutupan yang mengimplementasikan beberapa jenis fungsi yang ditentukan, Anda dapat menggunakan garis bawah untuk mengabaikan parameter tertentu.

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

Demikian pula, ketika mendeklarasikan fungsi yang mengadopsi protokol atau mengganti metode superclass, Anda dapat menggunakan nama_ parameter untuk mengabaikan parameter. Karena protokol / superclass mungkin juga menentukan bahwa parameter tidak memiliki label, Anda bahkan dapat berakhir dengan dua garis bawah dalam satu baris.

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
    }
}

Agak terkait dengan dua gaya terakhir: saat menggunakan kontrol aliran yang mengikat variabel lokal / konstan, Anda dapat menggunakan _untuk mengabaikannya. Misalnya, jika Anda ingin mengulangi urutan tanpa perlu akses ke anggotanya:

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

Jika Anda mengikat kasus tuple dalam pernyataan sakelar, garis bawah dapat berfungsi sebagai wildcard, seperti dalam contoh ini (disingkat dari satu di The Swift Programming Language ):

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")
}

Satu hal yang tidak cukup terkait, tapi yang saya akan meliputi sejak (seperti dicatat oleh komentar) tampaknya untuk memimpin orang di sini: Sebuah garis bawah di sebuah identifier - misalnya var _foo, func do_the_thing(), struct Stuff_- berarti tidak ada yang khusus untuk Swift, tetapi memiliki beberapa kegunaan di antara programmer.

Garis bawah di dalam nama adalah pilihan gaya, tetapi tidak disukai di komunitas Swift, yang memiliki konvensi kuat tentang penggunaan UpperCamelCase untuk tipe dan lowerCamelCase untuk semua simbol lainnya.

Awalan atau suffixing nama simbol dengan garis bawah adalah konvensi gaya, yang secara historis digunakan untuk membedakan simbol pribadi / hanya penggunaan internal dari API yang diekspor. Namun, Swift memiliki pengubah akses untuk itu, sehingga konvensi ini umumnya dianggap non-idiomatis di Swift.

Beberapa simbol dengan awalan garis bawah-ganda ( func __foo()) bersembunyi di kedalaman SDK Apple: Ini adalah simbol (Obj) C yang diimpor ke Swift menggunakan NS_REFINED_FOR_SWIFTatribut. Apple menggunakannya ketika mereka ingin membuat versi "lebih cepat" dari API C (Obj) - misalnya, untuk membuat metode agnostik tipe menjadi metode generik . Mereka perlu menggunakan API yang diimpor untuk membuat versi Swift yang disempurnakan berfungsi, sehingga mereka menggunakan __agar tetap tersedia sambil menyembunyikannya dari sebagian besar alat dan dokumentasi.

rickster
sumber
@rickster, Apa pentingnya garis bawah pada awal metode, seperti ini-> func _copyContents (menginisialisasi ptr: UnsafeMutableBufferPointer <Element>) -> (Iterator, UnsafeMutableBufferPointer <Element> .Index)} dari protokol Sequence.
dev gr
@devgr: Sama sekali tidak terkait, jadi saya akan merekomendasikan memposting pertanyaan terpisah.
rickster
Tentu, saya akan memposting pertanyaan terpisah.
dev gr
Terima kasih telah "tidak menetapkan apa pun" untuk pengembalian fungsi. Ini yang saya cari.
absin
8

Selain jawaban yang diterima, salah satu kasus penggunaan _adalah ketika Anda harus menulis nomor yang panjang dalam kode

Nomor lebih mudah dibaca

Ini tidak mudah dibaca manusia:

let x = 1000000000000

Anda dapat menambahkan _nomornya agar lebih mudah dibaca manusia:

let x = 1_000_000_000_000
Mojtaba Hosseini
sumber
6

Sejak Swift 3, menentukan nama parameter pada panggilan fungsi telah menjadi wajib - bahkan untuk yang pertama. Jadi, karena hal itu dapat menyebabkan masalah besar pada kode yang ditulis dalam swift 2, Anda dapat menggunakan garis bawah pada deklarasi untuk mencegah keharusan menulis nama parameter saat panggilan. Jadi dalam hal ini, dikatakan "tidak peduli dengan nama parameter eksternal". Di mana nama parameter eksternal adalah apa yang Anda panggil parameter di luar fungsi (panggilan) tidak ada di dalam. Nama parameter eksternal ini disebut label argumen. http://ericasadun.com/2016/02/09/the-trouble-with-argument-labels-some-thoughts/ ... lihat bagaimana parameternya diberikan dua nama? nah yang pertama adalah ke mana garis bawah akan pergi. Semoga ini bisa membantu, dan jangan ditanya apakah masih bingung.

Caspar Wylie
sumber
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)
}

The _adalah tempat untuk nama parameter. Dalam contoh Anda, Anda memanggil mereka secara berbeda, pada fungsi kedua, Anda perlu menulis nama parameter a: 1.

Konvensi nama fungsi Swift adalah funcName(param1:param2:), dan diperlukan _sebagai pengganti untuk membuat nama fungsi.

Di nama depan, namanya

divmod(_:_:)

Sedangkan yang kedua adalah

divmod(a:b:)
davidhu
sumber