LoginSignup
226

More than 5 years have passed since last update.

Swiftの関数の引数は、常に一つ

Last updated at Posted at 2014-07-29

だとしたら、Swiftではカリー化は不要ということになってしまう。

すなわち、ざっくり言うとカリー化とは複数の引数を1つに減らすことを指します - Swiftで関数のカリー化(currying)入門

Swiftの関数は、つねに一つの値を受け取り、一つの値を返すのだから。

以下のコードを動かしてみれば、それがわかる。

func call<A,R>(f:A->R, a:A)->R {
    return f(a)
}
func id(i:Int)->Int { 
    return i
}
func add(x:Int, y:Int)->Int {
   return x + y
}
call(id, 42)       // 42
call(add, (21,21)) // 42

上記のcall()は、「『型Aの値を一つだけ取って型Rの値を返す関数』と『型Aの値』を取って『型Rの値』を返す関数」なはずなのに、「IntIntを取ってIntを返す」関数も受け取っている。

なぜか?

IntIntを取ってIntを返す」関数なんて、はじめからどこにもなかったからだ。

あったのは、

(Int, Int)を受け取ってIntを返す関数」

だったのだ。

全てのSwiftの関数は、tupleを一つだけ受け取る関数なのである。

Haskellの言葉で言えば、上記のadd()

add:: Integer -> Integer -> Integer

ではなく

add::  (Integer, Integer) -> Integer

ということになる。

add()の本当の姿は、

func add(arg:(Int,Int))->Int {
   let (x, y) = arg
   return x + y
}

だったわけだ。

ちなみに(Int, Int)は、Intとは独立した固有の型である。そしてInt(Int)でもある。ので要素数ゼロのtupleである()を除く全ての値は、必ず.0というプロパティが存在する。

let n = 0
n // 0
n.0 // 0
n.0.0 // 0
n.0.0.0 // 0
// ちなみに0.0.0... は syntax error
// さもないと 0.0がDouble(0.0)なのか(0).0なのか判別不能になる

さらに

func hello(){ println("hi") }

は、()を受け取って()を返す関数であり、

call(hello, ())

は期待通り動く。

The Swift Programming Languageには

Tuples are particularly useful as the return values of functions

なんてのんきに書いてあるが、便利どころかSwiftでは全ての値がtupleなのだ。通常の値は要素数1のtupleで、「値がない値」すら、要素数0のtuple。

このことを知らなくても、普通の関数やclassやstructやenumは書けるのけど、上記のようにジェネリクスを使う場合、このことは必須の知識となる。

大事なことなのにアマツバメ本にきちんと明記していないので、記事にした次第。

(Dan, Swift, Newbie)

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
226