LoginSignup
2
2

[Swift]むりやりPoint-Free Style

Last updated at Posted at 2023-12-30

Point-Free Styleとは

関数を渡す関数を使う時にTrailing closureやクロージャ式を使わず関数の識別名を渡すスタイルのことです。
たとえば

func add2(_ i: Int) -> Int {
    i + 2
}

という関数を配列内の全てに適用する時に

intArray.map { add2($0) }
// または
intArray.map( { add2($0) } )

と書くかわりに

intArray.map(add2)

と書くスタイルです。

こちらもPoint-Free Styleです。

// 全ての要素を足し合わせる
intArray.reduce(0, +)

引数のメソッドを使いたい

ところが引数のメソッドを使いたい場合通常のやり方ではPoint-Free Styleが使えません。

// 全ての要素が偶数かどうか
intArray.allSatisfy { $0.isMultiple(of: 2) }

むりやり使うための知識

Swiftのメソッドの型

Swiftの関数には型が存在します。たとえば先ほどのadd2関数の型は(Int) -> Intです。

func add2(_ i: Int) -> Int {
    return i + 2
}

print(type(of: add2)
// prints (Int) -> Int

ではメソッドの型はどうなっているでしょう。

print(type(of: 0.isMultiple))
// print (Int) -> Bool

これも関数と同じ形式の型になっています。
ところがメソッドにはもう一つの取り出し方があります。

print(type(of: Int.isMultiple))
// print (Int) -> (Int) -> Bool

型名.メソッド名という形で取り出すことで、インスタンスを引数にとりそのインスタンスがもつメソッドと同形の関数を返す関数として取り出せます。

let method = Int.isMultiple

let methodForOne = method(1) // 1.isMultiple と同じ
print(methodForOne(2))  // 1.isMultiple(of: 2) と同じ
// prints false

// あるいは
print( method(1)(2) )
// prints false

引数の順番を入れ替える

これを使えばPoint-Free Styleを使えそうです。
しかし、引数の順番が逆なのでこれを入れ替える関数が必要です。

func flip<A, B, C>(_ f: @escaping (A) -> (B) -> C) -> (B) -> (A) -> C {
    { b in { a in f(a)(b) } }
}

むりやりPoint-Free Style

準備が整いました。先ほど出した例をむりやりPoint-Free Styleで書いてみましょう。

元の形

// 全ての要素が偶数かどうか
intArray.allSatisfy { $0.isMultiple(of: 2) }

むりやりPoint-Free Style

intArray.allSatisfy(flip(Int.isMultiple)(2))

まとめ

これで引数のメソッドを利用したい時でもPoint-Free Styleで書くことができるようになりました。
ほかにもむりやりPoint-Free Styleはあるはずです。これはPoint-Free Styleは無理とあきらめずに探しだしてみましょう。
変な奴と後ろ指さされること間違いなしです。

追記

問題点があったので追記です。

問題点

引数を持たないメソッドの場合flip関数が使えない。

以下のような場合です。

// struct Int {
//  func signum()
// }

intArray.map(flip(Int.signum)())  // コンパイルエラー

対応

以下のような関数を作ります。

func shrink<A, B>(_ f: @escaping (A) -> () -> B) -> (A) -> B {
  { a in f(a)() }
}
intArray.map(shrink(Int.signum))  // OK
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2