読者です 読者をやめる 読者になる 読者になる

ux00ff

ビールとプログラミングと

sbtのバージョンを確認する

いつも忘れるので。

うまくいかない

$ sbt version

versionサブコマンドはsbtのバージョンではなく、現在のプロジェクトのバージョン値を返す。だいたいホームディレクトリで間違って打っちゃって、最初は1.0-SNAPSHOTって表示され、気がつくとホームディレクトリに projects/ とかできていることに気がつく。

うまくいかない

$ sbt --version

そんなオプションねーよと怒られる。-versionとか-Vとかたいてい試す。全部ダメ。

正解

$ sbt sbt-version

ということで、sbt-versionサブコマンドが正解。

> sbt-version
[info] 0.13.15

MindNode2

マインドマップツールが欲しかったので導入しました。

f:id:ux00ff:20170511121106p:plain

もともとFreeMindを使っていましたが、仕事で使うってこともあるしちゃんと業務用として使っているツールについては開発元に還元せねばという気持ちが最近強く。製品版なら課金はするし、GitHubにあるライブラリとかなら・・・えっと、Starを細々とつけたり? なるべくコントリビュートしたいとは思いますが、なかなかできていないのが実情で、いやそれはともかくとして。

ツール類は1000円超える価格帯だと妙にゴテゴテしてたりするのがありますが、MindNode2はそういうこともなく。シンプルできちんと動くツールとして重宝します。レビューで日本語がうまく入力できないとか書かれてたりしますが少なくともうちの環境では問題なかったです。macOS 10.12.4 Sierraと標準の日本語入力の組み合わせですね。

とりあえず以下のショートカットさえ使えればすぐに使い始められるシンプルさが大事です。

機能 キー
新しい子ノードを追加 Tab
新しい兄弟ノードを下に追加 Enter
新しい兄弟ノードを上に追加 Alt + Enter
ノードのテキストを編集 Command + Enter
兄弟間の位置の変更 Command + ↑, Command + ↓

日常的に使うツールはこのあたりの操作が直感的でないと辛いところ。どんなに高機能でも人は使い慣れたツールに戻っていくんですよ。そう、秀丸とかに。

jqのtodateでタイムスタンプ値を読みやすく

できるんじゃないか!

背景: jq コマンドで todate が使えるのをさっき知って。たぶん、何度目かに知って、感動しています。いいんだ、嬉しいことは何度あったっていいんだ。

つまりCloudWatch Logsのエポックタイム形式の表記を「2017-05-07T07:20:58Z」のような人間に優しい感じに拾えるということであって、これはとてもありがたい。filter-log-events がたいへん便利なんだけど時刻がエポックミリ秒なのがどうにも辛かったので。なお jq は 1.5 を使っています。

で、これができると、以下のようにCloudWatchのログが探せて結果がとても読みやすいわけです。

aws --profile=production logs filter-log-events \
    --log-group-name "/aws/lambda/my-awesome-log-group!" \
    --max-item 10 \
    --start-time `date -v-5M +"%s"` \
    --query "events" \
    --filter-pattern='REPORT' \
    --query "events[].{timestamp:timestamp,message:message}" | \
    jq '.[] | {: .timestamp | tonumber | (. / 1000) | todate , message: .message}'

しかし “–query” 内の関数に todate 追加されないものかなー、と思って見てみる。aws-cliのrequirements.txtでは boto/jmespath.git が参照されてます。実際に環境に利用されているのは jmespath-0.9.1のようですね(最新は0.9.2)。そしてpython版実装に対して todate 関数は実装されていません。残念。夢潰える。

さらっと見て jmespath の関数の実装は難しくないので送り付けちゃうのもいいのかもしれません。例えばエポックミリ秒を date に変換する millixec_to_date をこんな風に作ることで動くには動く。

    @signature({'types': ['number']})
    def _func_millisec_to_date(self, arg):
        from datetime import datetime
        return datetime.fromtimestamp(arg/1000)

じゃあどこに突っ込むかといえば、jmespath/functions.pyなわけなんですが、算術演算子がサポートされていない中で、エポック秒とエポックミリ秒を用意するのはスマートではないしなぁ。

Hello PlayFramework2

ちょっと仕事でWeb API周りを用意する必要がありまして。流れでScalaだろうなぁという話もあって、PlayFrameworkをチラ見していました。ん、Play2 Framework? PlayFramework2? どっちだろう。まあよい。

JSONを返すエンドポイントを作成するロールプレイ

プロジェクトを作成する

$ sbt new playframework/play-scala-seed.g8

ここでは play-api としました。

プレーンテキストなエンドポイントを作る

まずはエンドポイントに対応するコントローラとメソッドを作成します。ドキュメントによると、「Controllers are action generators」だそうです。かっこいいですね。もともと雛形として HomeControllerとか作られていますが、適当に新しいファイルを作っても作らなくてもいいです。controllersの下に作りましょう。

以下のような簡単な新しいコントローラを作成しました。アクセスすると hello world と挨拶してくれるイメージです。

package controllers

import javax.inject._
import play.api._
import play.api.mvc._

@Singleton
class GoodController @Inject() extends Controller{
  def hello = Action { implicit  request =>
    Ok("hello world")
  }
}
続きを読む

Scala x Matsuri

2月25日、2月26日にお台場で開かれたScalaMatsuri2017に参加してきました。初参加です。

とはいえスポンサーブース側でブースに張り付いていたので講演は聞けず、惜しいことをしました。後から資料を見て楽しむことにします。

ユーザー母数としてはけっして規模が大きいわけではないScalaという単一言語のイベントでありながら、運営母体がすごくしっかりしていて参加者も愛に溢れており、心から楽しむことができました。コミュニティの関心のノリがいろいろわかって、濃い人とお話もできて、実に濃密な二日間でした。スタッフの練度も高く、不愉快に感じたことは全くなかったと言っていいくらいです。それにしても同時通訳すごかったなぁ。

f:id:ux00ff:20170310115457j:plain

写真は公式Twitterのエントリからパクってるわけですが、ブースはこんな感じで出していました。今回スポンサーブースで建てた MacBook Proのプレゼント企画、課題として設定したクロスワードはおおむね好評だったけど、日本語読めない勢がちょっと残念そうだったので、次回は日本語に依存しないコンテンツ作らないとなと痛感しました。こんなに国際色豊かだとは思っていなかった。

これまではあまり技術系のコミュニティイベントに参加することはなかったのだけど、けっこう熱気に当てられました。いいもんですね。こういうの。有名人に全く知らずに話を振って苦笑されるシーンもたまに。講演者の @niw さんに「今日は何を目当てに来られたんですか」と聞いてしまったり、・・・いや、最大の失敗はきの子さんに「本名ですか」と聞いてしまったことです。思い出すと悶えるしかない。あるある。

Right value is right

Either型で成功と失敗を表すとき、どうして慣習的にLeftがエラー情報、Rightが正常系なんだろうと不思議だったんですが、Right(右)とRight(正常な)がかかってるっていうことを知って地味に感動しました。ダジャレか。

個人的には最初、先に(左側)正常値を書くのが自然かなと思っていたんですが、コードで戻り値をチェックする際 Right で正常というのは言われてみたら納得感あります。

scala> def div(c:Int ,d:Int) :Either[Exception, Int] = {
     |   d match {
     |     case 0 => Left(new Exception("d is 0"))
     |     case _ => Right(c/d)
     |   }
     | }

scala> div(5, 2)
res34: Either[Exception,Int] = Right(2)

scala> div(10, 0)
res36: Either[Exception,Int] = Left(java.lang.Exception: d is 0)