Search on the blog

2019年6月22日土曜日

Scala: implicit の使い方

Scala の implicit の使い所をまとめておく。

Pimp My Library

標準機能やサードパーティライブラリのクラスを拡張したいときに使う。

object ImplicitInt {
  implicit class RichInt(val x: Int) {
    def negate: Int = -x
    def square: Int = x * x
  }
}

上記のような implicit class を作っておいてimport すると、Int型の変数で squareメソッド、negate メソッドが使えるようになる。

import ImplicitInt._

object Main {
  def main(args: Array[String]): Unit = {
    // pimp my library
    val x = 100
    println(x.square)  // 10000
    println(x.negate)  // -100
  }
}

Implicit Conversion

暗黙の型変換。

case class Rational(real: Double, imag: Double) {
  def +(that: Rational) = Rational(real + that.real, imag + that.imag)
}

object Rational {
  implicit def double2Rational(x: Double): Rational = new Rational(x, 0)
}

上記のように複素数を扱うクラスを定義したとする。複素数と実数の足し算をしたい場合、implicit conversion を使うと以下のように書ける。わざわざ Double から Rational クラスを明示的につくらなくていいので便利。


object Main {
  def main(args: Array[String]): Unit = {
    val x = Rational(1.0, 1.0)
    val y = x + 2.0
    println(y)  // Rational(3.0,1.0)
  }
}

Implicit Parameter

暗黙的なパラメータ。実行コンテキストなどのパラメータを暗黙的にメソッドに渡してくれる。

import scala.concurrent.{ExecutionContext, Future}

class RemoteCall {
  def get(x: Int)(implicit ex: ExecutionContext): Future[Int] = Future {
    println("heavy remote call...")
    Thread.sleep(5000)
    x
  }
}

上記のような重い処理があって、メインスレッドとは別のスレッドで実行したいとする。 ExecutionContext を implicit で受け取れるように定義されているため、以下のように実行コンテキストを渡すことができる。

import java.util.concurrent.Executors

import scala.concurrent.{ExecutionContext, ExecutionContextExecutorService}
import scala.util.{Failure, Success}

object Main {
  def main(args: Array[String]): Unit = {
    implicit val ex: ExecutionContextExecutorService =
      ExecutionContext.fromExecutorService(Executors.newSingleThreadExecutor())

    val remoteCall = new RemoteCall
    remoteCall.get(123) onComplete {
      case Success(r) =>
        println(r)
        ex.shutdown()
      case Failure(t) => println(t.getMessage)
    }
    println("do something else")
  }
}

他にもデータベース接続をするときに、接続まわりを担当するクラスを implicit parameter で渡すなどの使い方がある。

2019年6月15日土曜日

GITADORA DM スキル 2286.19

 ネームカラーが黄色になった。スティックを買ってメトロノームにあわせて叩く練習を始めた。


最近の練習曲は以下のとおり。

  • 高校生のときに流行っていた懐メロ
  • 難易度のわりに簡単
  • 気持ち早めに叩きにいくと Perfect が出やすかった 

  • ドンタン、ドンタ、ドンドタン、ドンタンみたいなパターンが独特
  • サビ前のスネアの連打が決まると気持ちいい

  • 難易度のわりに難しい気がする
  • 最初挑戦したときはまともに叩けるようになる気がまったくしなかった
  • 16分音符のタム回しがキマると気持ちいい


2019年6月9日日曜日

Latin Honors

 著名な人の経歴を調べていると、「summa cum laude」とか「magna cum laude」とか出てくる。成績優秀者に与えられる称号という漠然とした意味は知っていたが、称号をえるための基準や称号の順位を知らなかったので調べてみた。

summa cum laude
  • 成績上位5%
  • GPA 3.8以上

magna cum laude
  • 成績上位10%
  • GPA 3.6以上

cum laude
  • 成績上位15%
  • GPA  3.4以上

上記の数字はあくまでも目安で、大学によって基準は変わるらしい。

2019年5月17日金曜日

GITADORA DM スキル 1921.83

 最近GITADORAのドラムマニアにハマっている。


どのくらいのスキルのときにどのくらいのレベルの曲を練習していたかの記録を付けていこうと思う。

  • ロードオブメジャーの懐メロ
  • サビ前のHHSHHHSHHHSHHHSHのところが右右左右...だと難しかったが、右左右左...だと叩けた。


  • アニメの主題歌らしい
  • タム回しがうまく叩けない 


  • けいおん!!の主題歌らしい
  • ロータム、フロアタム、スネアを力強くたたくところが気持ちいい


2019年1月19日土曜日

Approximation Algorithms Part I Week 2

 Week2 の講義を視聴した。Week2のテーマはナップサック問題だった。

 ナップサック問題は、動的計画法の基礎中の基礎ということで、プロコンで何度も解いているので最初の方はだいたい知っている話だった。価値が小さな整数の場合は多項式時間の動的計画法で解けるが、任意の実数の場合はどうすればよいか? Scaling、Roundingというテクニックを使うことで近似解を求めることができる。

 Roundingのテクニックは Week1 の vertex cover にも出来てたが、vertex cover の場合は LP relaxation を解いた出力を rounding するのに対して、ナップサック問題の場合は 入力値を rounding する。アイデア自体はシンプルで実数を整数に変換して動的計画で解けばOK。

 Scalingのパラメータの取り方によって、任意のε > 0 に対して|OPT - ApproximationOPT| < εとなるような近似問題を定式化できるが、実行時間は1/εに対して線形で増えていくので実用的には程よいεを見極める必要がある。このあたりの reasoning/analysis は面白かった。

 

2019年1月12日土曜日

Approximation Algorithms Part I Week 1

 Courseraで「Approximation Algorithms Part I」という講義を取り始めた。以下のようなことを教えてくれる。

  • クラスNPの組み合わせ最適化問題の近似解を多項式アルゴリズムで求める
  • 近似アルゴリズムの精度
  • 近似解が実行可能であることの考察

ちなみにコースを提供しているENS(École normale supérieure; 高等師範学校)というのはフランスの大学らしい。

 第1週は Vertex Cover を解くための Linear Programming RelaxationとRoundingについてだった。さっき課題を提出したが、記述式の問題で、生徒同士で評価しあう形式だった。数式を書かないといけないのでひさびさにlatexを使って学生に戻った気分になった。

 組み合わせ最適化問題は実世界の問題にも適用できる場面が多いので、基本を抑えてエンジニアとしての引き出しを増やしておきたい。

2018年12月23日日曜日

reason about computer programs

 以前「Functional Programming in Scala」という本を読んでいたときに「reason about」という表現が出てきた。そのときはしっくりとくる和訳を見つけられずにいた。

Because of their modularity, pure functions are easier to test, to reuse, to parallelize, to generalize, and to reason about.

The use of throw and catch means we can no longer reason about our program purely locally by substituting terms with their definitions.

 どうやら純粋関数でプログラムを書くと reason abount しやすいらしい。最近読み出した「AN INTRODUCTION TO PROGRAMMING IN GO」という本でも同じ表現が出てきた。

You'll spend a large amount of your time just trying to fix your program so that it finally compiles. But types help us reason about what our program is doing and catch a wide variety of common mistakes.

 改めて辞書を引いてみると、「〜について論理的に考える、判断する」というのが妥当な和訳っぽい。そういえば日本語でも、ものごとについて論理的に考えて推論することをリーズニングというなぁ。

 ということで、reason about program でググっていたら面白い記事を見つけた。

 reason about という表現はバズワード的に使われるが、実は重要な意味がある。リーズニングしやすいコードとは以下の特性を持っている。
  1. 意図しない副作用を持たないこと
  2. 外部の状態に依存・影響しないこと
  3. 参照透明性
上記の特性を保証するには様々な方法がある。
  1. ユニットテスト
  2.  型
  3. イミュータビリティ
ユニットテストはコードが正しく動くことを保証してくれるしドキュメントとしても利用できるが徹底的に考えないとエッジケースを取りこぼしてしまう。型・イミュータビリティはコードに制約を課すが様々なエッジケースを防いでくれる。