時計を壊せ

駆け出してからそこそこ経ったWebプログラマーの雑記

YAPC::Asia 2015でうっかりをなくす技術について発表しました

スライドはこちらになります。

www.slideshare.net

まとめていただきました!

うっかりを潰せ!Perlに見る「やらかし防止」 #yapcasia #yapcasiaC - Togetterまとめ

YAPC::Asia Tokyo 2015 1日目レポート[更新中]:YAPC::Asia Tokyo 2015 スペシャルレポート|gihyo.jp … 技術評論社

200人〜300人くらい入る部屋が満員御礼で立ち見も出る程の方々にお越しいただきました。

緊張してしまってうまく話せなかった部分や、時間配分を間違えてしまって最後のあたりが駆け足になってしまいましたが、 会場の雰囲気やまとめなどを見る限り、伝えたかったことは伝えられたかと思います。 裏番組が非常に魅力的な中で、あえてぼくのトークを聴きにきて頂きまして、本当にありがとうございました!

よかったら、ベストトーク賞の投票もおねがいします :)

yapcasia.org

宣伝

Gotanda.pm #6やります!

gotanda-pm.connpass.com

Perlからmrubyの関数を呼び出せるようになりました

mRuby.pmにmrubyの任意の関数を呼び出すインターフェースを追加しました。バージョン0.08としてリリースしています。

Perlのデータを引数として渡してmrubyの世界で扱い、mrubyの世界の値を返してPerlから使うことができます。 mrubyからPerlにデータを渡すことは今までのmRuby.pmでも可能でしたが、Perlからmrubyにデータを渡すことは0.08から新しくサポートしました。

つまり、以下のようなコードが動きます。

use mRuby;

my $mruby = mRuby->new(src => <<'...');
def add(l, r)
    l + r
end
...
my $ret = $mruby->funcall(add => 1, 2) + 3 + $mruby->funcall(add => 4, 5); # => 15

これによって、iOS/AndroidアプリとPerlのWeb APIで共通となるロジックや設定をmrubyで書き、 動的にロジックや設定を更新し適用するといったことが可能となります。

ぜひ、使ってみてください :)

宣伝

今週水曜日(2015/06/24)はGotanda.pm #5です!ぜひきてください!

gotanda.pm.org

宣伝2

YAPC::Asia 2015にトークをsubmitしています。良かったら+1してください!

追記: acceptされました!ぜひ見にきてください!

yapcasia.org

Cartonで不要になったモジュールをcpanfile.snapshotから削除したい

こうすることで消せた:

rm -rf local
carton install --deployment
carton install

なんか良い方法ないかなー。

追記: 2015-06-11 17:03

CIでcpanfile.snapshotを生成すれば解決しそう

参考: www.songmu.jp

GeoHex v3のC99実装ができた

掲題の通り。詳しくはREADMEを読んでみて欲しい。 karupanerura/c-geohex3 · GitHub

GeoHexとは何なのかと言うと世界を六角形により分割するためのアルゴリズムだ。 サイバーでかっこいいデモが公開されている。 デモサイト: GEOHEX.net

幾つかインターフェースや名前や実装方法を変更しているが、基本的にはJavaScriptにより実装された原始コードの移植と言って差し支えない。 元コードとアルゴリズムはMITライセンスで提供されており、本コードもMITライセンスで提供している。

現状で提供されているテストケースは全てパスしており、 以下のようなコードが動く。

#include <geohex3.h>
#include <stdio.h>

int main (int argc, char *argv[]) {
  for (int i = 1; i < argc; i++) {
    printf("/********* geohex:%s **********/\n", argv[i]);
    const geohex_verify_result_t result = geohex_verify_code(argv[i]);
    switch (result) {
      case GEOHEX3_VERIFY_RESULT_SUCCESS:
        {
          const geohex_t geohex = geohex_get_zone_by_code(argv[i]);
          printf("code  = %s\n", geohex.code);
          printf("level = %zu\n", geohex.level);
          printf("size  = %Lf\n", geohex.size);
          printf("[location]\n");
          printf("lat = %Lf\n", geohex.location.lat);
          printf("lng = %Lf\n", geohex.location.lng);
          printf("[coordinate]\n");
          printf("x = %ld\n", geohex.coordinate.x);
          printf("y = %ld\n", geohex.coordinate.y);
        }
        break;
      case GEOHEX3_VERIFY_RESULT_INVALID_CODE:
        printf("code:%s is invalid.\n", argv[i]);
        break;
      case GEOHEX3_VERIFY_RESULT_INVALID_LEVEL:
        printf("code:%s is invalid level. MAX_LEVEL:%d\n", argv[i], GEOHEX_MAX_LEVEL);
        break;
    }
  }
}

せっかくなのでXSを使ってPerl Bindingを書いた。

Geo::Hex::V3::XS - GeoHex implementation with XS. (c-geohex3 Perl5 binding.) - metacpan.org

近いうちにSwiftのbindingも書くつもり。

宣伝

gotanda.pm.org

いますぐ応募!

宣伝2

yapcasia.org

聞きたい!という人はイイね!なりツイートなりお願いします!

npmに上がっていないブラウザ向けに書かれたJavaScriptをnode.jsから雑に使うの術

ブラウザ向けに書かれたJavaScriptだと、windowに対してexportしていて、nodeから使いにくくて困ることがある。 nodeでも動くようなpatchを書けばいいという話ではあるが、githubにコードが上がっていないとやりにくくてつらい。

そこで、適当なObjectをcontextにして、vmでぶん回すことで、雑に解決することができた。 以下はGeoHexというライブラリのJavaScriptの実装がwindow.GEOHEXにエクスポートする実装であったために困ったので雑に解決した例。

"use strict";

var http = require('http');
var co   = require('co');

var get = function (url) {
  return new Promise(function (resolve, error) {
    http.get(url, function (res) {
      res.setEncoding('utf8');

      var buf = "";
      res.on('data', function (chunk) {
        buf += chunk;
      });
      res.on('end', function (chunk) {
        resolve(buf);
      });
    }).on('error', error);
  });
};

var getGeoHex = co(function *() {
  var window = {};

  var vm = require('vm');
  vm.createContext(window);

  var body = yield get("http://geohex.net/src/script/hex_v3.2_core.js");
  vm.runInContext(body, window);

  return window.GEOHEX;
});

getGeoHexを、以下のようにyieldしてやるといいかんじにwindow.GEOHEXが取得できていることがわかる。

co(function *() {
  var GEOHEX = yield getGeoHex;
  cosole.log(GEOHEX);
});

雑だけど問題は解決できた。べんり。

このへんで使った: c-geohex3/dump.js at master · karupanerura/c-geohex3 · GitHub

Implicitly Unwrapped Optionalは基本的に使うべきではない

Swiftのはなしです。

Swiftは言語標準でOptionalが入っていて、Optionalを除く全てのデータ型はnilを表現できません。 その中で、特殊なOptionalとして、Implicitly Unwrapped Optionalと呼ばれるものがあります。 これは、勝手にunwrapしてくれるので普通のデータ型と同じようにアクセスできるけど、中身がnilだったらunwrapに失敗するので死ぬという、特殊なOptionalです。 つまり、こいつを使うと、Optionalがせっかく解決してくれているはずの「ぬるぽリスク」が再び我々の目の前に現れることになり、つらい思いをすることになります。 どうしても使わなければならない場面でなければ、普通のOptionalを利用するべきです。

しかし、アクセスするタイミングでは「絶対に」nil にならないんだけど、一時的にnilになり得る場合がある。といったケースもあると思います。 具体的にはUIViewControllerdidViewLoadedで初期化するケースなどです。 そういったケースでは、(無理やりnilを代入して初期化するといったことをしていない限り、)Implicitly Unwrapped Optional による「ぬるぽリスク」も少ないのである程度安心して利用できます。

  • どうしてもnilの代入は裂けられないのか?
  • どうしても初期化でnil以外の値を入れることはできないのか?
    • せめて、初期化のタイミングでnil以外の値がくることを保証できないか?
    • e.g.) NG: let timeZone: NSTimeZone! = NSTimeZone(name: "Asia/Tokyo")
    • e.g.) OK: let timeZone: NSTimeZone? = NSTimeZone(name: "Asia/Tokyo")
    • e.g.) OK: let timeZone: NSTimeZone = NSTimeZone(name: "Asia/Tokyo")!
  • nilのタイミングでは絶対にアクセスしないか?

というあたりにすべてYESと答えられない限り、Implicitly Unwrapped Optionalは使うべきでないです。 やすやすと手をだすと忘れた頃に痛い目を見ることになるでしょう。

現場からは以上です。