Keep on moving

あんまりまとまってないことを書きますよ

scalafmt の設定ファイルのおすすめ最小構成(2017.10)

package version
scalafmt 1.3.0

皆さんScalaでもコードフォーマットツール使ってますか? 僕はscalafmtを愛用しています。

http://scalameta.org/scalafmt/

goのgofmtみたいなものなんですが、設定ファイルでフォーマットの条件をいじれます。 設定しなくてもいいんですが、まだたまーに 互換性のないアップデートがあったりするので 個人的には設定ファイルをつくっておくのをおすすめしています。 で、最小構成の設定ファイルを毎回作るので、一旦まとめてみました。

最小構成

僕はプロジェクトに追加するときはひとまずファイルをつくっています。 ちなみにプロジェクトのroot direcotory に .scalafmt.conf と言う名前で作ります。

# Only format files tracked by git.
project.git = true # Default: false
# Manually exclude files to format.
project.excludeFilters = ["target/"]
#
# maxColumn = 100 # Default: 80
  • project がgitだったら project.git=trueは入れましょう。gitによって追跡されるファイルのみがフォーマット対象になります
  • target配下は外していいと思います
  • maxColumnは好きな値をいれると良いでしょう。こだわりがなければ80文字で良いかと。github mobileとかでも読みやすくなるそうな。

その他

  • Q:既存のプロジェクトにフォーマットを崩さないように追加したい場合は?
  • A: KKK(Kiai/Konjou/Konki) でオプションを駆使して頑張ってください!!

参考

Scalafmt - code formatter for Scala

qiita.com

dockerで実行するときにulimitを設定する

software version
docker 17.09

dockerを使ってUnitTest実行したいときってありますよね? でもファイルとかソケットをもりもり開く処理がおおいとosのopen filesの上限を超えちゃうことってありますよね?(ホントか?)

普通にOSのせっていだったら以下のようにすればいい

ulimit -n 12345

ではdockerだとどうなのよってことで調べました。今は docker run のときのオプションで設定できるらしい

docs.docker.com

docker run --ulimit nofile=12345:12345 <image-tag>

うーんdocker containerを作り直さなくていいので楽でいいですね。

先人に感謝

小規模なライブラリでのJUnit5 migration方法

JUnit 5がついにリリースされましたね。

後方互換性がなくなったこともあって、使い方を覚えたくなって私の自作ボットエンジン(Java版のHubot的なもの)をJUnit5で動くようにマイグレーションしてみました。

TL:DR

github.com

題材

GitHub - masahitojp/botan-core: tiny chat bot framework for Java SE 8.(like a Hubot)

Java8 Lambdaでパフォーマンスがどれくらい変わるかみるためにつくったもの

マイグレーション用の資料

JUnit 5 User Guide

Release JUnit 5.0.0 · junit-team/junit5 · GitHub

>> JUnit 5.0.0 = Platform 1.0.0 + Jupiter 5.0.0 + Vintage 4.12.0

今までと違ってテスト実行エンジンとテスト用の記法が別れてると考えるといいかも(まだちゃんと理解できてません)
VintageはJUnit4との互換性を残すためのものらしい

置き換え方

ざっくり以下の用に置き換えると無事移行できました

名前 4 5
Before org.junit.Before org.junit.jupiter.api.BeforeEach
After org.junit.After org.junit.jupiter.api.AfterEach
Test org.junit.Test org.junit.jupiter.api.Test
assertEquals org.junit.Assert.assertEquals org.junit.jupiter.api.Assertions.assertEquals

ざっくりした例ですがこんな感じになります。
github.com

まとめ

変更点は大きいし、ライブラリにもたくさん文章が増えていますが、テストが少ないせいかマイグレーションするのは
ドキュメントを調べる時間もいれて30分位ですみました。
個人的にはBefore -> BeforeEachに名前が変わったことでいつ実行されるかわかりやすくなったと思います。
みなさんのマイグレーションの一助になるといいなーと思っています。

JUnit5の実装をすすめた皆さん本当にありがとうございました。

Rasberry Pi 3 +OpenCV3.xの環境を作ってみた(archLinux)

顔認識やってみたくなったので、Rasberry Pi 3 +OpenCV3.xの環境を作ってみた。

環境

raspi3を買う

今回はAmazon で買った。

Amazon | Raspberry Pi3 Model B ボード&ケースセット 3ple Decker対応 (Element14版, Clear)-Physical Computing Lab | マザーボード | パソコン・周辺機器 通販

環境構築

archLinuxをinstall

OpenCV の3系を自前ビルドしないで使いたいのでarchLinuxを今回は採用した。

opencv (arm) | Packages | Arch Linux ARM

インストールもRaspberry Pi 3向けのドキュメントが書かれていてすごく親切ですね。 ここの"install"の手順通りで悩まずにインストールできます。 ちなみにfdisk 等の操作はLinuxの環境で行ったほうが便利だと思います。

https://archlinuxarm.org/platforms/armv8/broadcom/raspberry-pi-3

sudo設定とか新規ユーザー作成とか、sshdの設定とかは割愛。

OpenCV

opencv.org

pacman -S opencv python3

これだけだとcv2をimportした時に失敗する。

>>> import cv2
ImportError: libhdf5.so.100: cannot open shared object file: No such file or directory

stackoverflow.com

追加でhdf5をインストールすると無事読み込めるようになるらしい。

pacman -S hdf5

無事これでエラーがでなくなりました. 顔認識の部分はまた次回にでも。

型ヒントが提供されていないpythonライブラリにmypy用に型ヒントを入れる

who can zen better than cats?

最近mypyを趣味で使い始めたのでいろいろ書こうと思います。 @tk0miiyka さんの記事を読んでとりあえず自分の仕事でmypy使えそうなところをいろいろ考えてみた

対象バージョン

version
python 3.5.2
mypy 0.4.6
last update 2017.01.08

TL;DR

pyiファイルをつくれば世の中の型ヒントが提供されていないプロジェクトに型ヒントをつけられる。 まーでも結構めんどいので、みんなでtypeshedを育てていくのがよさそうです。

GitHub - python/typeshed: Collection of library stubs for Python, with static types

mypyって?

こちらの素晴らしい記事を読んだほうがいいですね。

qiita.com

要はPython3.4以降で使える静的型チェッカーらしい。個人的にはコメントをツールで拡張できるところがいいと思ってます。 コメントだからスクリプトの邪魔をしないんですよね。また、あとから書き足すことも可能です。 世界樹の迷宮風に言うと「君は型を書いてもいいし、書かなくてもいい」ってところです。

ちなみに僕はある程度使い回す&&インターフェースがほぼもう変更されない段階のpythonスクリプトとかに書いてます。 たまにコード読むとこのコードなんだったか忘れますよねー。(ものぐさ

インストール

pipで一発です。python 3.4以降で動くのでvenvとか使うと手元の環境が汚れないので良いかと。

pip install mypy-lang

venvについてはこちら http://docs.python.jp/3.5/library/venv.htmldocs.python.jp

mypyかるく使い方説明

といいつつ、この辺見るのがよさ気。割とちゃんとドキュメントが書かれてるのが良い感じ。

http://mypy.readthedocs.io/en/latest/basics.htmlmypy.readthedocs.io

python2でも使えるよ

type hintってpython3から入ったからpython2のスクリプト使えないっぽく見えるんですが、実際には使えますです。 こんな感じ。

http://mypy.readthedocs.io/en/latest/python2.html?highlight=py2mypy.readthedocs.io

でもtypeshedが対応してないといろいろ怒られる

残念ながらtypeshedに登録されていないライブラリを実行するとmypyさんに怒られてしまう。 例えばfabric用のファイルとかにmypyを実行するとこんな感じで怒られてしまいます。

from fabric.api import run

def test():
  "() -> None"
  run("ls")
$ mypy --py2 fabfile.py 
fabfile.py:1: error: No library stub file for module 'fabric.api'
fabfile.py:1: note: (Stub files are from https://github.com/python/typeshed)

typeshedにstub登録されてないっすよって言われてしまいました。 軽い気持ちでmypy使いたい勢としては辛い。。。。

pyiファイルってのがある

やっとここからが話したかったことです。 そんなどうしようもない人たち向けにpyiってファイルがありまして、これを用意するとなんとかなる。

out/
└── fabric
    ├── __init__.py
    └── api.pyi

api.pyi

def run(command: str): ...
MYPYPATH=./mypy-stub/fabric/ mypy --py2 fabfile.py 

こんな感じで実行しても怒られなくなります。 でも毎回自分でpyiファイルを用意するのはめんどいよね。

stubgen

という声のために、mypyはpyiを作ってくれるコマンドを用意してくれてます。 こんなのをつかうとメソッドリストは簡単につくれる

mypy/stubgen.py

@methane さんが作ってるpymysql用のstubもあって、これもstubgenつかってるらしい。

github.com

使い方はmypyとstubを作りたいライブラリをインストールして、実行するだけ!!

詳しくはコードを読んでね

https://github.com/python/mypy/blob/master/mypy/stubgen.py

mkdir out
stubgen fabric
stubgen fabric.api
stubgen fabric.operations

これで無事作られる...やったー、というわけには行かなくてですね。。。

残念ながら今のstubgenはメソッドとimportを抜き出してくれるだけで、ライブラリ内でimportしてるところをうまく抜き出してくれないんですよね。。。 まー自力でメソッドリストつくらなくてもいいのは助かります。

とかとかで対象になるライブラリのコードを読んで対処します。

というわけで頑張ってある程度実行できるやつを作りました。

github.com

$ git clone https://github.com/masahitojp/fabric-mypy.git
$ MYPYPATH=./fabric-mypy/ mypy --py2 learn_mypy/fabfile.py 

ふーやっと怒られなくなりました。お疲れ様でした。

まーこんな感じで型情報が提供されてないライブラリを使ってmypyできるところまでこれました。 mypyを使いやすくするためになるべくtypeshedに上げるように頑張りたいところですねー

気になってるもの

  • ライブラリ側のバージョンアップでインターフェース変わったらどうするよ
  • pyiのテスト

github.com

参考

tk0miya.hatenablog.com qiita.com qiita.com

PostgresqlでUpdate/Select

やってみたらできた。このへんはRDBMSごとに書き方が変わりそうだな

-- T1.date2にT2のdate2を月末にスライドして格納
 update T1 set date1=a.date1, date2= a.date2 from 
  (select id, date1,
    to_date(to_char(date2,'yyyy-mm-01'),'yyyy-mm-dd') 
     + interval '1 month' + interval '-1 day' date2 
    from T2) a 
  WHERE T1.fk_id = a.id;

Eclipse Collectionガンガン使おう

うまくまとまらないけど、つらつら書いてみようと思う。

vaskir's blog: Hash maps: Rust, F#, D, Go, Scala

読んでてScalaの数値があんまり良くない原因がコメント欄で書かれてた

Scala/JVM's boxing and unboxing is very slow in such a tight loop.
Eclipse collections may be useful.

https://gist.github.com/zakki/66d785b4a9d3c64bc9f8199d7e290e07 13x faster

ただ、元コードがRustでの

  • std::collections::{HashMap}へのキー追加
  • Vecで頭から参照しながら足してく

なので、int[]で計算してたのが気になったのでeclipseコレクションつかって計算してみた

  • org.eclipse.collections.impl.factory.primitive.IntIntMaps
  • org.eclipse.collections.impl.factory.primitive.IntLists
import org.eclipse.collections.api.list.primitive.MutableIntList;
import org.eclipse.collections.impl.factory.primitive.IntIntMaps;
import org.eclipse.collections.impl.factory.primitive.IntLists;

import java.util.Random;
import java.util.function.Supplier;
import java.util.stream.IntStream;


public class Main {

	private static <T> void  time(final String name, Supplier<T> func) {
		long s = System.nanoTime();
		func.get();
		System.out.println(String.format("%s: %d elapsed.", name, (System.nanoTime() - s) / 1_000_000));
	}

	public static void main(String[] args) {
		final MutableIntList source = IntLists.mutable.empty();
		final Random r = new Random();
		IntStream.range(0, 50_000_000).forEach(i -> source.add(r.nextInt()));

		time("Insertion", () -> source.injectInto(IntIntMaps.mutable.empty(), (x, y) -> {
			x.put(y, 0);
			return x;
		}));

		time("Lookups", () -> source.injectInto(0, (x, y) -> x + (y % 10)));
	}
// Insertion: 4793 elapsed.
// Lookups: 482 elapsed.
}

https://gist.githubusercontent.com/masahitojp/475f8da57fd54f56bf9d7786c1311f6a/raw/d9f208ea1c9e29d6b644fbdf38f41d4014074a5b/ECMain.java


それにしてもMapは遅いなぁ。。。
// Map
Insertion : 42535 elapsed.

// eclipse collectionを使用
Insertion: 1040 elapsed. 

まとめ


boxing/unboxingがきになるときはEclipese Collectionを積極的につかうべし