型駆動開発の裏側 -IdrisのIDEモードを試してみる-

以前紹介したように、AtomにIdris用パッケージをインストールするとキーボードショートカットで様々な機能を利用できます。

takezoe.hatenablog.com

これがどのように実装されているのかが気になったので調べてみようと思い、Atomパッケージのソースコードを眺めてみました。

github.com

どうやらIdrisにはIDEモードというモードがあり、標準入出力を使用してS式でやり取りを行うIDE向けのプロトコルが存在するようです。ちょっと試してみました。

まずはIDEモードでプロセスを起動。

$ idris --ide-mode
000018(:protocol-version 1 0)

入出力は「メッセージの文字数を6桁の16進数にエンコードしたもの+S式のメッセージ」という形式で行われるようです。

こんな感じの作りかけのファイルを用意しておきます。

module Main

main : IO ()

このファイルを読み込みます。メッセージにはユニークなカウンタを含める必要があるようです。

000022((:load-file "/tmp/hello.idr") 1)

出力はこんな感じ。

0000a9(:output (:ok (:highlight-source ((((:filename "/tmp/hello.idr") (:start 1 8) (:end 1 12)) ((:namespace "Main") (:decor :module) (:source-file "/tmp/hello.idr")))))) 1)
00001e(:set-prompt "*/tmp/hello" 1)
000015(:return (:ok ()) 1)

CTRL+ALT+A相当の:add-clauseというメッセージを送信してみます。

00001B((:add-clause 3 "main") 2)

こんな感じで生成されたコードが返ってきます。

000025(:return (:ok "main = ?main_rhs") 2)

シンプルな手法ではありますが、Idris側でこのような機能を持っているので様々なエディタで同じ機能を簡単に実装できるようです。実際Atom以外にもvimEmacsSublime Text用のプラグインなども用意されています。ショートカットは異なりますが、使い慣れたエディタを使用して型駆動開発を行うことができますね。

GitBucketがScala関西Summit 2017のスポンサーになりました

f:id:takezoe:20170625015539p:plain

GitBucketがScala関西Summit 2017のブロンズスポンサーになりました!Webサイトにロゴを掲載していただいています。リンク先がGitHubのREADMEというのも寂しいので、この日のためにランディングページも用意しました!!*1

summit.scala-kansai.org

ボランタリベースのオープンソースプロジェクトで捻出できる範囲なので微力ではありますが*2、国内でのScalaの普及に少しでも貢献できればと思います。ブロンズスポンサーでもノベルティを配布できるそうなので、GitBucketステッカーを配布させていただこうと思っています。

個人でCFPも出しているので、もし採択いただけたら今年も関西に参戦しようと思います。また、水面下で進めているプロジェクトがあり*3、ちょうど時期的にScala関西Summitの頃にScalaユーザの皆さんに素晴らしいニュースをお届けできるかもしれません。こちらもご期待いただければと思います!

*1:昨年ScalaMatsuriのスポンサーした時に作ったリクルーティングページを改造したものですがw

*2:とはいえ個人レベルでもサポートできるプランが用意されているのは嬉しいところです。

*3:私はほとんどタッチしていないので「進めていただいている」が正しいのですが…。

Akka Streams用のElasticsearchコネクタを作ってみた

github.com

元々はAlpakkaにプルリクしていたのですが、取り込んでもらうのに時間がかかりそう or 取り込んでもらえるかわからない感じなので自分で使う用に別リポジトリで単独のライブラリとして公開しました。Maven Centralにもpublishしてあります。

Elasticsearchからスクロールスキャンでデータの読み込みを行うSourceと、バルクでデータの投入を行うSink(Flowもあります)を提供しています。使い方は以下のような感じです。ElasticsearchのRestClientをimplicit valで定義しておく必要があります。

implicit val client = RestClient.builder(
  new HttpHost("localhost", 9201)).build()

val f1 = ElasticsearchSource(
  "source",
  "book",
  """{"match_all": {}}""",
  ElasticsearchSourceSettings(5)
)
.map { message: OutgoingMessage[JsObject] =>
  IncomingMessage(Some(message.id), message.source)
}
.runWith(
  ElasticsearchSink(
    "sink1",
    "book",
    ElasticsearchSinkSettings(5)
  )
)

SourceはOutgoingMessage[JsObject]で出力し、SinkはIncomingMessage[JsObject]でデータを受け取ります。JSONライブラリとしてはspray-jsonを使っています(Java向けのAPIも提供しており、そちらではJacksonを使っています)。

spray-jsonのFormatを定義することで、JsObjectではなくケースクラスなどでデータを扱うこともできます。

case class Book(title: String)
implicit val format = jsonFormat1(Book)

val f1 = ElasticsearchSource
  .typed[Book](
    "source",
    "book",
    """{"match_all": {}}""",
    ElasticsearchSourceSettings(5)
  )
  .map { message: OutgoingMessage[Book] =>
    IncomingMessage(Some(message.id), message.source)
  }
  .runWith(
    ElasticsearchSink.typed[Book](
      "sink2",
      "book",
      ElasticsearchSinkSettings(5)
    )
  )

Sourceはスクロールスキャンで読み込んだドキュメントをバッファリングしており下流からpullされた分だけpushし、バッファが空になるとElasticsearchから次のページの分を取得するという動きになっています。Sinkもバッファを持っており、バッファに溜まった分をElasticsearchにバルクリクエストでインデキシングするという感じになっています。Sink側の挙動に関しては改善の余地があるかなと思っています。

第十九回 #渋谷java を開催しました

6月17日(土)に弊社オフィスで第十九回 #渋谷javaを開催しました。当日の様子や皆さんの発表内容については以下のtogetterまとめをご覧ください。

togetter.com

今回は以下の皆さんに発表していただきました。

  • セッション枠
    • hagino_takahiro 「PredictionIO」
    • shimamoto 「LocalStack -クラウドサービスのモック環境-」
    • lagénorhynque 「MP in Clojure
  • 通常枠(10分)
    • Naoki Takezoe 「最強のAltJava言語Xtend」
    • Ikuru K 「ClojureのWeb開発の歴史」
    • vertical_blank 「GraalVMの話」

発表資料は公開され次第追加していきます。

www.slideshare.net

www.slideshare.net

www.slideshare.net

slides.com

ClojureやGraalVMなど相変わらず濃い話が多く、個人的には楽しいLTばかりだったのですが、Javaの最近の動向が知りたかったのに期待していたのと違う…と感じる方や、逆にテーマが散漫なので参加しづらい…という部分もあるかもしれないと感じています。より有意義な勉強会となるよう今後の運営方法についても検討していきたいと思います。

AtomのGit / GitHub連携機能を試してみた

Atom 1.18がリリースされ、以前アナウンスされていたGit / GitHub連携機能が標準で使えるようになったので試してみました。

blog.atom.io

「Packages」メニューの「GitHub」サブメニューからエディタの右側にGit / GitHubタブを表示できます。キーボードショートカットでは^ + (でGitタブ、^ + *GitHubタブをトグルすることができます。

Gitタブでは変更したファイルの差分を確認したり、ステージ、コミットが可能です。また、画面下のステータスバーからブランチの作成・切り替え、プッシュ、プル、フェッチを行うことができます。あとログを見たりマージやリベース操作ができれば最低限必要な日常操作はできそう。

f:id:takezoe:20170619115537p:plain

GitHubタブはアクセストークンを登録する必要があります。今のところはoriginに現在のブランチに対応するプルリクエストがあるとその内容を表示することしかできないようです。差分も見たり何か操作ができるわけでもありませんし、プルリクエストに変更があっても反映されないようです。タブにもpreviewと書いてありますが、まだほとんど何もできないに等しいです。

f:id:takezoe:20170619115805p:plain

Git連携に関しては基本的な操作は可能なものの日常的に利用するにはもう一息、GitHub連携に関してはまだまだこれからといったところでしょうか。git-plusやgit-controlなどのパッケージもありますが、正直どちらもあまり使いやすいとは言えませんので、Atom標準のGit連携機能が強化されることを期待したいところです。

Idris + Atomによる型駆動開発入門

4月から社内でType-Driven Development with Idrisの読書会をやっています。

takezoe.hatenablog.com

最近ようやくChapter 3まで進み、実際に自分でコードを書くエクササイズなども出てきました。この本ではAtomを使うことが推奨されているのですが、Atom用のIdrisパッケージが非常に強力で、型駆動開発の魅力を存分に感じることができます。そこで、今回は実際にAtomでのIdrisプログラミングがどのようなものかについて紹介したいと思います。

github.com

たとえば以下のようなシグネチャを持つVect(要素数を型情報に持つリスト)用のマップ関数を実装するとします。Vect n aの各要素に(a -> b)という関数を適用してVect n bを返すというものです。

my_vect_map : (a -> b) -> Vect n a -> Vect n b

まずmy_vect_map関数の型を定義し、関数定義部分でCTRL+ALT+Aを押します。 すると関数の実装の雛形が生成されます。

f:id:takezoe:20170615134138p:plain

続いてxsのところでCTRL+ALT+Cを押します。すると引数のパターンマッチに分解されます。

f:id:takezoe:20170615134149p:plain

?my_vect_map_rhs_1などとなっている部分は「ホール」と呼ばれるもので、Scalaでいうと???に近いものです。ひとまずこれで型チェックを通し、あとから実装を当てはめていくことができます。ホールの部分でCTRL+ALT+Sを押すと型情報から推測が可能な実装が生成されます。

f:id:takezoe:20170615134206p:plain

残ったホールでもう一度CTRL+ALT+Sを押します。

f:id:takezoe:20170615134219p:plain

なんということでしょう!関数の型を定義したあとは、ショートカットを押していくだけでmy_vect_map関数が完成してしまいました!

f:id:takezoe:20170615134237p:plain

もちろんこれは非常に簡単な例ですが、型駆動開発の片鱗は感じ取ることができるのではないでしょうか。静的な型付けのプログラミング言語コンパイル時の型チェックなど安全性が強調されることが多いですが、型駆動開発は型の力をよりアグレッシブに活用する開発スタイルといえるでしょう。

読書会の完走まではまだまだ長い道のりですが、型駆動開発の奥義を会得するべく日々修業を続けていきたいと思います。

Scalatra 2.5.1をリリースしました

Scala用のSinatraライクなWebフレームワークScalatraの最新バージョン2.5.1をリリースしました。

github.com

今回は主に2.5.0で入ったSwagger 2.0サポートの改善やバグ修正がメインとなっています。特に@jb08氏には多くのフィードバックをいただきました。ありがとうございます。修正内容の一覧は以下になります。

http://scalatra.org/2017/06/01/2017-06-01-scalatra-2-5-1-released.html

ScalatraはGitBucketで使っている関係上、メンテをしていかざるを得ないのですが、次は2.6.0で機能の整理・統廃合を行い、3.0.0で足回りのモジュール化(Servlet / http4sなどを選択可能に)をやりたいと思っています。

アクティブなコミッタが死滅してしまったのでここ半年ほど1人で細々とメンテしていたのですが、最近新コミッタとして@magnolia-kさんのリクルーティングに成功したので頑張っていきたいと思います。