なんでこんなことを思ったか
ちょっとHaskellをみていて、関数合成ということばが出てきて、そういえばScalaにも関数合成(composeとかandThen)あったよなぁと思い出した。
それで、いざ使ってみようと思ったら「関数とは?」とふと思ってしまった。
以下、あんまりまとまってないので、そのうち書きなおすかも。
ネット上の意見
その1
What is the difference between a method and a function
Objectに関連するものがメソッド、そうでなく独立しているものが関数である。
ふむ?
その2
Scala def versus val
valがfunction、defがmethodである?
ふむむ?
その3
関数にしか見えないものが「メソッド」と新たな名前で呼ばれる理由(1)
override可能なものがmethodで、不可能なものがfunction
ということはdefがmethodで、valがfunction?
以下の通りであるということか?
メソッド(def)
override 可能
/**
* 文字列をInt型の逆リストに変換
* */
private def toReverseIntList(s: String): List[Int] = {
s.sliding(1).map(_.toInt).toList.reverse
}
関数(val)
override 不可能
private val toReverseIntList = (s: String) => {
s.sliding(1).map(_.toInt).toList.reverse
}
考える
その1が曖昧。
Objectに関連するものはdefでもvalでもメソッドになるというのか?
おそらく答え
※英語は読むのに根気がいるのでまだ読めていない
Difference between method and function in Scala
methodを定義すべきか、functionを定義すべきか
はてさて・・・
defでも、valでも関数合成は可能なんだなぁ
関数合成
def バージョン
/**
* Created by FScoward on 15/01/18.
*/
object Luhn {
/**
* Luhn algorithm
* */
def isValid(s: String): Boolean = {
// val list = doubleOddValues(toReverseIntList(s))
// sum(list) % 10 == 0
// ↑はいつもの使い方
(sum _ compose doubleOddValues _ compose toReverseIntList _)(s) % 10 == 0
}
/**
* 偶数桁の値を倍にして返す
* */
private def doubleOddValues(list: List[Int]): List[Int] = {
(0 until list.size).map(i => {
if (i % 2 == 0) {
list(i)
} else {
list(i) * 2
}
}).toList
}
/**
* 文字列をInt型の逆リストに変換
* */
private def toReverseIntList(s: String): List[Int] = {
s.sliding(1).map(_.toInt).toList.reverse
}
/**
* リストの値を合計する
* 但し、2桁以上の数字は分割して加算する
* */
private def sum(list: List[Int]) = {
list.map(i => {
i match {
case i if i > 9 => {
i.toString.sliding(1).map(_.toInt).sum
}
case i => {
i
}
}
}).toList.sum
}
}
val バージョン
object Luhn {
/**
* Luhn algorithm
* */
def isValid(s: String): Boolean = {
(sum compose doubleOddValues compose toReverseIntList)(s) % 10 == 0
}
/**
* 偶数桁の値を倍にして返す
* */
private val doubleOddValues = (list: List[Int]) => {
(0 until list.size).map(i => {
if (i % 2 == 0) {
list(i)
} else {
list(i) * 2
}
}).toList
}
/**
* 文字列をInt型の逆リストに変換
* */
private val toReverseIntList = (s: String) => {
s.sliding(1).map(_.toInt).toList.reverse
}
/**
* リストの値を合計する
* 但し、2桁以上の数字は分割して加算する
* */
private val sum = (list: List[Int]) => {
list.map(i => {
i match {
case i if i > 9 => {
i.toString.sliding(1).map(_.toInt).sum
}
case i => {
i
}
}
}).toList.sum
}
}
なお、sumだけval sum = (list: List[Int]) =>
の形で書けばあとはdefで書いても関数合成できる。
違い
def バージョン だと_
で関数オブジェクト化する必要がある。
つまり
def は関数ではない?
よくわからない
言語に詳しい諸兄方のご意見ください。