Gigahorse 0.2.0

in

Gigahorse 0.2.0 をリリースした。新機能は 2つのバックエンドを選べるようになったことだ。
@alexdupre さんが AHC 1.9 から Netty 4 ベースの AHC 2.0 への移行をコントリビュートしてくれた。#12

さらに、#15 で僕が実験的な Akka HTTP サポートを追加した。

詳しくは Gigahorse ドキュメントを参照してほしい。

Scala 2.12.0 リリースノート

in

昨日リリースされたばかりの Scala 2.12.0 のリリースノートを翻訳しました。
Lightbend 社 Scala チームのコンパイラ魂を感じ取れる、マニアな内容になっています。

Scala 2.12.0 がリリースされました!

Scala 2.12 コンパイラは Java 8 から使えるようになった新しい VM 機能を利用するために、完全なオーバーホールが行われた。

gigahorse-github 0.1.0

gigahorse-github 0.1.0 をリリースした。これは、Github API v3 のための Gigahorse プラグインだ。

レポジトリ情報を取得する使用例はこんな感じだ:

scala> import gigahorse._, gigahorse.github.Github, scala.concurrent._, duration._
 
scala> val client = Github.localConfigClient
client: gigahorse.github.LocalConfigClient = LocalConfigClient(OAuthClient(****, List(StringMediaType(application/json), GithubMediaType(Some(v3),None,Some(json)))))
 
scala> Gigahorse.withHttp { http =>
         val f = http.run(client(Github.repo("eed3si9n", "gigahorse-github")), Github.asRepo)
         Await.result(f, 2.minutes)
       }
res0: gigahorse.github.response.Repo = Repo(https://api.github.com/repos/eed3si9n/gigahorse-github, gigahorse-github, 64614221, User(https://api.github.com/users/eed3si9n, eed3si9n, 184683, Some(https://github.com/eed3si9n), Some(https://avatars.githubusercontent.com/u/184683?v=3), Some(), Some(User), Some(true), None, None), eed3si9n/gigahorse-github, Some(Gigahorse plugin for Github API v3),...

gigahorse-github 本体に興味がある人は、README にドキュメンテーションがあるのでそちらを参照してほしい。

Gigahorse を拡張する

Gigahorse プラグインの書き方を解説したGigahorse を拡張するというページも書いた。
Dispatch プラグインの書き方とだいたい同じになっている。そこで書いたように、JSON データバインディングをスキーマから自動生成するという方法をとっている。

そのため、僕にとって gigahorse-github は Gigahorse の概念実証であると同じかそれ以上に sbt-datatype の概念実証であるという意味合いがある。やはりというか、全コンポーネントで細かいバグが出てきたので有益な演習だったといえる。

Gigahorse 0.1.0

更新: Gigahorse 0.1.1 を使ってください。

Gigahorse 0.1.0 をリリースした。これは Scala のための HTTP クライアントで、内部にAsync Http Client を使っている。詳しくは Gigahorse ドキュメントを書いたので、それを参照してほしい。ライブラリがどういう感じなのかを例でみるとこんな感じだ。

scala> import gigahorse._
scala> import scala.concurrent._, duration._
scala> Gigahorse.withHttp(Gigahorse.config) { http =>
         val r = Gigahorse.url("http://api.duckduckgo.com").get.
           addQueryString(
             "q" -> "1 + 1",
             "format" -> "json"
           )
         val f = http.run(r, Gigahorse.asString andThen {_.take(60)})
         Await.result(f, 120.seconds)
       }

registry and reference パターン

ここ最近考えている「パターン」があって、オブジェクトを永続化/シリアライゼーションするみたいな状況で出てくる。

問題提起として、以下のような case class を考えてみてほしい:

scala> case class User(name: String, parents: List[User])
defined class User
 
scala> val alice = User("Alice", Nil)
alice: User = User(Alice,List())
 
scala> val bob = User("Bob", alice :: Nil)
bob: User = User(Bob,List(User(Alice,List())))
 
scala> val charles = User("Charles", bob :: Nil)
charles: User = User(Charles,List(User(Bob,List(User(Alice,List())))))
 
scala> val users = List(alice, bob, charles)
users: List[User] = List(User(Alice,List()), User(Bob,List(User(Alice,List()))),
  User(Charles,List(User(Bob,List(User(Alice,List()))))))

注目してほしいのは parents という他のユーザを参照するリストを保持してることだ。
次に、users リストを JSON に変換したいとする。

[{ "name": "Alice", "parents": [] },
{ "name": "Bob",
  "parents": [{ "name": "Alice", "parents": [] }] },
{ "name": "Charles",
  "parents": [{ "name": "Bob", "parents": [{ "name": "Alice", "parents": [] }] }] }]

sjson-new とアズカバンの囚人

in

本稿は sjson-new に関する第3部だ。パート1パート2も是非読んでみてほしい。

sbt のコード内にはデータ永続化が数百メガバイトのオーダーに達している部分がいくつかあって、特にマシンに SSD が積まれていない場合は性能ボトルネックになる疑いがあるんじゃないかと思っている。
当然、最初に飛びついたのは Google Protocol Buffers のエンコーディングを参考に独自のバイナリフォーマットを実装することだった。

sbt-jmh を用いたマイクロベンチマーク

僕がまずやるべきだったのは、ベンチマークを取ることだ。@ktosopl (Konrad Malawski)君の sbt-jmh を使うとマイクロベンチマークは簡単に作ることができる。ビルドにプラグインを入れて、JmhPlugin を有効化したサブプロジェクトを定義するだけだ。

sjson-new と LList を用いたカスタムコーデック

in

2ヶ月ぐらい前に sjson-new について書いた。週末にまたちょっといじってみたので、ここに報告する。
前回は Scala エコシステムにおける JSON ライブラリの家系をたどって、複数バックエンドに対応し、かつ型クラスベースの JSON コーデックライブラリという概念を導入した。課題は、カスタムコーデックを簡単に定義できるようにする必要があるということだった。

私家版 shapeless

4月に書いたのと先週までの間に flatMap(Oslo) 2016Scala Days New York 2016 という 2つのカンファレンスがあった。残念ながら、僕は flatMap の方には行けなかったけども、Daniel Spiewak さんの "Roll Your Own Shapeless" (「私家版 Shapeless のすゝめ」) というトークを New York で聞けた。flatMap 版の方が完全版でそれは vimeo にも出てるので、是非チェックしてみてほしい。

sbt の内部では、sbinary を用いたキャッシングに HList が用いられてたりする:

implicit def mavenCacheToHL = (m: MavenCache) => m.name :*: m.rootFile.getAbsolutePath :*: HNil
implicit def mavenRToHL = (m: MavenRepository) => m.name :*: m.root :*: HNil
...

そういう影響もあって、HList とか Shapeless の LabelledGeneric みたいなのがあれば JSON object を表す中間値としていいのではないかと思っていたので、Daniel のトークには最後に背中を押してもらった気がする。

本稿では、HList の目的を特化した LList というものを紹介する。

LList

sjson-new には LList というデータ型があって、これは labelled heterogeneous list、ラベル付された多型リストだ。
標準ライブラリについてくる List[A] は、A という同じ型しか格納することができない。標準の List[A] と違って、LList はセルごとに異なる型の値を格納でき、またラベルも格納することができる。このため、LList はそれぞれ独自の型を持つ。REPL で見てみよう:

scala> import sjsonnew._, LList.:*:
import sjsonnew._
import LList.$colon$plus$colon
 
scala> import BasicJsonProtocol._
import BasicJsonProtocol._
 
scala> val x = ("name", "A") :*: ("value", 1) :*: LNil
x: sjsonnew.LList.:*:[String,sjsonnew.LList.:*:[Int,sjsonnew.LNil]] = (name, A) :*: (value, 1) :*: LNil
 
scala> val y: String :*: Int :*: LNil = x
y: sjsonnew.LList.:*:[String,sjsonnew.LList.:*:[Int,sjsonnew.LNil]] = (name, A) :*: (value, 1) :*: LNil

x の長い型の名前の中に StringInt が書かれているのが分かるだろうか。y の例が示すように、String :*: Int :*: LNil は同じ型の略記法だ。

BasicJsonProtocol は全ての LList の値を JSON オブジェクトに変換することができる。

foundweekends

週末に趣味プログラミングをする人のための Github organization として foundweekends を作った。参加したい人は twitterGitter で声をかけてください。

当面の活動は @n8han から conscriptgiter8pamflet を引き継ぐことだ。

sjson-new

in

Scala プログラマの週末の嗜みとして、僕も一つ sjson-new という JSON ライブラリを書いてみた。
sjson-new は型クラスベースの JSON コーデックライブラリで、Jawn のための wit だ。つまり、複数のバックエンドに対して sjson的なコーデックを提供することを目指している。

コードは spray-json を元にしているが、データの扱いに関しての考え方は Scala Pickling の方に近い。Pickling と違って、sjson-new-core はマクロとか普通のパターンマッチング以外での実行時リフレクションなどは一切使っていない。

Json4s-AST と使う場合:

libraryDependencies += "com.eed3si9n" %%  "sjson-new-json4s" % "0.1.0"

Spray と使う場合:

libraryDependencies += "com.eed3si9n" %%  "sjson-new-spray" % "0.1.0"

sbt server リブート

in

これは先日書いた sbt 1.0 ロードマップの続編だ。この記事では sbt server の新しい実装を紹介する。感想やコメントがあれば sbt-dev mailing list にお願いします。

sbt server の動機は IDE との統合の改善だ。

ビルドは、巨大で、可変で、共有された、状態のデバイスだ。ディスクのことだよ! ビルドはディスク上で動作するのもであって、ディスクから逃れることはできない。

-- Josh Suereth、The road to sbt 1.0 is paved with server より

マシンに積んであるディスクは根本的にステートフルなものであり、sbt がタスクを並行実行できるのもそれが作用に関する完全なコントロールを持っていることが大前提になっている。同じビルドに対して sbt と IDE を同時に実行していたり、複数の sbt インスタンスを実行している場合は、sbt はビルドの状態に関して一切保証することができない。

sbt server というコンセプトは元々 2013年に提案された。同時期にその考えの実装として sbt-remote-control プロジェクトも始まった。ある時点で sbt 0.13 が安定化して、代わりに Activator が sbt-remote-control を牽引する役目になり、sbt 本体を変えない、JavaScript をクライアントとしてサポートするなどという追加の制約を課せられることになった。

sbt 1.0 を念頭に置いて、僕は sbt server の取り組みをリブートすることにした。sbt の外で何かを作るのではなくて、僕はアンダーエンジニアリングすることを目指している。つまり「オーバーエンジニアリング」の逆で、自動ディスカバリーや自動シリアライゼーションといった僕から見て本質的じゃない既存の前提を一度捨てようと思っている。代わりに、気楽に sbt/sbt コードベースに取り込めるような小さいものがほしい。Lightbend 社は Engineering Meeting といってエンジニア全員が日常から離れた所に集結して議論をしたり、内部でのハッカソン的なことをやる合宿みたいなことを年に数回やっている。2月に美しいブダペストで行われたハッカソンでは sbt server リブートという提案に Johan Andrén (@apnylle)、 Toni Cunei、 Martin Duhem の 3人が乗ってくれた。目標として設置したのは、IntelliJ IDEA に sbt のビルドを実行させるボタンを付けることだ。

Syndicate content