Skip to content

Instantly share code, notes, and snippets.

@lyricallogical
Last active December 13, 2015 16:49
Show Gist options
  • Save lyricallogical/4943588 to your computer and use it in GitHub Desktop.
Save lyricallogical/4943588 to your computer and use it in GitHub Desktop.
rpscala97

!SLIDE PartialFunction ってなあに?

部分関数のことだよ

!SLIDE 部分関数ってなあに?

そもそも関数ってなあに?

!SLIDE 関数ってなあに?

一般にプログラミングでいう関数は全域関数(total function)のことだよ

!SLIDE 全域関数ってなあに?

値を渡したら必ず値を返してくれる関数のことだよ

!SLIDE 全域関数と部分関数はなにが違うの?

部分関数は全域関数と違って、値を渡しても値を返してくれないことがあるよ

!SLIDE 例えば?

  • 例外を投げる関数
  • 停止しない関数
  • 失敗する関数
  • 一部しか処理する気のない関数

!SLIDE 例:例外を投げる関数

数学的には部分関数だけど Scala の PartialFunction ではないよ

!SLIDE 例:停止しない関数

これも数学的には部分関数だけど Scala の PartialFunction ではないよ

!SLIDE 例:失敗する関数

例えば A => Option[B] のようなもの

unlift メソッドとか見てわかって

これは Scala がリテラルから生成する PartialFunction に一番近いよ (注:言語仕様的には PartialFunction のためのリテラルなんてないです)

!SLIDE Scala がリテラルから生成する PartialFunction って?

collect メソッドに渡してる部分がそうだよ

val oddStrings = (1 to 10).collect {
  case x if x % 2 == 1 => x.toString
}

!SLIDE 近いって、同じじゃないの?

A => Option[B] と collect に渡されたものは、ちょっと違うよ

!SLIDE どこが?

その前に Scala における PartialFunction と Function1 の違いをちゃんと知ろう

abstarct class PartialFunction[-A, +B] extends (A => B) {
  def isDefinedAt(x: A): Boolean
}

極論すると、これだけだよ

!SLIDE isDefinedAt メソッド

関数(Function1)が引数値を処理できるかどうかを知るためのメソッドだよ。

!SLIDE 結局何が違うの?

A => Option[B] の場合は、実際に関数を評価しないといけないよ

A => Option[Lazy[B]] とか A => LazyOption[B] とかなら…

!SLIDE collect に渡してたのはどうなの?

Scala コンパイラがうまいこと定義してくれるから、パターン部しか評価されないよ

val oddStrings = (1 to 10).collect {
  case x if x % 2 == 1 => x.toString
}

x.toString は評価されないよ

!SLIDE 何が嬉しいの?

値を処理できるかどうか「だけ」を知りたいときに、計算を保留してもらえるよ

!SLIDE 例:一部しか処理する気のない関数

Akka の Actor とかがそうだよ

// 簡略化してます、実際はもっと色々定義してあります
trait Actor {
  def receive: PartialFunction[Any, Unit]
}

!SLIDE Actor ってなあに?

こんな風に使うよ

class GreetingActor extends Actor with ActorLogging {
  def receive = {
    case Greeting(who)  log.info("Hello " + who)
  }
}

GreetingActor は処理できるメッセージ(Greeting)だけを処理するよ

所謂メッセージ指向だよ、分散処理とか得意だよ

!SLIDE 結局 PartialFunction は何が嬉しいの?

じゃあ聞くけど Function は何が嬉しいの?

!SLIDE えっそれは関数型プログラミングが…

関数型プログラミングなんて JavaN(N < 8)でもできるよね?

e.g. Functional Java

でもリテラルがないと書くのも読むのも冗長になっちゃう

!SLIDE 関数型プログラミング言語判断基準

出自忘れた

  • 関数が first-class value であること
  • 関数を記述するリテラルがあること

二番目が重要!

!SLIDE 関数型プログラミングは何が嬉しいの

いわせんなよ恥ずかしい or それを記述するには以下略

!SLIDE 部分関数型プログラミング言語判断基準

言葉も判断基準も今ボクが考えた(!)

  • 部分関数が first-class value であること
  • 部分関数を記述するリテラルがあること

!SLIDE 部分関数を言語としてサポートする利点

関数を言語としてサポートする利点と同じだよ

そのパラダイムでのプログラミングの記述性、可読性が向上する!

!SLIDE 部分関数型プログラミングは何が嬉しいの

メッセージ指向、イベント駆動型のプログラミングの実装に向いてるよ(Akka とか)

普通の関数より小さい計算を合成して大きい関数を作れるよ

!SLIDE 小さい計算?

compose メソッドを使ったことは?

flatMap メソッドを使ったことは?

型よりもっと細かい単位でそれらのメソッドを使いたいと思ったことは?

!SLIDE 時間切れ

残念(口頭でカバーしたい)

!SLIDE まとめ

  • PartialFunction は便利だよ
  • ある領域の問題を解決する時は特に便利だよ
  • 言語サポートがあると記述性、可読性が向上するので嬉しいね

!SLIDE 以後のページは発表時にはなかった追記になります

!SLIDE 小さい計算

動的型付き言語で、大きすぎる関数を分割するとき、型と値、どちらを意識しますか?

値について意識しながら分割することもあるのではないでしょうか

!SLIDE 型レベルよりも小さい値レベルの計算

  • 通常の関数では型のレベルでしか計算を分割できない
    • 嘘。正確には勿論できるけれど、その事実は型に現れてこない
  • 部分関数なら、型より小さいレベル、値レベルで計算を分割できる

!SLIDE 比較的具象的な例

  • これ とかで雰囲気伝わらないかなあ
  • 部分関数なら分岐処理も含めて合成できるので、余計な分岐を書かずにすむ
  • 通常の関数だと分岐処理は書かざるを得ない
  • 実は open recursion で部分関数の合成相当の処理は実現できるけれど、ここまで綺麗にはできない
  • 合成、合成といっていますが、PartialFunction#orElse は horizontal な合成です
  • 一方 Function1#compose は vertical な合成です !SLIDE 追記おわり

網羅性には気をつけてね!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment