LoginSignup
6
5

More than 5 years have passed since last update.

Scala における method と 関数(function) の違いとは? - 関数合成

Last updated at Posted at 2015-01-19

なんでこんなことを思ったか

ちょっと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 は関数ではない?

よくわからない

言語に詳しい諸兄方のご意見ください。

6
5
1

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
6
5