Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional Programming

Yuuki Sumida
December 11, 2014

Functional Programming

合同勉強会 in 大都会岡山 -2014 Winter-
https://manage.doorkeeper.jp/groups/gbdaitokai/events/15289

Yuuki Sumida

December 11, 2014
Tweet

More Decks by Yuuki Sumida

Other Decks in Technology

Transcript

  1. 手続きスタイルでのプログラミング int age = Integer.MAX; for (Employee employee: employees) {

    if (employee.getGender() == Gender.Male) { // 1 if (employee.getAge() < age) { // 2 age = employee.getAge(); // 3 } // 2 } // 1 }
  2. コレクションの高階関数 val age = employees .filter(_.gender == Male) // 1

    .map(_.age) // 2 .fold((x, y) => if (x < y) x else y) // 3
  3. STRINGの値は一体どこでおかしくなって しまったのか? public class A { String s = ...;

    public void foo() { // sの操作 } public void bar() { // sの操作 } } A a = new A(); a.foo(); a.bar();
  4. 変更1:クラスの状態をなくす public class A { public static String foo(String s)

    { // 新しい文字列を返す } public static String bar(String s) { // 新しい文字列を返す } } String s1 = ...; String s2 = A.foo(s1); String s3 = A.foo(s2);
  5. 変更2:クラスを不変な値クラスにする public class A { String s = ...; public

    A foo() { // 新しいAのインスタンスを作って返す } public A bar() { // 新しいAのインスタンスを作って返す } } A a1 = new A(); A a2 = a1.foo(); A a3 = a2.foo();
  6. 注意:可変なデータ構造は伝搬する public class A { List<String> list = ...; public

    A foo() { // 新しいAのインスタンス内のリストも新しく作る必要がある } public A bar() { // 新しいAのインスタンス内のリストも新しく作る必要がある } } A a1 = new A(); A a2 = a1.foo(); A a3 = a2.foo();
  7. 宣言的なプログラミング 「どのように値を返すか」ではなく、「どのような値を返 すか」を記述するプログラミング int age = Integer.MAX; for (Employee employee:

    employees) { if (employee.getGender() == Gender.Male) { if (employee.getAge() < age) { age = employee.getAge(); } } } val age = employees .filter(_.gender == Male) .map(_.age) .min
  8. パターンマッチ enum Gunpla {HG, MG, PG, RG, RE_100} Gumpla g

    = Gunpla.RE_100; switch (g) { case HG: case MG: // foo break; default: // bar } if (g == Gunpla.HG) { // foo } else if (g == Gunpla.MG) { // bar } else { // baz }
  9. パターンマッチ abstract sealed class Gunpla case object HG extends Gunpla

    case object MG extends Gunpla case object PG extends Gunpla case object RG extends Gunpla case object RE_100 extends Gunpla val hg: Gunpla = HG hg match { case HG => "HG" case MG => "MG" } <console>:12: warning: match is not exhaustive!
  10. パターンマッチ case class Person(name: String, age: Int) val john =

    Person("John Doe", 31) john match { case Person(name, age) if age < 20 => name + "さんは子供です" case Person(name, _) => name + "さんは大人です" }
  11. カリー化と部分適用 f: (X × Y) -> Z g: X ->

    (Y -> Z) def f1(x: Int, y: Int) = x + y def f2(x: Int)(y: Int) = x + y val g = f2(1)_ g: Int => Int = <function1> // g(y: Int) = 1 + y
  12. 遅延評価 val a = ... lazy val b = ...

    lazy val c = ... val d = ... // 条件によってbまたはcを使う
  13. 遅延評価による無限リスト def iterate[T](f:T => T, x:T):Stream[T] = Stream.cons(x, iterate(f, f(x)))

    iterate((x:Int) => x + 1, 1) // 1から開始で、+1ずつされていく無限リスト .take(10) // 10要素取得 .toList // リスト化(この時点で初めて評価されてリストになる) // List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) val codename = List("Playground", "Kestrel", "Merlin", "Tiger", "Mustang", "Dolphin") iterate((x:Int) => x + 1, 1) .zip(codename) .toList // List[(Int, String)] = // List((1,Playground), (2,Kestrel), (3,Merlin), // (4,Tiger), (5,Mustang), (6,Dolphin))
  14. 再帰と末尾再帰最適化 def iterate[T](f:T => T, x:T):Stream[T] = Stream.cons(x, iterate(f, f(x)))

    iterate((x:Int) => x + 1, 1) // 1から開始で、+1ずつされていく無限リスト .take(10) // 10要素取得 .toList // リスト化(この時点で初めて評価されてリストになる) // List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)