Haxeのexternとinlineを同時に書くとinlineが優先されるっぽい
HaxeのjQuery externで new JQuery("selector"); って書くのがダサいなぁと思って、いろいろ試していたときにコンパイルできたコードをメモ。externとinlineを同時に書くとinlineの方が優先されるらしい。
Haxe 3.1.3で確認。
@:native("jQuery") extern class JQuery { public static inline function create(selector: String, ?context: Dynamic): JQuery { return untyped __js__("jQuery")(selector, context); } }
var elem = JQuery.create("body"); var tag = JQuery.create("<div/>");
その他のポイントとしては、untyped __js__("jQuery")で、Functionを取得して、それをコールしていること。
で、ここまでやってみたいのだけど、そもそも「jQueryの $() が色々できてしまうこと」自体がHaxeの文化にマッチしていないので、$.find() とか $.parseHTML() を使った方がいいよねという考えに至ったので、不採用とした。
HaxeのJavaScriptターゲット用のビルトイン
Haxe 3.0から __js__() 以外にもいくつか追加されてたらしい。知らんかった。
untyped __js__(js : String) : Dynamic
インラインJavaScript。
var console = untyped __js__("console");
untyped __js__("console.trace()");
untyped __instanceof__(obj : Dynamic, type : Dynamic) : Bool
JavaScriptの"instanceof"。@ktz_aliasさんが、標準APIのStd.is()を使えば良いのではって言ってたけど、本当にそうだと思う。
if (untyped __instanceof([], Array)) { // if ([] instanceof Array) { }
untyped __typeof__(obj : Dynamic) : String
JavaScriptの"typeof"。Haxe 3.1から使えるようになったっぽい。
switch (untyped __typeof__(x)) { // switch (typeof(x)) { case "string": case "number": case "boolean" default: }
untyped __strict_eq__(a : Dynamic, b : Dynamic) : Bool
JavaScriptの"==="。Haxe 3.1から使えるようになったっぽい。
if (untyped __strict_eq__(x, "hoge")) { // x === "hoge" }
untyped __strict_neq__(a : Dynamic, b : Dynamic) : Bool
JavaScriptの"!=="。Haxe 3.1から使えるようになったっぽい。
if (untyped __strict_neq__(x, "fuga")) { // x !== "fuga" }
Haxeの構造的部分型(typedef)ってstaticでも使える
Haxeを使い始めて2年ぐらい経つけど、今更こういうコードが書けることに気が付いた。
typedef Foo = { function print(): Void; }
class Hoge { public static function print() { trace("Hoge"); } }
var foo: Foo = Hoge; foo.print();
Haxeで仕方なくnullと付き合う
Haxeは現時点で選択しうるaltJSの中では型システムが一番出来が良く、代数的データ型(Haxeではenum)が扱える点が素晴らしい。しかし、元々はFlashを前提とし、今はマルチターゲット(JavaScript、PHP、C++、C#等)にコンパイルする言語として設計されているため、どうしてもnulを扱わなければならない。
これはHaxeに限った話ではなく、F#やScalaなどでも同様の問題があるのだが、これらの言語と比較すると、Haxeはすこしnullが全面に出てしまっている(むしろnullを許容する言語設計にすることで、学習時の敷居を下げているのではないかとも思えるが…)ので、nullを根絶したい勢にすると、ちょっとぐぬぬとなる面がある。
少し前置きが長くなったが、Haxeで仕方なくnullを付き合うための方法の1つを書いてみる。
そもそも、nullを使わないコードとは?
Option型(言語によってはMaybe型)を使うコードである。Option型とは、「値が存在しない可能性があるデータ」を表現するための型である。
最近普及期に入ってきた型システムがリッチな言語(Scala、F#、OCaml、Haskell等)では当たり前に利用できる。
要は「nullの代わりに使いましょう」という型なのだが、nullのと大きな違いは、型安全である(「いわゆるnullチェック」にあたるコードを書かないとコンパイルすら通らない)という利点がある。nullを許容する場合だと、nullチェックを書かなくてもコンパイルが通ってしまうため、ケアレスミスによるバグが混在してしまう可能性がある。
蛇足ではあるが、リッチな型システムを使うメリットは「計算機がチェックできる範囲を広げることで、人間が楽をできる」ことであるので、食わず嫌いをして使わないのは勿体がない。
Haxeでnullを使わざるをえないところ
大きく2つある。
1. デフォルト引数
Haxeは関数やメソッドにデフォルト引数が設定できるのだが、デフォルト引数にOption型を指定することができない。そのため、どうしても次のような定義を書かざるをえないことがある。
function foo(option: String = null): Void { ... }
2. 環境依存や外部ライブラリを利用するケース
JavaScriptでDOMやjQueryなどを扱わなければならない場合に多発する。
var elem = js.Browser.document.querySelector("#hoge");
// valueにはnullが入る可能性 function setProperty(name: String, value: String): Void { var node = new JQuery("#hoge"); node.prop(name, value); }
これらの他にも、コールバック関数で受け取る値がnullというようなケースも多々ある。
ちょっとした工夫をする
まず次のようなHelperを作成する。ScalaのOption型まんまである。
class OptionHelper { public static function create<T>(x: T): Option<T> { return (x != null) ? Some(x) : None; } public static function getOrElse<T>(a: Option<T>, b: T): T { return switch (a) { case Some(x): x; case None: b; } } }
これだけあれば、結構いける。どうしてもコーディング規約的なものになってしまうが、無いものは仕方がない。
function foo(rawOption: String = null): Void { var option = OptionHelper.create(rawOption); ... }
using OptionHelper; //using mixin function setProperty(name: String, value: Option<String>): Void { var node = new JQuery("#hoge"); node.prop(name, value.getOrElse("")); }
OptionHelperにmap()等のメソッドを追加すると更に便利である。本当はこのあたりを全て標準ライブラリで用意してもらいたい…。
Windows用のPostgreSQL 9.3でUUIDを使えるようにする
シーケンスの代わりにuuidをIDとして使う | Siguniang's Blogを見ながら必要なことだけをメモ。
UUIDを生成する
v1, v3, v4, v5が使えるらしいけど、実質v1とv4ぐらいしか使わないよね。
select uuid_generate_v1(); select uuid_generate_v4();
UUIDをプライマリキーにしたテーブルを作る
CREATE TABLE sample ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), value text )