Tại sao tôi cần dấu gạch dưới trong swift?


161

Ở đây có ghi: "Lưu ý: _nghĩa là tôi không quan tâm đến giá trị đó", nhưng đến từ JavaScript, tôi không hiểu điều đó có nghĩa là gì.

Cách duy nhất tôi có thể có được các chức năng này để in là sử dụng dấu gạch dưới trước các tham số:

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

Nếu không có dấu gạch dưới, tôi phải viết nó như thế này để tránh mọi lỗi:

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

Tôi không hiểu cách sử dụng gạch dưới này. Khi nào, làm thế nào và tại sao tôi sử dụng những dấu gạch dưới này?

Câu trả lời:


353

Có một vài sắc thái cho các trường hợp sử dụng khác nhau, nhưng nói chung, dấu gạch dưới có nghĩa là "bỏ qua điều này".


Khi khai báo một hàm mới, dấu gạch dưới nói với Swift rằng tham số sẽ không có nhãn khi được gọi - đó là trường hợp bạn đang thấy. Một khai báo hàm đầy đủ hơn trông như thế này:

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

"nhãn" là nhãn đối số và phải có mặt khi bạn gọi hàm. (Và kể từ Swift 3, các nhãn được yêu cầu cho tất cả các đối số theo mặc định.) "Name" là tên biến cho đối số mà bạn sử dụng bên trong hàm. Một hình thức ngắn hơn trông như thế này:

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

Đây là lối tắt cho phép bạn sử dụng cùng một từ cho cả nhãn đối số bên ngoài và tên tham số bên trong. Nó tương đương với func myFunc(name name: Int).

Nếu bạn muốn chức năng của mình có thể gọi được mà không có nhãn tham số, bạn sử dụng dấu gạch dưới _để làm cho nhãn không có gì / bị bỏ qua. (Trong trường hợp đó, bạn phải cung cấp một tên nội bộ nếu bạn muốn có thể sử dụng tham số.)

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

Trong câu lệnh gán, dấu gạch dưới có nghĩa là "không gán cho bất cứ thứ gì". Bạn có thể sử dụng điều này nếu bạn muốn gọi một hàm trả về kết quả nhưng không quan tâm đến giá trị được trả về.

_ = someFunction()

Hoặc, như trong bài viết bạn liên kết đến, để bỏ qua một yếu tố của bộ dữ liệu được trả về:

let (x, _) = someFunctionThatReturnsXandY()

Khi bạn viết một bao đóng thực hiện một số loại hàm được xác định, bạn có thể sử dụng dấu gạch dưới để bỏ qua các tham số nhất định.

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

Tương tự, khi khai báo một hàm thông qua một giao thức hoặc ghi đè một phương thức siêu lớp, bạn có thể sử dụng _cho các tên tham số để bỏ qua các tham số. Vì giao thức / siêu lớp cũng có thể xác định rằng tham số không có nhãn, thậm chí bạn có thể kết thúc bằng hai dấu gạch dưới liên tiếp.

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

Một số liên quan đến hai kiểu cuối cùng: khi sử dụng cấu trúc điều khiển luồng liên kết một biến / hằng cục bộ, bạn có thể sử dụng _để bỏ qua nó. Ví dụ: nếu bạn muốn lặp lại một chuỗi mà không cần truy cập vào các thành viên của nó:

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

Nếu bạn ràng buộc các trường hợp tuple trong câu lệnh chuyển đổi, dấu gạch dưới có thể hoạt động như một ký tự đại diện, như trong ví dụ này (rút ngắn từ một trong Ngôn ngữ lập trình Swift ):

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

Một điều cuối cùng đó là không hoàn toàn liên quan, nhưng mà tôi sẽ bao gồm từ (như đã nêu bởi comments) có vẻ như để lãnh đạo nhân dân ở đây: Một dấu gạch dưới trong một định - ví dụ như var _foo, func do_the_thing(), struct Stuff_- phương tiện không có gì đặc biệt để Swift, nhưng có một vài công dụng trong số các lập trình viên.

Dấu gạch dưới trong tên là một lựa chọn kiểu, nhưng không được ưa thích trong cộng đồng Swift, vốn có những quy ước mạnh mẽ về việc sử dụng UpperCamelCase cho các loại và lowCamelCase cho tất cả các biểu tượng khác.

Tiền tố hoặc thêm một tên biểu tượng với dấu gạch dưới là một quy ước kiểu, trong lịch sử được sử dụng để phân biệt các biểu tượng chỉ sử dụng riêng / nội bộ với API xuất khẩu. Tuy nhiên, Swift có các sửa đổi truy cập cho điều đó, vì vậy quy ước này thường được xem là không thành ngữ trong Swift.

Một vài biểu tượng có tiền tố gạch dưới kép ( func __foo()) ẩn sâu trong các SDK của Apple: Đây là các biểu tượng (Obj) C được nhập vào Swift bằng NS_REFINED_FOR_SWIFTthuộc tính. Apple sử dụng điều đó khi họ muốn tạo một phiên bản "Obifty" hơn của API (Obj) C - ví dụ, để biến một phương thức bất khả tri thành một phương thức chung . Họ cần sử dụng API đã nhập để làm cho phiên bản Swift tinh chỉnh hoạt động, vì vậy họ sử dụng __để giữ nó có sẵn trong khi ẩn nó khỏi hầu hết các công cụ và tài liệu.


@rickster, tầm quan trọng của dấu gạch dưới khi bắt đầu một phương thức, như thế này-> func _copyContents (khởi tạo ptr: UnsafeMutableBufferPulum <Element>) -> (Iterator, UnsafeMutableBufferPulum <Element
dev gr

@devgr: Hoàn toàn không liên quan, vì vậy tôi khuyên bạn nên đăng một câu hỏi riêng.
còi xương

Chắc chắn, tôi sẽ đăng một câu hỏi riêng biệt.
dev gr

Cảm ơn vì "không gán cho bất cứ điều gì" cho một hàm trả về. Đây là những gì tôi đang tìm kiếm.
absin

8

Ngoài câu trả lời được chấp nhận, một trong những trường hợp sử dụng _là khi bạn cần viết một số dài trong mã

Số dễ đọc hơn

Điều này không dễ đọc với con người:

let x = 1000000000000

Bạn có thể thêm _vào số để làm cho nó dễ đọc hơn:

let x = 1_000_000_000_000

6

Kể từ Swift 3, việc chỉ định tên tham số cho các lệnh gọi hàm đã trở thành bắt buộc - ngay cả đối với lần đầu tiên. Vì vậy, vì điều đó có thể gây ra vấn đề lớn đối với mã được viết trong swift 2, bạn có thể sử dụng dấu gạch dưới tại phần khai báo để tránh phải viết tên tham số trong cuộc gọi. Vì vậy, trong trường hợp này, nó có nghĩa là "không quan tâm đến tên tham số bên ngoài". Trong đó tên tham số bên ngoài là những gì bạn gọi các tham số bên ngoài hàm (trên cuộc gọi) không bên trong. Các tên tham số bên ngoài được gọi là nhãn đối số. http://ericasadun.com/2016/02/09/the-trouble-with-argument-labels-some- Dùts / ... xem tham số được đưa ra hai tên như thế nào? đầu tiên là nơi gạch dưới đang diễn ra. Hy vọng điều này sẽ giúp, và hỏi nếu vẫn còn bối rối.


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

Đây _là một giữ chỗ cho tên tham số. Trong ví dụ của bạn, bạn gọi chúng khác nhau, trong hàm thứ hai, bạn cần viết tên tham số a: 1.

Quy ước tên hàm của Swift là funcName(param1:param2:)và nó cần _một trình giữ chỗ để tạo tên của hàm.

Trong tên đầu tiên, tên là

divmod(_:_:)

Trong khi thứ hai là

divmod(a:b:)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.