55265


Swiftで、以下のコードが何をやっているのか教えてください。  
<https://github.com/johnjcsmith/iPhoneMoCapiOS/blob/master/iPhoneMoCap/FaceGeoViewController.swift>

[code]

        let message = $0.reduce("", {
            result, input in
            result.appending("\(input.key.rawValue) - \(Int(input.value.doubleValue * 100))|")
        })
    
[/code]

私には、上記のコードを読んでも、「クロージャを使って、何らかの値を足し合わせたりしている感じなんだろうか？」というざっくりしたことしか分かりません。。

エスケープ文字回避なのか何なのか、(input.key.rawValue)の前の部分に、バックスラッシュが入っている理由や、"|"が入っている理由が分かりません。  
また、プログラム内の他の箇所にresult変数やinput変数が出てきていないのに突然登場してきて理由などもよく分かりません。

reduceの後に空白の文字列、""が登場しているのは、この文字列に何かを足し合わせて代入しているという感じなのでしょうか？？

全体的にswiftのことをよく知らないのでこの文法について教えていただけると嬉しいです。


CC BY-SA 4.0
2019-05-26T11:26:45.203
55262
2019-05-26T14:25:28.583
34471
question
swift ios クロージャ
Swiftのクロージャの使い方についての質問


まず最初に。「全体的にswiftのことをよく知らない」との事でしたら、入門書や入門サイト(残念ながら日本語の良いサイトは私は知りませんが…)を見て、基本的な事項については習得してからご質問を書くことをお勧めしておきます。Q&Aの形式でプログラミング言語の基本を学習するのは、かえって面倒になることが多いです。

ちなみにSwift以外のプログラミング言語のことなら多少は知っている、と言う場合にはそのことを書いておくと、よりわかりやすい説明を得られるかもしれません。

* * *

前置きが長くなりましたが、今回の質問内容については、ある程度範囲が絞り込めているので、それぞれ回答してみようと思います。

**_(input.key.rawValue)の前の部分に、バックスラッシュが入っている理由_**

Swiftの文字列補間と言うものを使っています。`"..."`と言う構文が文字列リテラルを表していると言うことまではおわかりのようですが、Swiftの場合文字列リテラルの途中に`\(式)`と言うものを挟み込んでやると、その式を文字列変換したものと他の部分をつなげた文字列を作ってくれます。

例えば、

[code]

    let a = 1
    let b = 2
    let message = "a + b = \(a + b)"
    print(message) //->a + b = 3
    
[/code]

とやると、`a + b =`の部分はそのまま文字列として扱われますが、`\(a +
b)`の部分は式として評価された結果の`3`が表示されているのがわかるでしょう。

**_"|"が入っている理由_**

単に文字列の一部です。上の例でも`a + b
=`の側の`+`や`=`には何の意味もありません。単に文字列に含まれる文字として`+`や`=`を表示したかったからそこに入れているだけです。あなたが例に挙げられた`"|"`も同じことです。それを`";"`なんかの別の文字に変えても、文字列の中身にその通りに入っていくだけです。

**_プログラム内の他の箇所にresult変数やinput変数が出てきていないのに突然登場してきて理由_**  
**_reduceの後に空白の文字列、""が登場しているのは、この文字列に何かを足し合わせて代入しているという感じなのでしょうか？？_**

以下にまとめて **`reduce`の使い方** と合わせて説明します。

まず、`reduce`と言うのは配列等に対して、`a = a +
b`型の計算を繰り返し行った結果を計算するためのメソッドです。例では文字列を作っていますが、最初は数値の方がわかりやすいでしょう。

[code]

    let arr = [1, 2, 3, 4, 5]
    let sum = arr.reduce(0, +)
    print(sum) //->15
    
[/code]

`reduce`の引数のうち、最初の`0`が初期値、2個目の`+`が繰り返して欲しい計算を表しています。

こう書くのとほとんど同じ意味になります。

[code]

    var result = 0
    for input in arr {
        result = result + input
    }
    let sum = result
    
[/code]

行いたい計算は足し算ばかりではないでしょうから、第2引数で指定できるようになっています。例えば掛け算ならこんな風に書けます。

[code]

    let prod = arr.reduce(1, *)
    print(prod) //->120
    
[/code]

* * *

では、もっと複雑な計算をしたかったらどう書けば良いのでしょうか。例えばこれと同等の計算。

[code]

    var result = 0
    for input in arr {
        result = result * 10 + input
    }
    let number = result
    print(number) //->12345
    
[/code]

Swiftでは、このような場合に、任意の「計算」を引数として渡すためにクロージャというものを使います。基本はこんな構文です。

`{ 仮引数 in 式 }`

(単純な「式」1個の代わりにもっと複雑な計算も書けるのですが、ここでは省略しておきます。)

上の繰り返しは、`reduce`を使うとこんな風に書けます。

[code]

    let number = arr.reduce(0, {result, input in result * 10 + input})
    
[/code]

ここで`result`, `input`は仮引数で、お好みなら任意の別の名前に変えても構いません。

[code]

    let number = arr.reduce(0, {r, x in r * 10 + x})
    
[/code]

Swiftのクロージャでは`{`の直後の「仮引数」はその場で宣言されたことになります。

(もっと短く書きたいんなら`仮引数 in`の部分も省略できるんですが、ここではその記法にも触れないでおきます。)

「プログラム内の他の箇所にresult変数やinput変数が出てきていないのに突然登場してきて理由」はお分りいただけましたでしょうか。関数定義を書くとき

[code]

    func f(_ a: Int, _ b: Int) -> Int {
       return a + b
    }
    
[/code]

仮引数の`a`や`b`は「プログラム内の他の箇所に出てきていないのに突然登場」しますよね? それと同じことです。

* * *

「reduceの後に空白の文字列、""が登場している」のは、`reduce`に与えるための「初期値」だということは、もうお判りいただけるでしょうか。

[code]

    var result = ""
    for input in arr {
        result = result + "\(input);"
    }
    let connected = result
    print(connected) //->1;2;3;4;5;
    
[/code]

この繰り返し、空文字列`""`から始めて、それに`"数字;"`という文字列を付け加えるというものです。これは簡単に`reduce`に置き換えられて、こう書けます。

[code]

    let connected = arr.reduce("", {result, input in result + "\(input);"})
    
[/code]

ここでは文字列の連結に`+`演算子を使いましたが、Swiftの`String`型には`appending`というメソッドがあり、そちらも文字列の連結に使えます。`str1
+ str2`と書くのと`str1.appending(str2)`と書くのとは全く同じ結果になります。

[code]

    let connected = arr.reduce("", {result, input in result.appending("\(input);")})
    
[/code]

* * *

大変ざっくりですが、ご質問頂いた項目については答えたつもりです、いかがだったでしょうか?

(結構な長文になってしまいましたが、「ざっくり」でなく、ちゃんと書くと、もっとはるかに長くなってしまいます。)

リンク先のようなサンプルアプリでも、基本がわからないまま読み解いていくのはかなり難しいだろうと思います。どのような目的でSwiftのコードを読んでいっておられるのか分りませんが、「順番間違えると帰って時間がかかるんじゃないですか」とは言っておきたいと思います。


CC BY-SA 4.0
2019-05-26T14:25:28.583
55265
2019-05-26T14:25:28.583
13972
55262
answer