scala

warning: Creating default object from empty value in /opt/bitnami/apps/portal/htdocs/modules/taxonomy/taxonomy.pages.inc on line 33.

-Xlint, -Xfatal-warnings, そして Scalafix を用いた Scala の厳格化

in

コンパイルする、さもなければコンパイルしない。警告などいらない。最近気に入っている Scala コンパイラのフラグは "-Xlint""-Xfatal-warnings" の 2つだ。

以下は、サブプロジェクトと共に使えるセッティングの例だ:

ThisBuild / scalaVersion := "2.12.6"
 
lazy val commonSettings = List(
  scalacOptions ++= Seq(
    "-encoding", "utf8",
    "-deprecation",
    "-unchecked",
    "-Xlint",
    "-feature",
    "-language:existentials",
    "-language:experimental.macros",
    "-language:higherKinds",
    "-language:implicitConversions"
  ),
  scalacOptions ++= (scalaVersion.value match {

sbt-nocomma を用いたカンマの消去

in

本稿は build.sbt からカンマを消去する nocomma { ... } マクロを導入する sbt-nocomma を紹介する。

import Dependencies._
 
lazy val root = (project in file("."))
  .settings(nocomma {
    ThisBuild / organization := "com.example"
    ThisBuild / scalaVersion := "2.12.4"
    ThisBuild / version      := "0.1.0-SNAPSHOT"
 
    name := "Hello"
 
    // comment works
    libraryDependencies += scalaTest % Test
  })

猫番: 17日目

in

猫番: 17日目を書いた。始対象と終対象、積、双対性、余積など抽象構造を見ていきつつ、Either を coproduct として使う方法を紹介します。

ファイルパスの URI 参照へのエンコード方法

in

本稿では古くて新しい問題であるファイルパスの Uniform Resource Identifier (URI) へのエンコード方法について議論する。

2017年現在、権威ある情報の元は RFC 8089 - The "file" URI Scheme だ。未来の読者の人は "file URI scheme RFC" で検索して最新版を探してほしい。プログラマの人は RFC を読んで下さい。この覚え書きは URI エンコーディングに関連した問題の認識を高めるためのものだが、RFC の代替とはならない。

最近 file:/foo/bar がパースできないというプラットフォーム間の相互乗り入れ問題に出くわした。ファイルパスを URI として表現するのに関連した問題に悩まされるのはこれが最初でもない。ファイルシステムという概念は 1960年代に遡り、1990年代から URL があることを考えると、このコンセンサスが取れていないというのは意外なことだ。しかし、十進法小数のように、深く掘り下げたり、データを交換しはじめると、Matrix のほころびが見えてくるのかもしれない。

Contraband、case class の代替案

in

しばらく考えている疑問がいくつかある:

  • データや API はどう書かれるべきだろうか?
  • そのデータは Java や Scala ではどう表現されるべきか?
  • そのデータは JSON などのワイヤーフォーマットにどう変換することができるか?
  • そのデータをどうやってバイナリ互換性を崩さずに進化させることができるか?

case class の限界

Scala でデータ型を表現する慣用的な方法は sealed trait と case class だが、バイナリ互換性を保ったままフィールドを追加することができない。簡単な Greeting という case class を例に取って、それがどのようなクラスとコンパニオンオブジェクトに展開されるか考察してみよう:

package com.example
 
class Greeting(name: String) {
  override def equals(o: Any): Boolean = ???
  override def hashCode: Int = ???
  override def toString: String = ???
  def copy(name: String = name): Greeting = ???
}

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 機能を利用するために、完全なオーバーホールが行われた。

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 オブジェクトに変換することができる。

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"
Syndicate content