裏番組がすごいつよいので、負けないようにがんばります! もしよかったらきてください!
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です!ぜひきてください!
宣伝2
YAPC::Asia 2015にトークをsubmitしています。良かったら+1してください!
追記: acceptされました!ぜひ見にきてください!
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も書くつもり。
宣伝
いますぐ応募!
宣伝2
聞きたい!という人はイイね!なりツイートなりお願いします!
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
になり得る場合がある。といったケースもあると思います。
具体的にはUIViewController
のdidViewLoaded
で初期化するケースなどです。
そういったケースでは、(無理やり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は使うべきでないです。
やすやすと手をだすと忘れた頃に痛い目を見ることになるでしょう。
現場からは以上です。
Akka 2.4を雑にためす: その1
※ メモです
Scalaもくもく会に参加した。 Gitterでわいわいしながら自分のペースでもくもくできてよかった。
第1回 Scalaもくもく会@Volare - connpass
第2回 Scalaもくもく会@Volare - connpass
ぼくは、Actorが使ってみたくてScalaでAkkaをためしてみた。 ドキュメント長すぎて読むのに気力と体力が要求されたので、 とりあえずドキュメントを読まずにサンプルコードを書き換えてみるという、 非常にカジュアルな試しかたをした。
まずはbuild.sbtを書く。
lazy val root = (project in file(".")). settings( name := "tut", version := "1.0", scalaVersion := "2.11.6", libraryDependencies += "com.typesafe.akka" % "akka-actor_2.11" % "2.4-SNAPSHOT", libraryDependencies += "org.scalaj" %% "scalaj-http" % "1.1.4", resolvers += "Akka Snapshot Repository" at "http://repo.akka.io/snapshots/" )
雑に1秒遅れてEchoするActorを書く。
import akka.actor.{Actor,ActorSystem,Props} import akka.pattern.ask import akka.pattern.gracefulStop import akka.util.Timeout import scala.concurrent.Future import scala.concurrent.Await import scala.concurrent.duration._ class DelayEchoActor extends Actor { def receive = { case msg: String => Thread.sleep(1000) sender ! msg } } object HelloWorld { def main(args: Array[String]) = { var sys = ActorSystem("system") val echo = sys.actorOf(Props[DelayEchoActor]) implicit val timeout = Timeout(10 seconds) val futures = scala.collection.mutable.ArrayBuffer.empty[Future[Any]] futures += echo ? "あれ?" futures += echo ? "文字列が" futures += echo ? "遅れて" futures += echo ? "流れて" futures += echo ? "くるよ?" for (future <- futures.toArray) { val res = Await.result(future, timeout.duration) res match { case msg: String => println(msg) } } sys.shutdown() } }
動かしてみると、たしかに遅れて流れてくる。 では、並列に動かすには?
とりあえず、systemを複数作ってみる。ついでなのでHTTPでgoogleのトップページも雑に叩く。
import akka.actor.{Actor,ActorSystem,Props} import akka.pattern.ask import akka.pattern.gracefulStop import akka.util.Timeout import scala.concurrent.Future import scala.concurrent.Await import scala.concurrent.duration._ import scalaj.http._ import java.lang.Object class DelayEchoActor extends Actor { def receive = { case msg: String => import dispatch._, Defaults._ Thread.sleep(1000) sender ! msg } } class HttpGetRequestActor extends Actor { def receive = { case url: String => val response: HttpResponse[String] = Http(url).asString sender ! response } } object HelloWorld { def main(args: Array[String]) = { val echo1Sys = ActorSystem("echo1") val echo2Sys = ActorSystem("echo2") val http1Sys = ActorSystem("http1") val http2Sys = ActorSystem("http2") val echo1 = echo1Sys.actorOf(Props[DelayEchoActor]) val echo2 = echo2Sys.actorOf(Props[DelayEchoActor]) val http1 = http1Sys.actorOf(Props[HttpGetRequestActor]) val http2 = http2Sys.actorOf(Props[HttpGetRequestActor]) implicit val timeout = Timeout(10 seconds) val futures = scala.collection.mutable.ArrayBuffer.empty[Future[Any]] futures += echo1 ? "あれ?" futures += echo2 ? "文字列が" futures += echo1 ? "遅れて" futures += echo2 ? "流れて" futures += echo1 ? "くるよ?" futures += http1 ? "http://www.google.co.jp/" futures += http2 ? "http://www.google.co.jp/" for (future <- futures.toArray) { val res = Await.result(future, timeout.duration) res match { case response: HttpResponse[String] => println(response.body) case javaObject: Object => println(javaObject.toString()) } } } }
なるほど。並列に動く。
しかし、こんなめんどくさい感じなわけがないし、なんか、res
に変なのがくるし、おかしい。(とりあえずjava.lang.Object
で受けてtoStringするという漢らしいことをしている。)
コードを追ってみるとActorSystem -> LocalActorRef -> ActorCell -> Deployerという要素が見えてきたがキリが無いので諦めてドキュメントに目を移す。
ドキュメントを斜め読みする。ふむ。なんかconfigというのがあるらしい。
akka.actor.deployment
にnr-of-instances
というやつがいる。これか?
となったところで、電池が切れそう。
結論
ドキュメント読んでから使え。
支援
Vol.3もあるようです:
第3回 Scalaもくもく会@Volare - connpass
気が向いたらその2も書く。