ux00ff

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

implicit parameter として引数と戻り値が同じ型の関数型を指定するとコンパイルが通らない

Mac OS Sierra / scala 2.12.1 にて。結論から言えば、Predef で定義されているものとコンフリクトするので、自前で利用する implicit parameter にはちゃんと固有の型をつけなさいって話であり。

タイトル通りの現象にひとしきり悩んだ

以下のような test.scala を用意する。

implicit val intToString = (a:Int) => s"string ${a}"

def lovelyIntAndString(implicit f: Int => String) = f(10)

println(lovelyIntAndString)

で、スクリプトモードで実行すると、想像通りの動作をするわけです。

$ scala test.scala
string 10

lovelyIntAndString メソッドが、implicit parameterとして、同じスコープに存在する intToString を拾って動作しています。

これが、メソッドのシグネチャInt => Intにすると、コンパイルが通りません。以下は test2.scala として作成したサンプル。

implicit val intToint = (a:Int) => a

def lovelyInt(implicit f: Int => Int) = f(10)

println(lovelyInt)

これを同様に実行すると、

$ scala test2.scala
/Users/ma2saka/Developments/test.scala:5: error: ambiguous implicit values:
 both method $conforms in object Predef of type [A]=> <:<[A,A]
 and value intToint of type => Int => Int
 match expected type Int => Int
println(lovelyInt)
        ^
one error found
続きを読む

docker 17.06 の仕様変更に伴う aws-cli の動作変更

docker login 時に -e オプションを取らなくなったよ、ということで。

# docker 17.06より前
aws ecr get-login

# docker 17.06以後 ( aws-cli 1.11.91 以上が必要)
aws ecr get-login --no-include-email

こうなるのでヨロシクってメールがAWSから来ていた。というメモ。

メールで「 [Action Required] Docker Email Flag Removal [AWS Account: hogehoge]」ってきたから一瞬びびった。確かに、メッセージさらっとしか見てなかったけど今確認したら、docker 17.03 ではログイン成功したって表示のあとにさりげなく Flag --email has been deprecated, will be removed in 1.14.って書いてる。

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")
  }
}
続きを読む