⚡
カリー化(Scala)のメモ
def asyncFunc()(implicit ec: ExecutionContext): Future[Unit] = {
...
}
(implict ec: ExecutionContext)
がよく分からないので、まずはカリー化から勉強してみる。
カリー化は関係なさそうだった...
カリー化
構文
合計金額 = 単価 * 個数
を計算する下記の関数について考える。
def calcTotal(price: Int, qty: Int): Int = {
price * qty
}
total:Int = calcTotal(100, 3) // -> total: 300
これをカリー化すると、↓のようになる。
def calcTotalCurried(price: Int): Int => Int = {
qty => price * qty
}
total: Int = calcTotalCurried(100)(3) // -> total: 300
-
Int => Int
の部分は、戻り値がInt型の変数を受け取り、Int型を返す関数であることを表している
calcTotalCurried()
は↓のようにも書ける。(↓の方が一般的)
def calcTotalCurried(price: Int)(qty: Int): Int = {
price * qty
}
引数が3つの場合も同様に書ける。
- notカリー化
def calcTotal(price: Int, qty: Int, taxRate: BigDecimal): Int = {
val beforeTax: BigDecimal = BigDecimal(price * qty)
(beforeTax + (beforeTax * taxRate))
.setScale(0, BigDecimal.RoundingMode.DOWN)
.toInt
}
- カリー化
def calcTotalCurried(price: Int): Int => BigDecimal => Int = {
qty => {
taxRate => {
val beforeTax: BigDecimal = BigDecimal(price * qty)
(beforeTax + (beforeTax * taxRate))
.setScale(0, BigDecimal.RoundingMode.DOWN)
.toInt
}
}
}
def calcTotalCurried(price: Int)(qty: Int)(taxRate: BigDecimal): Int = {
val beforeTax: BigDecimal = BigDecimal(price * qty)
(beforeTax + (beforeTax * taxRate))
.setScale(0, BigDecimal.RoundingMode.DOWN)
.toInt
}
部分適用
いくつかの引数を設定した関数を事前に受け取り、残りの引数を後から受け取る関数を作成すること。
具体的には↓のようなもの。
// カリー化された関数
def calcTotal(price: Int)(qty: Int): Int = price * qty
// 単価を部分適用
// 食べ物はどれでも450円、飲み物はどれでも250円
val calcTotalFood = calcTotal(450) _
val calcTotalDrink = calcTotal(250) _
// それぞれのテーブルについて、食べ物、飲み物の数に応じた料金を計算
val priceTableA: Int = calcTotalFood(3) + calcTotalDrink(5)
val priceTableB: Int = calcTotalFood(2) + calcTotalDrink(2)
メリット
- 呼び出し方がシンプルで分かりやすくなる
- ↓に比べてカリー化、部分適用を使ったほうがシンプル
- 多分実際は部分適用した関数をimportするだろうから↑はよりシンプルになるはず
- ↓に比べてカリー化、部分適用を使ったほうがシンプル
def calcTotal(price: Int, qty: Int): Int = price * qty
val foodPrice: Int = 450
val drinkPrice: Int = 250
val priceTableA: Int = calcTotal(foodPrice, 3) + calcTotal(drinkPrice, 5)
val priceTableB: Int = calcTotal(foodPrice, 2) + calcTotal(drinkPrice, 2)
Discussion