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

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

ただいまの
回答率

90.38%

  • Swift

    9182questions

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

中身がnilかチェックをするはずのif letにnilが代入される

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,317

Blue0999

score 62

以下の関数convInt()は引数に文字列を代入し空文字ならエラーを投げ、整数に直せる場合はその整数自身を返し、整数に直せない場合はnilを返すというものです。
質問の箇所はfor文内のif let文です。if letは代入される値がnilでなければ代入し処理を実行する、というものだと思っているのですがif文をブロック内の処理とするfor文で使われている定数sに格納された配列内の"str"を関数convIntの引数として実行され定数xに代入される場合、nilが返されるので代入できないと思うのですが、正常に代入されif let文内の処理も実行されています。なぜnilが返されるはず関数をxに代入する事ができたのでしょうか?
enum FooError:ErrorType {
    case Ooal
}
func convInt(s:String) throws -> Int? {
    if s == "" {
        throw FooError.Ooal
    }
    return Int(s)
}

for s in ["1", "str", ""] {
    if let x = try? convInt(s) {
        print(x)
    } else {
        print("Failure")
    }
}

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+3

if letは代入される値がnilでなければ代入し処理を実行する

そうですね
では代入されている値は何ですか?
try? convInt(s)ですね。
try? vは正常パスならv、例外だったらnilを返します。
v:Vだったとした場合、try? vV?を返します。

つまり、try? convInt(s)の戻り値の型はInt??です。
なので、
if let x = try? convInt(s)において、xの型はInt??です。

さて、
Int?nilInt??nilは別物です。
それぞれ、Optional<Int>.None と Optional<Optional<Int>>.Noneです。

convInt("str")Optional<Int>.Noneを返しますが、
これは、Optional<Optional<Int>>的には存在する値(Some)なので、
if letx:Int??に代入可能です。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/24 13:21

    丁寧に説明して頂きとても助かりました!
    if letはnilを代入しないがnil?は別物だという事ですね。

    キャンセル

  • 2016/03/24 13:39

    問題点がやっとわかった。
    print(try? convInt(s))
    をすると分かりやすいです。
    http://qiita.com/koher/items/c6f446bad54442a28bf4
    このページが参考になります。

    キャンセル

+1

nil と 空(””)とは異なりますよ

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/24 12:51

    横からすみません
    これ。不思議ですね。
    質問者さんがおっしゃっているのは
    "str"の場合にもprint(x) が通ってしまうということですよね?

    for s in ["1", "str", ""] {
    let test = try? convInt(s)
    if let x = test {
    print(x)
    } else {
    print("Failure")
    }
    }
    で通しましたが、やはりprint(x) 通ります、
    try? convInt(s)で int?? が返されて、if let x = test
    にてxにnil?が入ってきてしまいますね。
    二重にoptional型になっているとif letでも入ってきてしまうのかもしれませね・・・

    キャンセル

  • 2016/03/24 13:04 編集

    tomohiro_obaraさん、わかりづらい質問になってしまってすみませんでした。

    キャンセル

  • 2016/03/24 13:05

    Rumi_Igarashiさん、不思議ですよね。確かに二重のoptional型になっているとif letに入ってしまうのかもしれません。

    キャンセル

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

  • ただいまの回答率 90.38%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Swift

    9182questions

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