Swiftの関数は必ず何らかの引数を取るということ
Swiftを触っていて、割と初歩的なことを認識できていなかったので備考録。
error: ambiguous use
下記のようなクロージャーを引数にする関数を持っているstructを実行すると
struct Music {
static func play(completion: @escaping () -> Void) {
print("🎵")
}
}
Music.play(completion: { (something) in } )
結果は
🎵
になります。ここまでは期待通りの動作です。
次に、このMusic structに
static func play(completion: @escaping (String) -> Void) {
print("🎵🎵🎵")
}
というString型を引数にするクロージャを引数に指定した同名のメソッドを宣言してみると、下記のようなエラーメッセージが表示されます。
Playground execution failed: error: MyPlayground.playground:10:1: error: ambiguous use of 'play(completion:)'
Music.play(completion: { (something) in } )
() -> Voidに対して、引数を持たないクロージャという認識だったため、上記のエラーで混乱してしまいました。
( そもそも引数を持たないという理解だったら、*Music.play(completion: { (something) in } )*で動くのがおかしいと思うべきだったかも・・)
Swiftの関数は必ず何らかの引数を取る。
クロージャで指定した**() -> Void** について考えてみます。
Swiftのモジュールを見ると
public typealias Void = ()
Voidというのは**()のエイリアスとなっています。
また、()型というのは空のタプルを表しているので、() -> Void** というのは空のタプルを受け取り、空のタプルを返すという事になります。
ドキュメントにも下記のように書かれています。
Functions without a defined return type return a special value of type Void. This is simply an empty tuple, which is written as ().
今回の場合、somethingという型の指定がない引数を取っていたため、このsomethingは**()型もString型**も取れる可能性があり、
コンパイラがメソッドを指定できなかったという事になります。
例えば、上記の処理を下記のように、型指定してあげるとエラーは修正されます。
Music.play(completion: { (r: String) in } )
Music.play(completion: { (r: ()) in } )
まとめ
- Swiftの関数は必ず、何らかの引数を取り、何らかの返り値を返す。
- () -> Void が引数を取らないクロージャという理解は良くない。
参考資料