fc2ブログ

詳解Swift改訂版(02)〜関数

2016. 12. 28
この記事は詳解 Swift 改訂版(初版第1刷)を元に、Xcode 8.2.1(Swift 3.0.2)下における差異を記述しています。



CHAPTER 02 関数



●2.1 関数定義の基本


・関数定義の概要

List2-1 において、関数の引数のラベルは第1引数でも必要になりました。

func count(n: Int) -> Int {
    total += n
    return total
}

count(10)        // error: missing argument label 'n:' in call

Qiita/Xcode 8 Release Notes 日本語翻訳メモ」によると、Swift 3 で関数の引数は全ての引数でラベル付けされることになったようです。

これに関しては「Xcode 8 Release Notes(Xcode 8.0/Swift/New Features)」に、その旨の記述があります。

「関数の引数は現在、全ての関数の引数に渡って一貫したラベル付けを行うようになりました。
このアップデートでは第1引数の宣言が、これまでの第2以降の引数の動作と一致するようになりました。

以前に書かれたコードでは、

func Resolved Issues(x: Int, y: Int) {}
Resolved Issues(1, y: 2)

func bar(a a: Int, b: Int) {}
bar(a: 3, b: 4)

となっていましたが、現在は次のように記述します。

func Resolved Issues(_ x: Int, y: Int) {}
Resolved Issues(1, y: 2)
func bar(a: Int, b: Int) {}
bar(a: 3, b: 4)

(
SE-0046)」

したがって関数 count の呼び出しは以下のようになります。

count(n: 10)


・外部引数名

上記の通り関数は全ての引数でラベル付けされるようになりましたので、これまでの Objective-C のメソッド記法のように関数名に第1引数の意味を含める必要は無くなったと思われます。
今後はシンプルな関数名で構わないでしょう。

List2-2 を例にすると、

func buyProduct(product:Int, price:Int, quantity:Int) {
    print("Product:\(product), amount = \(price * quantity)")
}

buyProduct(product: 19090, price: 180000, quantity: 1)        // Product:19090, amount = 180000

関数名に第1引数の意味を含み、且つ第1引数のラベルもあって冗長になりますので、関数名から第1引数の意味を取り除いた方がいいでしょう。

func buy(product:Int, price:Int, quantity:Int) {
    print("Product:\(product), amount = \(price * quantity)")
}

buy(product: 19090, price: 180000, quantity: 1)        // Product:19090, amount = 180000

また今回の例で言えば、関数名 buy だけでは単純すぎて心許なく、引数の product はカタログ番号であることから、関数名をそのままに第1引数名を number とする手もあるでしょう。

func buyProduct(number:Int, price:Int, quantity:Int) {
    print("Number:\(number), amount = \(price * quantity)")
}

buyProduct(number: 19090, price: 180000, quantity: 1)        // Number:19090, amount = 180000

もしくは「_」で第1引数の外部引数名を省略することで、これまでと同じ挙動にすることもできます。

func buyProduct(_ product:Int, price:Int, quantity:Int) {
    print("Product:\(product), amount = \(price * quantity)")
}

buyProduct(19090, price: 180000, quantity: 1)        // Product:19090, amount = 180000

いずれにせよ、これまでの記法には再考の余地があります。

※ 以降において、第1引数のラベル付けに関する修整については、分かり易さのために「_」で呼び出し時の外部引数名を省略することにし、特別な理由がなければ説明を割愛します。


・外部引数名の指定と省略

上記の通り第1引数も自動的に外部引数名が付与されることになりましたが、

func area(h:Double, w:Double) -> Double {
    return h * w
}

let a = area(h: 10.0, w: 12.5)

これまでと同様、内部引数名と別途に外部引数名を指定することもできます。

func area(height h:Double, width w:Double) -> Double {
    return h * w
}

let a = area(height: 10.0, width: 12.5)



●2.2 関数定義におけるさまざまな設定


・inout 引数

List 2-3 において、inout 引数でエラーが出るようになりました。

func mySwap(inout _ a:Int, inout _ b:Int) {        // 'inout' before a parameter name is not allowed. place it before the parameter type instead

Qiita/Xcode 8 Release Notes 日本語翻訳メモ」によると、Swift 3 で inout 引数は : の後ろに書くことになったようです。

これに関しては「Xcode 8 Release Notes(Xcode 8.0/Swift/New Features)」に、その旨の記述があります。

「inout 属性の場所が : の後ろ且つ引数型の前に移動されています。
例えば以前に書かれたコードでは、

func Resolved Issues(inout x: Int) {
}

ですが、現在は次のように記述する必要があります。

func Resolved Issues(x: inout Int) {
}

(SE-0031)」


したがって関数 mySwap の引数は以下のようになります。

func mySwap(_ a: inout Int, _ b: inout Int) {


・関数の引数に規定値を指定する

List2-4 の関数 setFont の実行結果の例で、規定値を指定した引数の順序を入れ替えた場合にエラーが出るようになりました。

setFont(name: "Times", bold:true, size:18.0)        // error: argument 'size' must precede argument 'bold'

Qiita/Xcode 8 Release Notes 日本語翻訳メモ」によると、Swift 3 で規定値を持つ引数は宣言順に指定することになったようです。

これに関しては「Xcode 8 Release Notes(Xcode 8.0/Swift/New Features)」に、その旨の記述があります。

「デフォルト値を持つ関数の引数は、現在宣言順に指定する必要があります。
呼び出し時に提供する引数の位置は、常に宣言された順序で関数に渡す必要があります。

func requiredArguments(a: Int, b: Int, c: Int) {}
func defaultArguments(a: Int = 0, b: Int = 0, c: Int = 0) {}

requiredArguments(a: 0, b: 1, c: 2)
requiredArguments(b: 0, a: 1, c: 2)        // error
defaultArguments(a: 0, b: 1, c: 2)
defaultArguments(b: 0, a: 1, c: 2)        // error

指定された引数が宣言の順序に従う限り、デフォルト値を持つ任意のラベル付き引数を省略することができます。

defaultArguments(a: 0)        // ok
defaultArguments(b: 1)        // ok
defaultArguments(c: 2)        // ok
defaultArguments(a: 1, c: 2)        // ok
defaultArguments(b: 1, c: 2)        // ok
defaultArguments(c: 1, b: 2)        // error

(SE-0060)」


したがって関数 setFont の引数は以下のようになります。

setFont(name: "Times", size:18.0, bold:true)        // Times 18.0 [B]


・引数の値を処理中に変更できるようにする

List2-6 の関数 dayOfWeek において、引数への var 修飾語の付与はエラーが出るようになりました。

func dayOfWeek(var _ m:Int, _ d:Int, var year y:Int = 2016) -> Int {        // error: parameters may not have the 'var' specifier

Qiita/Xcode 8 Release Notes 日本語翻訳メモ」によると、Swift 3 で関数の引数で var が使えなくなったようです。

これに関しては「Xcode 8 Release Notes(Xcode 8.0/Swift/New Features)」に、その旨の記述があります。

「var はもはや関数の引数属性として認められません。
コンパイラは関数本体にシャドウコピーを作成するための修正を提供します。
例えば以前に書かれたコードが、

func Resolved Issues(var x: Int) {
}

となっていた場合、現在は次のように記述する必要があります。

func Resolved Issues(x: Int) {
  var x = x
}

(
SE-0003)」

したがって関数 dayOfWeek の引数指定は以下のようになります。

func dayOfWeek(_ m:Int, _ d:Int, year y:Int = 2016) -> Int {
    var m = m, y = y

また本文中で「変更しないことを明示するために let という修飾語を使うことができます。」とありますが、「Qiita/Xcode 8 Release Notes 日本語翻訳メモ」にSwift 3で無駄な let は削除されたとあり、「Xcode 8 Release Notes(Xcode 8.0/Swift/New Features)」に、その旨の記述があります。

「let はもはや関数の引数属性として認められません。
コンパイラは関数の宣言から削除するための修正を提供します。(
SE-0053)」

例えば関数 dayOfWeek の引数 d に let を指定すると警告が出ます。

func dayOfWeek(_ m:Int, let _ d:Int, year y:Int = 2016) -> Int {        // 'let' as a parameter attribute is not allowed


・返り値を必ず使うための指定

返り値を伴う関数に @warn_unused_result 属性を指定すると警告が出るようになりました。

@warn_unused_result        // 'warn_unused_result' attribute behavior is now the default
func dayOfWeek(_ m:Int, _ d:Int, year y:Int = 2016) -> Int {

Tomorrow Never Comes./[Swift]関数の返り値を使わない時は」によると、Swift 3 から関数の返り値を使用しない場合はデフォルトで警告が出るようになったため、@warn_unused_result は不要になったようです。

逆に返り値を使用しないことを明示するには @discardableResult 属性を指定することになります。

ただしプレイグラウンドでは、返り値を伴う関数を返り値を使用しない形で実行しても警告が出ないようなので注意が必要です。



Qiita/Xcode 8 Release Notes 日本語翻訳メモ

Tomorrow Never Comes./[Swift]関数の返り値を使わない時は

詳解Swift 第3版(Amazon)
 

Calendar
11 | 2016/12 | 01
Sun Mon Tue Wed Thu Fri Sat
- - - - 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Recent Articles
Wish List
iOS/iPadOS Devices
Twine
Twine Reference
1. 序章
2. はじめに
2.1. Twineのインストール
2.2. 基本コンセプト
2.3. Twineを使いこなす
2.4. Twineのアップデート
2.5. Twineのアンインストール
2.6. Twineの古いバージョンを使う
3. ストーリーライブラリを使う
3.1. ストーリーの表示
3.2. ストーリーの作成、コピー、インポート
3.3. ストーリーの編集
3.4. ストーリー名の変更
3.5. ストーリーのアーカイブとエクスポート
3.6. ストーリーの削除
3.7. ストーリーへのタグ付け
3.8. ライブラリの場所を変更する
4. ストーリーの編集
4.1. ストーリーマップのナビゲーション
4.2. 取り消しとやり直し
4.3. パッセージの選択と移動
4.4. パッセージの編集
4.5. パッセージのリンク
4.6. パッセージの削除
4.7. パッセージのタグ付け
4.8. テキストの検索と置換
4.9. ストーリー名の変更
4.10. ストーリーフォーマットの変更
4.11. ストーリーの統計の表示
4.12. ストーリーのJavaScriptとCSSを編集する
5. 作品の公開出力
5.1. ストーリーのテスト
5.2. ストーリーの校正
5.3. ストーリーのプレイ
5.4. ストーリーの公開出力
5.5. スクラッチフォルダ
6. ストーリーフォーマットの管理
6.1. ストーリーフォーマットの表示
6.2. デフォルトのストーリーフォーマットの変更
6.3. 校正フォーマットの変更
6.4. ストーリーフォーマットの追加
6.5. ストーリーフォーマットの削除
6.6. ストーリーフォーマットの拡張機能を無効にする
6.7. Twineがストーリーフォーマットのバージョンを管理する方法
7. Twineのカスタマイズ
7.1. 環境設定の設定
7.2. コマンドラインスイッチ
7.3. 高度なカスタマイズ
8. 制限事項
8.1. 大きなストーリー
8.2. ストーリーの組み合わせ
8.3. ストーリーの共同編集
8.4. 画像とマルチメディアの使用
8.5. ソースコントロールでの作業
9. 問題のトラブルシューティング
9.1. バックアップ
9.2. ローカルストレージの直接表示
9.3. 編集中にエラーメッセージが表示される場合
9.4. Twineが起動しない場合
9.5. Twineがあなたのストーリーを失ったら
9.6. ストーリーが破損している場合
9.7. Twineの外観に不具合がある場合
10. リリースノート
10.1. バージョン 2.8
10.2. バージョン 2.7
10.3. バージョン 2.6
10.4. バージョン 2.5
10.5. バージョン 2.4
10.6. バージョン 2.3
10.7. バージョン 2.2
10.8. バージョン 2.1
10.9. バージョン 2.0
10.10. バージョン 1.0
10.11. Tweebox バージョン

Twine Cookbook
詳解Swift
詳解Swift第5版(01)〜Swiftでプログラミング
詳解Swift第5版(02)〜関数
詳解Swift第5版(03)〜構造体
詳解Swift第5版(04)〜オプショナル
詳解Swift第5版(05)〜プロトコル
詳解Swift第5版(06)〜基本的なデータ型
詳解Swift第5版(07)〜パターン
詳解Swift第5版(08)〜クラスと継承
詳解Swift第5版(09)〜メモリ管理
詳解Swift第5版(10)〜拡張
詳解Swift第5版(11)〜エラー処理
詳解Swift第5版(12)〜クロージャ
詳解Swift第5版(13)〜ジェネリクス
詳解Swift第5版(14)〜メモリへのアクセスとポインタ
詳解Swift第5版(15)〜カスタム属性とDSL記法
詳解Swift第5版(16)〜GUI との連携

詳解Swift第4版(01)〜Swiftでプログラミング
詳解Swift第4版(02)〜関数
詳解Swift第4版(03)〜構造体
詳解Swift第4版(06)〜基本的なデータ型
詳解Swift第4版(07)〜パターン
詳解Swift第4版(08)〜クラスと継承
詳解Swift第4版(09)〜メモリ管理
詳解Swift第4版(10)〜拡張
詳解Swift第4版(11)〜エラー処理
詳解Swift第4版(12)〜クロージャ
詳解Swift第4版(13)〜ジェネリクス

詳解Swift第3版(01)〜Swiftでプログラミング
詳解Swift第3版(02)〜関数
詳解Swift第3版(03)〜構造体
詳解Swift第3版(05)〜基本的なデータ型
詳解Swift第3版(06)〜パターン
詳解Swift第3版(07)〜演算子
詳解Swift第3版(08)〜クラスと継承
詳解Swift第3版(09)〜メモリ管理
詳解Swift第3版(10)〜プロトコル
詳解Swift第3版(11)〜拡張
詳解Swift第3版(12)〜エラー処理
詳解Swift第3版(13)〜クロージャ
詳解Swift第3版(14)〜ジェネリクス

詳解Swift改訂版(01)〜Swiftでプログラミング
詳解Swift改訂版(02)〜関数
詳解Swift改訂版(03)〜構造体
詳解Swift改訂版(04)〜オプショナル
詳解Swift改訂版(05)〜基本的なデータ型
詳解Swift改訂版(06)〜パターン
詳解Swift改訂版(07)〜演算子
詳解Swift改訂版(08)〜クラスと継承
詳解Swift改訂版(09)〜メモリ管理
詳解Swift改訂版(10)〜プロトコル
詳解Swift改訂版(11)〜拡張
詳解Swift改訂版(12)〜エラー処理
詳解Swift改訂版(13)〜クロージャ
詳解Swift改訂版(14)〜ジェネリクス

詳解Swift(1)〜Swiftでプログラミング
詳解Swift(2)〜関数
詳解Swift(3)〜構造体
詳解Swift(4)〜オプショナル
詳解Swift(5)〜基本的なデータ型
詳解Swift(6)〜パターン
詳解Swift(7)〜演算子
詳解Swift(8)〜クラスと継承
詳解Swift(9)〜メモリ管理
詳解Swift(10)〜プロトコル
詳解Swift(11)〜拡張
詳解Swift(12)〜クロージャ
詳解Swift(13)〜ジェネリクス
詳解Swift(14)〜C/Objective-Cとのデータ受け渡し
Swift
Site Map
Apple Music


Categories
Tips
ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
QR Code
QR
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ

Visitors