from Minority

〜log

処理をまとめる[関数・クロージャ]

関数

func 関数名 ( パラメタ ) -> 戻り値の型 {
    処理内容
}
func doubleVal(val: Int) -> Int {
   return val * 2
}


  • パラメタ・戻り値なし
// パラメタ無し
func sayHello() {
    println("Hello")
}

// 戻り値無し
func sayHello() -> Void {
    println("Hello")
}


  • 複数のパラメタ・戻り値
// 複数のパラメタ
func multiply(val1: Int, val2: Int) -> Int {
   return val1 * val2
}

// 戻り値のタプル仕様
func httpRequest(url: String) -> (Int, String) {
    return (404, "Not Found")
}

let (code, message) = httpRequest()
code // 404
message // "Not Found"


  • パラメタ外部名
func joinPieces(arr: [String], withGlue glue: String) -> String {
    return glue.join(arr)
}

joinPieces(["a","b","c"], withGlue: ":")
// "a:b:c"


  • 外部名と内部名が等しい
func joinPieces(arr: [String], #withGlu: String) -> String {
    return glue.join(arr)
}

joinPieces(["a","b","c"], withGlue: ":")
// "a:b:c"

パラメタ・外部名が違えば別関数
関数名では特定できない
外部名を持たない第一パラメタについては「」記号で表現

joinPieces(_: withGlue: )


  • パラメタのデフォルト値
func joinPieces(arr: [String], withGlue glue: String = ":") -> String {
    return glue.join(arr)
}

joinPieces(["a","b","c"])
// "a:b:c"


  • デフォルト値と外部名
// デフォルト有り
func joinPieces1(arr: [String], glue: String = ":") -> String {
    return glue.join(arr)
}

// デフォルト無し
func joinPieces2(arr: [String], glue: String) -> String {
    return glue.join(arr)
}

// 外部名が必要
joinPieces1(["a","b","c"], glue: ":")
// "a:b:c"

// 外部名が不要
joinPieces2(["a","b","c"], ":")
// "a:b:c"


  • 可変数パラメタ
func sum(mumbers: Int...) -> Int {
  var sum = 0
  for mum in mumbers {
      sum += mum
  }
  return sum
}

sum(1,2,3,4,5) // 15


  • パラメタの変更と参照
// 関数内での定数と変数
func repeatFrom(var from: Int, #to: Int) { // formにvarをつけて変数定義
  do {
    println("\(from)")
    // 5 6 7 8 9 10
  } while ++from <= to // formのインクリメント
}

var from = 5
repeatFrom(from to:10)
from // 5
// 元の値は維持


  • inoutパラメタ
func swap(inout a: Int, inout b: Int) {
  let temp = a
  a = b
  b = temp
}

var a = 1
var b = 2
swap(&a, &b) // 参照渡し
a // 2
b // 1


  • 関数型 / すべての関数は「関数型」を持つ
// 同一の関数型
func add(a: Int, b: Int) -> Int {
  return a + b
}

func multiply(a: Int, b: Int) -> Int {
  return a * b
}

これはどちらも

(Int, Int) -> Int

という関数型を持っている


  • 関数型の定義
// 「(Int, Int) -> Int」型の変数calcFuncを定義してaddを初期値として設定
var calcFunc: (Int, Int) -> Int = add

calcFunc(1, 2) // 3
  • 関数型を使用した関数
func zero(a: Int, b: Int) -> Int {
 return 0
}

// 戻り値「(Int, Int) -> Int」を返す
func getCalcFunc(name: String) -> (Int, Int) -> Int {
  switch name {
    case "add":
      return add

    case "multiply":
      return multiply

    default:
      return zero
  }
}

// 戻り値が関数なのでそのままパラメタを渡す
getCalcFunc("add")(3, 4) // 7
getCalcFunc("multiply")(3, 4) // 12


クロージャ / 名前を持たない関数

{( パラメタ ) -> 戻り値 in
   処理内容
}
  • 実装例
{(a: Int, b: Int) -> Bool in 
   return a < b
}

「(Int, Int) -> Bool」の型をもつ値


  • 定義済の関数を使用したsorted関数の使用
func compare(a: Int, b: Int) -> Bool {
  return a < b
}

var arr = [3, 5, 1, 2, 4]
sorted(arr, compare) // [1, 2, 3, 4, 5]
var arr = [3, 5, 1, 2, 4]
sorted(arr, {
  (a: Int, b:int) -> Bool in 
  return a < b
})
// [1, 2, 3, 4, 5]


  • 型推測
var someFunc: (Int, Int) -> Bool

//パラメタ・戻り値の型省略
someFunc = {
  a, b in
  return a < b
}


  • sorted関数が型を決めてる
var arr = [3, 5, 1, 2, 4]
sorted(arr, {
  a, b in
  return a < b
})


  • パラメタ表記 / 戻り値の省略
var arr = [3, 5, 1, 2, 4]

// 元の形
sorted(arr, {
  (a: Int, b: Int) -> Bool in
  return a < b
})

// 型推測による省略形
sorted(arr, {
  a, b in
 return a < b
})

// パラメタの省略形
sorted(arr, {
  return $0 < $1
})

// returnの省略形
sorted(arr, {
  $0 < $1
})

「<」演算子は「(Int, Int) -> Bool」の型を持っているので・・・

var arr = [3, 5, 1, 2, 4]

sorted(arr, <)

とも書ける・・・。Σ(゚д゚;)えー! ちょっと感動。 こういう考え方に早く出会いたかったなぁ。


var arr = [3, 5, 1, 2, 4]

sorted(arr){$0 < $1}

クロージャが関数の最後のパラメタになるときこう記述可


var arr = [3, 5, 1, 2, 4]

// 通常の記述
arr.map({
  (mumber: Int) -> String in
  return "(\(mumber))"
})

// トレイリングクロージャ
arr.map{
  (mumber: Int) -> String in
  return "(\(mumber))"
}
// 関数のパラメタを表す( )の省略パターン

むむっ。ややこしい。


値のキャプチャ

func makeProgressBar(mark: String) -> ( ) -> String {
  var bar = ""
  func progressBar( ) -> String {
    bar += mark
    return bar
  }
  return progressBar
}
// progressBar( )が、定数markや変数barをキャプチャしている状態
// 関数のネストと関数を返す関数


var plusProgressBar = makeProgressBar("+")
plusProgressBar( ) // "+"
plusProgressBar( ) // "++"
plusProgressBar( ) // "+++"

注意キーワード):循環参照


まとめ

クロージャは多様な省略ルールを知らないとコード読めない。 順をおってひとつずつ。