なぜ下線をすばやく必要とするのですか?


161

ここでは「注:_「その値は気にしない」という意味ですが、JavaScriptから来たため、その意味がわかりません。

これらの関数を印刷できる唯一の方法は、パラメーターの前にアンダースコアを使用することでした。

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

下線がなければ、エラーを回避するために次のように記述する必要があります。

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

このアンダースコアの使い方がわかりません。いつ、どのように、なぜこれらのアンダースコアを使用するのですか?

回答:


353

さまざまな使用例にはいくつかのニュアンスがありますが、一般的に下線は「これを無視する」ことを意味します。


新しい関数を宣言するとき、アンダースコアは、呼び出されたときにパラメーターにラベルを付けてはならないことをSwiftに通知します。より完全な関数宣言は次のようになります。

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

「label」は引数ラベルであり、関数を呼び出すときに存在する必要があります。(そしてSwift 3以降、デフォルトではすべての引数にラベルが必要です。) "name"は関数内で使用するその引数の変数名です。短い形式は次のようになります。

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

これは、外部引数ラベルと内部パラメータ名の両方に同じ単語を使用できるようにするショートカットです。と同等func myFunc(name name: Int)です。

パラメータラベルなしで関数を呼び出せる_ようにする場合は、アンダースコアを使用して、ラベルを何も/無視しないようにします。(その場合、パラメーターを使用できるようにするには、内部名を指定する必要があります。)

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

割り当てステートメントでは、下線は「何にも割り当てない」ことを意味します。結果を返すが戻り値を気にしない関数を呼び出したい場合に、これを使用できます。

_ = someFunction()

または、リンクした記事のように、返されたタプルの1つの要素を無視するには、次のようにします。

let (x, _) = someFunctionThatReturnsXandY()

定義済みの関数タイプを実装するクロージャーを作成する場合、下線を使用して特定のパラメーターを無視できます。

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

同様に、プロトコルを採用する関数またはスーパークラスメソッドをオーバーライドする関数を宣言する場合_、パラメーターを使用してパラメーターを無視できます。プロトコル/スーパークラスでは、パラメータにラベルがないことも定義されている場合があるため、2つのアンダースコアが連続する場合もあります。

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

最後の2つのスタイルにある程度関連しています。ローカル変数/定数をバインドするフロー制御構成を使用_する場合、それを使用して無視できます。たとえば、メンバーへのアクセスを必要とせずにシーケンスを反復したい場合:

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

switchステートメントでタプルケースをバインドしている場合、この例のように、アンダースコアはワイルドカードとして機能します(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")
}

あまり関連性のない最後の1つは、(コメントで示されているように)ここから人々を導くように私が含めるためです:識別子のアンダースコアたとえばvar _foofunc do_the_thing()struct Stuff_は、特にSwiftには何も意味しませんが、いくつかの用途がありますプログラマの間で。

名前内のアンダースコアはスタイルの選択ですが、Swiftコミュニティでは推奨されていません。Swiftコミュニティでは、タイプにUpperCamelCaseを使用し、他のすべてのシンボルにlowerCamelCaseを使用することについて強い規則があります。

下線付きのシンボル名の接頭辞または接尾辞はスタイルの規約であり、エクスポートされたAPIからプライベート/内部使用のみのシンボルを区別するために歴史的に使用されていました。ただし、Swiftにはそのためのアクセス修飾子があるため、この規則は一般にSwiftでは慣用的ではないと見なされています。

2つのアンダースコアプレフィックス(func __foo())が付いたいくつかのシンボルは、AppleのSDKの奥深くに潜んでいます。これらは、NS_REFINED_FOR_SWIFT属性を使用してSwiftにインポートされた(Obj)Cシンボルです。Appleは、(Obj)C APIの「より迅速な」バージョンを作成したい場合に、たとえば、型に依存しないメソッドをジェネリックメソッドにしたい場合にそれを使用します。洗練されたSwiftバージョンを機能させるには、インポートされたAPIを使用する必要があるため、__ほとんどのツールやドキュメントから非表示にしながら、を使用して利用できるようにします。


@rickster、次のように、メソッドの開始時にアンダースコアの意味は何ですか-> func _copyContents(initializing ptr:UnsafeMutableBufferPointer <Element>)->(Iterator、UnsafeMutableBufferPointer <Element> .Index)}シーケンスプロトコルから。
dev gr

@devgr:まったく無関係なので、別の質問を投稿することをお勧めします。
リクスター

もちろん、別の質問を投稿します。
dev gr

関数を返すための「何にも割り当てない」をありがとう。これは私が探していたものでした。
18年

8

受け入れられた回答に加えて、使用例の1つは、_コードに長い数値を書き込む必要がある場合です。

より読みやすい番号

これは人間が判読しやすいものではありません。

let x = 1000000000000

_数字を追加して、人間が読みやすくすることができます。

let x = 1_000_000_000_000

6

Swift 3以降、関数呼び出しでパラメーター名を指定することが必須になりました。したがって、swift 2で記述されたコードに大きな問題を引き起こす可能性があるため、宣言時にアンダースコアを使用して、呼び出し時にパラメーター名を記述する必要をなくすことができます。したがって、この場合は、「外部パラメーター名は気にしない」と言っています。ここで、外部パラメーター名は、関数の内部ではなく(呼び出し時に)外部でパラメーターを呼び出すものです。これらの外部パラメーター名は、引数ラベルと呼ばれます。http://ericasadun.com/2016/02/09/the-trouble-with-argument-labels-some-thoughts/ ...パラメータに2つの名前が付けられる方法を確認するには?最初はアンダースコアが行くところです。これが役立つことを望み、まだ混乱しているかどうか尋ねてください。


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

_パラメータ名のプレースホルダです。あなたの例では、それらを別の方法で呼び出す、2番目の関数では、パラメーター名を記述する必要がありますa: 1

Swiftの関数名の規則はfuncName(param1:param2:)であり、関数の名前_を作成するにはプレースホルダーとしてが必要です。

名では、名前は

divmod(_:_:)

一方、2番目は

divmod(a:b:)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.