Scala入門以前 2015/04版
Scala入門したいけどどこから手を付けていいか分からない人向けの「まず何に手をつけるべきか」集みたいなもの。
Scalaの言語まわり知りたい
コップ本を一通り読むのがお進め。半分ぐらいでもいいかも。これより軽い入門書が欲しいよね、という話はちょいちょい話題に上るけど現状ない気がする(あったらおしえてください
開発環境の構築したい
sbt(Scala界で極めて一般的なビルドツールだ)だけ設定すれば8割終わる、とか良く言われている気がする。UNIX系環境ならsbt-extrasをインスコすれば大体いけるのでは。scalaのREPL(対話型で実行して試せる環境)はそれ専用のディレクトリ作って中にproject/build.propertiesファイル作ってsbt.version=0.13.8とか書けば良い。うん、まぁちょっと面倒くさい。ぼくの感覚ではRubyよかマシ…うわーなにをするやめろー!
補足すると、sbtはビルドツールではあるが、そのプロジェクトで依存するライブラリを全て読み込んだREPL環境を立ち上げる機能があり、ぶっちゃけ最初のうちはscalaコマンド無くてもそれでいける。scala無しでそれが立ち上がる理由は、sbtがScalaをダウンロードしてくるからである。しかもプロジェクトのScalaVersionに合った奴が落ちてくる。わおー。
だから、空プロジェクト作ってsbt consoleとかやればscalaのREPL環境が立ち上がるという訳。
Scalaやる以上sbtは(嫌でも)かなりお世話になる筈なので最初からsbtというのは割と良い選択肢だと思う。
FullHD超えのモニターを使うためのTips 2015/04
はじめに
最近会社で4K(3840x2560) + 2560x1440という贅沢なモニター環境を構築したので、苦労した点のメモを兼ねてまとめておく。
2015年4月現在において、ノートPCやタブレットだと、探せばそこそこFullHD(1920x1080)オーバーの環境が手に入る。MBP Retina、VAIO Z、Nexus9 etc...
一方desktopでも、4Kが5万円で手にはいるようになって、そこそこ身近になってきてはいるものの、FullHDと同じ感覚で気軽に買うにはハードルが高い問題がいくつかある。主にこの問題について解説する。
なお今時アナログ接続なんて有り得ないという主義なので、D-SUBは考慮してない。
2560x1440
60Hzで表示したい場合、通信速度制限の都合で、FullHD世代にメジャーだった幾らかのコネクション方式に制限が入る。
まずDVIだが、DualLink対応が必須になる。割と古い規格なので、初期のモニターはDVI-DLを前提としている場合が多く、比較的地雷を踏みにくい。
HDMIの場合、Ver1.3で追加されたHighSpeedが必須になる。ケーブルも対応のものが必要。モニター・GPUがこれに対応してない可能性もある。
DisplayPortなら問題はないと思われる。端子があれば。
4K
2560x1440は地雷があるだけだったが、4Kは最初から4K前提でマシン調達を考えた方がよい。
まず現行コンシューマー向けで4K60Hz対応のコネクションはDisplayPort1.2のみである。HDMI2.0であれば4K対応するが、モノを見たことがない。そもそもDP1.2非対応のモニターが稀にあって、これはつまり30Hz使用を前提にしている。
4KはGPUの条件もある。外部GPUボードのGPUであれば、DP1.2対応さえ確認すればおそらく問題ない。CPUの内臓GPUがやっかいで、搭載GPUが4K対応であることと、マザーボードも4K対応が必要。チップセットで決まる訳ではないので、マザボごとに調査が必要。搭載GPUに関して言うと、Haswell Reflesh世代だとi5以上が搭載する内臓GPUのみのようだ。
まとめ
と、難しい点はあるものの、高解像度モニターの圧倒的情報量は、CPU性能数十%頑張るよりもPCライフを変えることは間違いないと思う。文字綺麗だし!
Play2.3(Scala)で、sbtだけでPlay環境を構築する
更新
5/12 バージョン番号更新しました
はじめに
Playは使いたいけどActivatorとか落とすのデカいしだるい!そんな貴方のための記事
http://qiita.com/erukiti/items/0decc5fe8bf2c61d3b1e
がPlay2.2までにしか対応してなかったので書いてみた。割と変わってるんですよね。
追記:もっと良いの見つけた。こっち見た方が分かりやすいかも http://d.hatena.ne.jp/xuwei/20140531/1401525122
必要なファイル
build.sbt
scalaVersion := "2.11.6" lazy val root = (project in file(".")).enablePlugins(PlayScala)
project/plugins.sbt
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.9")
project/build.properties
sbt.version=0.13.8
以上は必須。あとは最低でもconf/routesと、app/controllers以下に何かしらのControllerを継承したclassが必要でしょう。例えばこんな感じ
conf/routes
GET / controllers.Application.index
app/controllers/Application.scala
package controllers import play.api.mvc._ object Application extends Controller { def index = Action { Ok("Hello, world!") } }
あと、マトモなプロジェクトであればconf/application.confが必要になるでしょう。ただ面倒なのでこの辺は公式サイトでも見て拡張していってください。良いPlayライフを!
USB充電速度の計測
はじめに
昔からスマホの充電速度には違和感があって、具体的には2A出力のUSB充電器を買って試してみても、あんま早く感じない、というのである。一方でApple製品はどういう訳だか異常に充電速度が早く感じる。とまあ良く分からんなら計測してみればいいということで、USBの電圧電流測定器買ったので調査してみた
ケーブルの充電電流
結論から言うと最も影響が大きいのはコレだった。特にデータ通信が可能なmicroUSBケーブルは、充電器に関わらず軒並み0.5Aしか出なかった。100円均一のケーブルは1.0Aで、充電ケーブルなら大体この値だと思われる。速度に拘らないならこの辺りでも特に問題は無い。拘る人は素直に急速充電を謳うケーブルを買うべき。こちらは2.4Aを謳っている奴を買って、少なくとも2.0Aよりは上であろうと思われる。(2.0Aを超える充電器が無かった)
スマホによる制約
当然スマホによっても異なる。Xperia Z Ultraは1.5Aが上限で、思ったより低い。iPadは1.9Aを観測したが、手元にある充電器のMAXが2.0Aだからなだけかもしれない。Butterfly Jがまた特殊で、電源OFF時で0.5A、画面ON時は1.0A、画面OFFでなおかつ電源が入ってるときのみ1.6Aまで出るという仕様。iPod Touchは0.9Aだった。
そういえばAppleのケーブルは通信できても特に速度が落ちない気がする。
充電器による制約
一般に書いてあるスペック通りの数字が出る可能性が高い。手元にEvergreenの充電器あって、コイツ速度出ないんじゃないか、と思っていたのだが、2.0Aの口でちゃんと1.9A出たので、まぁ充分かと思われる。
モバブーだと、cheeroの奴が公称2.1Aの口で1.5Aを観測した。モバブーも思ったより出力高いようだ。
まとめ
とまあ充電遅い原因がケーブルだと特定できたので、今ケーブルを大量購入しようとしているところである。
ちなみに、Ingress中にモバブーで充電しながらプレイしてもバッテリーが減る問題は、0.5Aが上限のケーブルを使っていたからだと分かった。残念過ぎる
あと、標準に附属しているケーブルで充電したとき、Apple製品はケーブルがネックで充電速度落ちず、バッテリー少なめで、よくチューニングされた省消費電力OSを使っているのもあって、圧倒的な速度で充電していくのに対し、Androidは標準附属のケーブルだと充電速度が制限されている上に、バッテリー容量で駆動時間を稼ぐという傾向もあって、iOSに比べて致命的に充電が遅くなっている傾向があるようにみえる
java.sql.Timestampのequalsが規約を満たしてない
事の発端
とある社内ライブラリを修正していたら、java.util.Date同士の比較で、getTimeを呼び出さないとtrueにならなくてエラー、というコードを発見した。こんな感じ
date1.getTime == date2.getTime // => true date1 == date2 // => false
Scalaの==はJavaのequalsメソッドを呼び出す仕様なので、参照を比較しているということはない。
ところがjava.util.Dateのドキュメントを読むと、「getTimeでミリ秒を比較して同じならtrueを返す」って書いてある。
http://docs.oracle.com/javase/8/docs/api/java/util/Date.html#equals-java.lang.Object-
この辺りでTwitterに色々書いて、色んな意見を聞くうちに、筋が悪いjava.util.Dateを継承した何かが関わってるのでは、という仮説を立てる。
java.sql.Timestampだった
デバッガで調べてみると、date1が実体はjava.sql.Timestampだったということが分かる。標準ライブラリだけどひょっとして…と思ってequals実装を見てみるとどうやら元凶はこやつだと分かる。
ここからequals実装を抜き出したのが以下
public boolean equals(Timestamp ts) { if (super.equals(ts)) { if (nanos == ts.nanos) { return true; } else { return false; } } else { return false; } } public boolean equals(java.lang.Object ts) { if (ts instanceof Timestamp) { return this.equals((Timestamp)ts); } else { return false; } }
あっこれequalsの規約にある「対称性」満たしてないやつや!
equalsの規約
equalsとか==の実装は、色々な所で使われるために、直感的におかしな挙動をしないようにいくつか規約があり(詳細はEffective Javaを読むかググるのが良いと思う)、その1つに対称性を満たしてないといけない、ってのがある。つまりこういう
s1 == s2がtrueのとき、s2 == s1がtrueを返す
何を当たり前なことを、って言われそうだが、Timestampの実装は満たしていない。以下に反例を挙げる
new java.util.Date(0L) == new java.sql.Timestamp(0L) // => true new java.sql.Timestamp(0L) == new java.util.Date(0L) // => false
私見では、そもそも継承すること自体が間違いだったと思われる(実際ドキュメントで実装継承のつもりだったとか言ってる。アホか)
結論
Javaの標準ライブラリはクソ(再確認)
Scalaのmatch caseが怖いと思ったら怖くなかった話
おさらい
Scalaのmatch case式がある。他の言語で言うところのswitch caseみたいな立ち位置だが、実際には比較にならないほど強力である。
def f(n: Int): String = n match { case 1 => "いち" case 2 => "に" case _ => "1と2以外" // default値 }
普通の値比較はこう。match「式」なので、返り値も持てる。_はそれより上で引っ掛からなかった値が全部処理される。勿論比較対象はStringじゃ使えないとか良く分からない制限はない。
次からはScala特有だが、まず、変数に束縛できる。
def f(n: Int): String = n match { case 1 => "いち" case 2 => "に" case x => x.toString }
_を変数名に置き換えただけのもの。Tupleや配列などの一部分にmatchすることもできる。(抽出子によるパターンマッチ)
def f(t: (Int, String)): String = t match { case (1, _) => "いち" case (2, str) => str case (x, _) => x.toString }
この場合、intが1であればstringが何であれ"いち"を、2であればstringをそのまま、それ以外であればintをtoStringしたものを返す。これらはunapply(というより抽出子か)で実現されているが、詳細はもっと良い他の資料を見ると良い(ググレカスの婉曲表現)
他にも型で分岐することもできる。
def f(x: AnyVal): String = x match { case y: String => y case y: Int => y.toString case _ => "Unknown Type" }
ifっぽく分岐したいならガード条件のifを使えばいい。
def f(x: AnyVal): String = x match { case y: Int if y > 0 => "Over 0" case y: Int => "Under 0" case _ => "Unknown Type" }
Haskellでas Patternと呼ばれている@も使える。
def f(t: (Int, String)): String = t match { case x @ (i, "OK") => assert(x._1 == i) x.toString case x @ (1, str) => assert(x._2 == str) str case _ => "Other" }
@前のxに全体が置かれつつも、中身は中身でちゃんとチェックしたりヒットしたりしてくれる。ただしおこの場合、全体をヒットさせるならtで良いので、多重Tupleとかでないと活躍しないかもしれない。
本題のこわいところ
以上のようにmatch caseには様々な使い方があり大変高機能なのだが、多機能故に、複数の意味に取れるパターンがある。
特に「特定の値にヒットする」caseと「変数に束縛する」caseがどっちとも取れる場合が割と良くある。
シンプルな例だと
val x = 2 1 match { case x => x case _ => -1 }
の結果は、幾つかのWarningと共に1が出力される筈だ。このxは束縛の意味になるから全ての場合でヒットする。下の行が無意味だという警告が出ている筈だ。
ではこれは
val X = 2 1 match { case X => X case _ => -1 }
-1が返ってきて、先程と違う結果になる。何故ならば、頭が大文字である場合は定数として扱われ、「特定の値にヒットする」方が優先されるからである。もちろん2でmatchさせれば2が返る。
ひねくれてこんなの考えてみる。
object math { val Two = 2 } 2 match { case math.Two => "に" case _ => "それ以外" }
ちゃんと「に」が返ってくる。
じゃあこんなのできるんじゃね!?ってなる
case class Pos(x: Int, y: Int) val p = Pos(1, 2) 1 match { case p.x => "x" case p.y => "y" case _ => "other" }
普通に通る(xが返ってくる)
で、これできないパターンあるんやで!っていうのを挙げようとしたけど何故か見つけられなかったので、怖い話をするつもりだったけど普通にこわくない話になった。というオチ