質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

2205閲覧

Swift @inlinable属性について

moriman

総合スコア615

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

1クリップ

投稿2020/02/16 06:03

final class ImageStore { typealias _ImageDictionary = [String: CGImage] fileprivate var images: _ImageDictionary = [:] fileprivate static var scale = 2 static var shared = ImageStore() func image(name: String) -> Image { let index = _guaranteeImage(name: name) return Image(images.values[index], scale: CGFloat(ImageStore.scale), label: Text(name)) } static func loadImage(name: String) -> CGImage { guard let url = Bundle.main.url(forResource: name, withExtension: "jpg"), let imageSource = CGImageSourceCreateWithURL(url as NSURL, nil), let image = CGImageSourceCreateImageAtIndex(imageSource, 0, nil) else { fatalError("Couldn't load image (name).jpg from main bundle.") } return image } fileprivate func _guaranteeImage(name: String) -> _ImageDictionary.Index { if let index = images.index(forKey: name) { return index } images[name] = ImageStore.loadImage(name: name) return images.index(forKey: name)! } }

swiftUIのチュートリアル
https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation
に出てくるコードなのですが、
_guaranteeImage(name: String)メソッドの中に出てくるimages.index(forKey: name)の定義に飛ぶと、

extension Dictionary : Collection { //省略 /// Returns the index for the given key. /// /// If the given key is found in the dictionary, this method returns an index /// into the dictionary that corresponds with the key-value pair. /// /// let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"] /// let index = countryCodes.index(forKey: "JP") /// /// print("Country code for (countryCodes[index!].value): '(countryCodes[index!].key)'.") /// // Prints "Country code for Japan: 'JP'." /// /// - Parameter key: The key to find in the dictionary. /// - Returns: The index for `key` and its associated value if `key` is in /// the dictionary; otherwise, `nil`. @inlinable public func index(forKey key: Key) -> Dictionary<Key, Value>.Index?

上記のコードが出てきました。コメントを見るとだいたい「キーを指定すると対応するインデックスを返す」くらいのことはわかるのですが、文法というかコードの作りとして上記のコードは、

エクステンションを用いてDictionary型がCollectionプロトコルに準拠している。
そのために必要な実装をブロック内に記述する。その一部が上記の

@inlinable public func index(forKey key: Key) -> Dictionary<Key, Value>.Index?

ということだと思うのですが、メソッドの実装がありません。(引数名、引数の型注釈、戻り値の型注釈のみ)
index(forKey key: Key)メソッドの本体(実装)は書かなくて良いのでしょうか?

多分@inlinable属性が関係あるようなので
https://docs.swift.org/swift-book/ReferenceManual/Attributes.html
のinlinableの部分を見て、インライン関数、インライン展開などネットで調べたのですが、いまいちよくわかりません。

結局@inlinableをつけると、メソッドの本体を呼び出し側に記述できる、ということなのでしょうか?
そしてそれが

images.index(forKey: name) { return index }

の最後の{ return index }の部分なのでしょうか?

ただ、2つ目のサンプル(コメントに書いてあるサンプルコード)のメソッド呼び出しでは、

let index = countryCodes.index(forKey: "JP")

とあり、本体部分は記述されていません(普通の関数呼び出し)。それでも普通に期待通りの挙動で結果が返されます。
つまり呼び出し側で本体を定義しない場合はどこかに事前に作ってある定義が呼び出される、みたいなことなんでしょうか?

全て推測なのですが、どういう仕組みなんでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ライブラリの関数などでJump to Definitionで表示されるものはコンパイラが生成したドキュメント的なInterfaceのみで実装は表示されません。
実装はGitHubで確認しましょう。

@inlinableはコンパイル時に関数呼び出しでなく呼び出し部分に実装を埋め込んでも良い。というコンパイラへの指示です。
これは最適化の一種で関数呼び出しは重い処理なので埋め込みを行うと実行が速くなります。

投稿2020/02/16 07:00

MasakiHori

総合スコア3384

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

moriman

2020/02/17 07:07

わかりました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問