読者です 読者をやめる 読者になる 読者になる

ギークハウスと海外とプログラミング

この記事はギークハウス Advent Calendar 2016 15日目の記事です。

はじめに

f:id:mi_kami:20161214224411p:plain

(2012年: 今は無くなったギークハウス武蔵小杉でやったUnityの勉強会)

ギークハウスのことを知ったのは2012年の5月くらいなのでもう5年近く前になる。その時はSIerとして働き始めて3年目くらい、はてなとかでギークハウスという名前が流行り始めた頃で、元々プログラミングやらアニメやらゲームが好きだった僕はすぐに引っ越しを決めた。

そこから半年後くらいにギークハウス新丸子へ引っ越し、暫く住んでからフィリピンに3ヶ月英語留学し、1年程カナダでプログラマとして仕事、2016年の2月に日本に帰ってきて今はGengoでまたプログラマとして働いている。今はギークハウス元住吉に住んでいる。

僕の住んだ3つのギークハウスはどれも神奈川県の川崎市内にあって、お互いとても近い位置にある。一方で他の東京都内のギークハウスとは少し離れているので、少し独特だったのかもしれないな、と今となっては思う。自分の変化も兼ねて少し思い出を書き連ねてみる。

ギークハウスでの生活

f:id:mi_kami:20161214224431p:plain

(2012年: iPhoneを分解して自分達で液晶を交換したときの写真)

元々一人暮らしをしていたので家具を含めてほとんどの物を捨てて2012年の5月にギークハウス武蔵小杉に引っ越した。シェアハウスは初めてだった上、自分の個室も無かった。

この頃は人の入れ替わりが多々あって、初期のメンバーが抜けた頃に僕が入居したのだった。Kさんが自分で3Dプリンタを作ってたり、Yさんがミニ四駆をやり始めて毎回大会に出るようになって、Railsミニ四駆ギャラリーを作ったりしていた。

僕はと言うと、仕事と関係無く自分でUnityでゲームを作ったりしていた。初代iPadが出たときにOpenGLを使ってゲームを作るとか、Unityで適当なゲームを作ってストアに出したり、あとはコミケにもたまに出したりしていた。それと同時にUnityの勉強会を自分で開いて使い方を教えたり、グローバルゲームジャムの会場をギークハウス武蔵小杉で登録して主催したり、とにかく他の人みたいに何かをしないと、という気持ちがあったように思う。

あとは@gigirさんという人がいて、見かけるときは朝でも晩でも、家から駅まで歩いてるときもゲームをしていた。ゲーム自体のデザインとかアイデアはその人に聞くと良い答えが返ってきた。

フィリピンに行くまでの道のり

f:id:mi_kami:20161214224502p:plain

(2013年: 住人でミニ四駆の公式大会に初めて出て予選敗退したときの写真)

その頃はスカイプの英会話とかフィリピン留学が流行り始めた頃だった。ギークハウス界隈ではゆる飲みと称して家でパーティをするのだが、その頃はそこでやたらフィリピンの英会話学校に行った話を聞く機会があった。「3ヶ月行って費用が30万くらい」だとか「一日8時間英語勉強しました」とかネットで調べて得られる情報ではなく、実際に行った人と話ができたのは大きかった。

同時に、ギークハウス元住吉に出資していた人がフィリピンに永住する話が出たりだとか、前に新丸子に住んでた人がSkype英会話のLangrich起業したとか、今現在ギークハウス元住吉に泊まってるでーきさんからもフィリピンの語学学校行って、マニラでRailsインターンしてる、みたいな話を聞いた。

ああ、自分は何もしてないなあ、と思った。普通に生活してたらSIerとして普通に生活することに何も感じなかったと思うけど、当時はそんな環境に身を置いていたので危機感を感じていた。それと同時に「旅と執筆とプログラミング」という翻訳記事を読んで、海外に行ってプログラミングすることに対して一種の憧れもあった。

その頃に影響を受けた人はたくさんいるけど、あえて言うなら西嶋くんだと思う。ギークハウス新丸子にふらっと遊びに行った時、スカイプか何かで英語でプログラミングの話をしていたのをよく覚えている。僕より年下のRailsエンジニアだったが、僕にとってロールモデルのような存在となった。僕がギークハウス新丸子に引っ越す前に、アメリカに行くことが決まってPivotalで今も働いていると思う。その西嶋くんも1年くらいフィリピンの英会話学校に行ったと言っていた。

それもあってフィリピンに行くことに決めた。

フィリピン

f:id:mi_kami:20161214224539p:plain

(2014年: フィリピンのセブにある英語学校)

1年半くらい準備してから仕事をやめたが、大して危機感は無かった。というのも、家にもニートがいたのでやっと同じ土俵に立ったな、という感じだった。数週間後にフィリピンのセブ島に飛び立った。

フィリピンでの生活は人生の中で一番楽しかったと思う。朝8時から夜10時まで英語の勉強をして、週末は旅行したりショッピングモールに行って過ごした。フィリピンに行く前に2年くらいスカイプで英会話をやったり準備はしていたけど、やっぱり学校で集中的に英語を勉強しているときが一番英語が伸びたと思う。スパルタコースだったので勉強時間も長いし、周りもやっぱり勉強している人が多かった。

f:id:mi_kami:20161214224557p:plain

(2014年: Pecha Kucha Nightのイベントの後に撮った写真)

あとは最後にセブのPecha Kucha Nightって言うイベントに出てギークハウスの生活を紹介した。これは学校は関係なく、勝手に申し込んだ。50人くらいの前で5分くらい英語でプレゼンしたんだけど、割とウケは良かったと思う。ギークハウスに住んで無かったら話すネタなんてなかったという意味でも、非常にギークハウスに感謝している。

プレゼンの後はたくさんの人に話しかけて貰えた。そこでPythonプログラマに会って後日一緒にコーヒー飲みに行ったりもした。

カナダ

f:id:mi_kami:20161214224622p:plain

(2014年: カナダ トロントコワーキングスペース)

元々はフィリピンに行って帰るだけの予定だったのだが、フィリピンで会った友達がみんなしてオーストラリアやらカナダやらに行くと言うので気になって自分も調べることにした。そもそも、これだけ英語勉強したのにまた日本に帰って同じように生活するのは単純に嫌だった。

どうやらカナダのワーホリビザなら何の制限もなくプログラマとして働けそうと言うことが判明したので行くことに決めた。2ヶ月くらい英語学校に行った後、履歴書を書いて面接をたくさん受けて(そしてたくさん落ちて)、最終的にフロントエンドの仕事が決まった。カナダの面接の好きなところは、志望動機を詳細に聞いてこないことと、紙/ホワイトボードに書いたコードで評価されることだった。

カナダでの生活はとてもシンプルですっきりしていて好きだった。仕事はみんな5時くらいには終わらせて帰るし、用事があれば平気で3時くらいでも帰る。アニメが好きなカナダ人と一緒に住んでいたので、家ではだいたいアニメを見るか海外ドラマを見て過ごしていた。

帰国、そしてまたギークハウスへ

f:id:mi_kami:20161214224635p:plain

(2016年: 現在のギークハウス元住吉のもくもく部屋)

カナダの仕事を辞めた後、メキシコとキューバを旅行して2016年の2月半ばに日本に戻ってきた。帰国して仕事を探していたが、たくさん面接を受けて最終的にGengoで働けることになったので5月から働いている。社内ではだいたい英語使って生活してコードも書いているのでとても満足している。

そして今はギークハウス元住吉に住んでいる。新丸子に住んでいたときに割と遊びに来ていたので元々知っている人もいたのが理由の1つだ。帰国してから、元々一緒に住んでいた人たちとご飯を食べに行ったりもした。こういう人との繋がりを保てるのもギークハウスの良い所だと思う。ギークハウスに入居する前は、仕事と学校以外の人と定期的に会うなんてことはほとんど無かった。

自分の変化とギークハウス

f:id:mi_kami:20161214224748p:plain

(2016年: 旧元住吉の住民が作ったギークハウス京都東福寺に遊びに行った時)

ギークハウスに住んでいなかったらどうなってたんだろう?と今では思う。フィリピンにも行かなかったし、カナダにも行かなかったし、今の仕事もしていなかった。ギークハウスのコミュニティを通して知り合ったたくさんのプログラマと会うこともなかった。仕事を辞めて海外に行くなんて普通の日本のコミュニティにいたら反対されるけど、僕の住んでいたギークハウスに似たような価値観を持っている人がいたから行く勇気を持てたのだと思う。この文章はMacBook Airに入れたLinux Mintで書いているけど、住人のサポートが無かったら入れることも無かったかもしれない。

ギークハウスに住む人も入れ替わっているし、ギークハウスにもそれぞれ個性があるし、その中でもそれぞれ違う考えを持った人がいるので今から住んでも同じような体験はしないと思う。それでも、住んでみたら今から起こるかもしれない何かを体験することになるかもしれない。有限な時間の中で、そこに住むだけで何か新しいものを得られる可能性があるのなら、そこに住む意味はあると思う。

PS. 関西圏に住んでる人がいたらギークハウス京都東福寺おすすめです。

Firefox OSをビルドしてZTE Openに書き込んだけど起動しない場合の対処法

ZTE Open(inari)用にFirefox OSを自分でビルドして、flash.shの実行時に以下のようなエラーが出る場合、/out/target/product/inari/配下にboot.imgが無い可能性がある。

mikamikuh@mikaubuntu:~/project/firefox/B2G$ sudo ./flash.sh
< waiting for device >
erasing 'cache'...
...
finished. total time: 0.002s
Attempting to set the time on the device
time 1392659912 -> 1392659912.0
settimeofday failed Bad file number

その場合、以下のサイトからboot.imgをダウンロードする。

* https://mega.co.nz/#!uJ52xZJa!M_YwAEXRwifN21QmQbHgNCcEc5Ml2CKw57IBGxnvdm4

ダウンロードしたファイルをboot.imgにリネームし、先程のパスに配置する。
あとは./flash.shを実行し、以下のようになればおそらくFirefox OSが起動する。

mikamikuh@mikaubuntu:~/project/firefox/B2G$ sudo ./flash.sh
< waiting for device >
erasing 'cache'...
...
finished. total time: 0.002s
Attempting to set the time on the device
time 1392659912 -> 1392659912.0
settimeofday failed Bad file number

Ubuntu13.10でFirefox OS端末をadbに認識させる方法

ZTEのFirefox OS端末を入手した。早速Ubuntu13.10上でOSをビルドをして最新のFirefox OSを試そうと思ったのだが、adbがデバイスを認識してくれない。

$ adb devices
List of devices attached 
????????????	no permissions

上記のように正しく認識されていない場合、ビルドが実行できない。adb用のudev設定を正しく実施する必要がある。

端末のベンダIDを調べる

Firefox OSの端末のベンダIDが必要になる為、lsusbコマンドを使ってそれを調べる。以下の例の場合、19d2がベンダIDとなる。

mikamikuh@mikaubuntu:~/project/firefox/B2G$ lsusb
...
Bus 003 Device 073: ID 19d2:1350 ZTE WCDMA Technologies MSM
...

udev rulesの作成

次に、以下のパスにrulesファイルを作成する。

  • /etc/udev/rules.d/51-android.rules

内容は以下のようにする。"19d2"の部分は使用する端末のベンダIDに置き換える。

SUBSYSTEM=="usb", ATTR{idVendor}=="19d2" MODE="0666" GROUP="plugdev"

udev rulesとは(補足)

udevはLinuxカーネル2.6.13以降に搭載されている/dev以下のデバイスを管理する為のツールである。
新しくデバイスが認識されると、/etc/udev/rules.d/に書かれているルールを辞書順に解析し、最初に見つかったルールを適用する。
51-android.rulesと50-hogehoge.rulesの2つのファイルがあった場合、50-hogehoge.rulesが先に評価される。

- (参考) http://www.gentoo.gr.jp/transdocs/udevrules/udevrules.html

動作確認

これで端末が認識されるようになった。

mikamikuh@mikaubuntu:~/project/firefox/B2G$ sudo service udev restart
mikamikuh@mikaubuntu:~/project/firefox/B2G$ adb devices
List of devices attached 
roamer2	device

Clojureで日付を扱う(clj-time)

clj-timeとは

Clojureで日時を扱う為にはclj-timeを使うと良い。これはJavaJodaTimeのラッパーで、イミュータブルでスレッドセーフなのでClojureからも安全に利用できる。
以下に書いてあることは基本的に上記のgithubのREADME.mdにすべて書いてある。

DateTimeオブジェクトを作る

date-time

DateTimeは時間まで指定してオブジェクトを作ることもできるし、日付だけ指定して作ることもできる。

時分秒まで指定
(date-time 1986 10 13 11 24 30)       
=> #<DateTime 1986-10-13T11:24:30.000Z>
日時まで指定
(date-time 1986 10 13)
=> #<DateTime 1986-10-13T00:00:00.000Z>

hour

DateTimeオブジェクトから時だけを取得する。同様にmonth, day, minute関数も存在する。

(day (date-time 1986 10 13 11 24 30))   
=> 13
(hour (date-time 1986 10 13 11 24 30))
=> 11
(minute (date-time 1986 10 13 11 24 30)) 
=> 24

タイムゾーンを指定する

date-time関数のコンストラクタはデフォルトでUTCタイムゾーンを返す。

from-time-zone

第1引数のDateTimeオブジェクトに対して、第2引数のタイムゾーンを設定したDateTimeオブジェクトを返す。

(from-time-zone (date-time 2013 4 1) (time-zone-for-offset +9))
=> #<DateTime 2013-04-01T00:00:00.000+09:00>

to-time-zone

第1引数のDateTimeオブジェクトに対して、第2引数のタイムゾーンを設定し、時差を計算してその時間を設定したDateTimeオブジェクトを返す。

(def time1 (from-time-zone (date-time 2013 4 1) (time-zone-for-offset +9)))
=> #'clj-time.core/time1
(to-time-zone time1 (time-zone-for-offset 0))  
=> #<DateTime 2013-03-31T15:00:00.000Z> # -9(+90の時差)された日時が入る
(to-time-zone time1 (time-zone-for-offset +10))
=> #<DateTime 2013-04-01T01:00:00.000+10:00> # +1(+9と+10の時差)された日時が入る

time-zone-for-id

タイムゾーンの指定にはtime-zone-for-offsetで時差を直接入力する以外に、タイムゾーンのIDを入力することでも指定出来る。

(to-time-zone (date-time 2013 4 1) (time-zone-for-id "Asia/Tokyo"))
=> #<DateTime 2013-04-01T09:00:00.000+09:00>

日付だけを扱う

local-date

時間を使わず、日付だけを操作したい場合はlocal-dateを使う。

(local-date 2013 10 1)
=> #<LocalDate 2013-10-01>

日時のチェック

after?関数は次の要素かどうかのチェック、before?関数は前の要素かどうかをチェックする。
これらはlocal-dateだけでなく、date-timeからでも利用出来る。また、date-timeは月まで、日まで、時間までを指定されたオブジェクトそれぞれに対してチェックの関数を使える。

次の月か?

(after? (date-time 2013 10) (date-time 2013 9)) 
=> true

次の日か?

(after? (date-time 2013 10 2) (date-time 2013 10 1))
=> true

次の時間か?

(after? (date-time 2013 10 2 10) (date-time 2013 10 2 9))
=> true

日時の演算

加算

(plus (date-time 2013 8 14) (months 3) (weeks 1))
=> #<DateTime 2013-11-21T00:00:00.000Z>

減算

(minus (date-time 2013 8 14) (months 3) (weeks 1))
=> #<DateTime 2013-05-07T00:00:00.000Z>

フォーマット

文字列をDateTimeに変換する場合、DateTimeを文字列に変換する場合はclj-time.formatを使う。

フォーマッタを作る

(def custom-formatter (formatter "yyyyMMdd"))
=> #'clj-time.core/custom-formatter

parseとunparse

(parse custom-formatter "20100311")                   
=> #<DateTime 2010-03-11T00:00:00.000Z>
(unparse custom-formatter (date-time 2010 10 3))
=> "20101003"

デフォルトで用意されたフォーマッタを使う

(def built-in-formatter (formatters :basic-date-time))
=> #'clj-time.core/built-in-formatter
(unparse built-in-formatter (date-time 2010 10 3))

マレーシアで開発合宿がしたい!

来週の火曜日からギークハウスのメンバー6人くらいでマレーシア旅行に行ってくる。もともとは開発合宿という名目だったのだが人が集まらなくて普通の旅行になった。とはいえ、本当に開発合宿やったら面白そうなので行く前に調べたことをまとめておく。

飛行機

f:id:mi_kami:20130707001107j:plain,w300
半年くらい前にやっていたAirAsiaのセールで往復2万前後でチケットを取れたらしい。僕は少しチケットを取るのが遅れたので往復3万くらいかかっているが、それでも3万なら十分に安い。空港も羽田からなので成田ほど時間も交通費もかからない。

宿

f:id:mi_kami:20130707001224j:plain,w300
宿泊先はAirbnbで見つけた。Airbnbは人の家だったり部屋だったりを有料で貸し借りできるサービスだ。今回借りる事にしたのはマレーシアの首都クアラルンプールにあるアパート。ベッドルーム3つトイレ2つの広い部屋を1週間で30000円くらいで借りる。6人で行くので1人あたり実質6000円程度で抑えられる。

電源

f:id:mi_kami:20111120185300j:plain,w300
電圧については問題無さそうだが、コンセントの形状が違うので変換プラグを買う必要がある。日本で変換プラグを買うと高くつくが、マレーシアで買うと50円程度で購入できるらしいので散歩がてら買いに行こうと思っている。

ネット環境

f:id:mi_kami:20130707001530j:plain,w300
我々ギークやらプログラマーはネットがあると人並み以上のパフォーマンスを出せるのだが、それが無くなった途端に人並み以下になるという性質を持つ。なのでネット環境をどうするかというのは死活問題だ。
マレーシアではSIMカードを購入して、必要に応じてチャージしてネットをするのが一般的らしい。日本からマレーシアに行く場合、SIMフリーの端末を1台持って行き、SIMカードを買って500M分ほどチャージしておくと良いとのこと。500Mチャージしても900円程度に抑えられそうだ。
そうでもなくとも、マックに行けばフリーのWifi使えるし、普通のカフェでもフリーのWifiは使えそうな気がする。そして今回借りるアパートにはWifiが付いてるので家にいる間はネットは問題にならなそうだ。

コワーキングスペース

首都クアラルンプールには幾つかコワーキングスペースがあるらしい。このサイトでまとめられている。まだ調べ切れていないが、普通に気軽に立ち寄れそうなところを探して遊びに行こうと思っている。
ただ、コワーキングスペースにかかるお金は1日1000円前後とあまり日本とあまり変わらなそうだ。

その他

治安もそれほど悪く無く、バトゥ洞窟とか国立公園のような観光施設もあるし、大型の商業施設もありそうだ。トリップアドバイザーを眺めていれば面白そうな場所は簡単に見つけられる。ご飯も日本円で50円くらいで外食出来るとのことだし、ホントに1ヶ月くらいマレーシア行って開発合宿するのも面白そう。本当に出来そうかどうか、帰ってきたらまとめてみる。

Clojureのバイトコード

Clojureを実行するときって、どういうバイトコードになっているんだろう?

クラスファイルを作る

まず、クラスファイルを出力するために:gen-classを付加する。

(ns clj.core
  (:gen-class))

(defn fuga [x y]
  (+ x y))

(defn hoge []
  (fuga 10 20))
 $ cd [project]
 $ lein compile


これで.classファイルがclassフォルダ配下に作成される。

作成されたクラスファイル

 $ ls
core$fn__50.class			core$loading__4910__auto__.class
core$fuga.class				core.class
core$hoge.class				core__init.class


って作られすぎだろ...。関数毎にクラスファイルが作られているようだ。中身もごちゃごちゃしててどうなってるのかさっぱりだ。困った。

JVMの関数はどのようにして呼び出されるか

関数が起動するとフレームというものが作成される。このフレームは、関数が終了したとき(正常リターン、例外に関わらず)破棄される。このフレームは以下の3つを持つ。

  • ローカル変数
  • オペランド・スタック
  • コンスタント・プール

関数hogeはint型の引数を3つを取り、その合計を返す。関数mainはその結果を標準出力に出良くする。

public class Switch {
	public static void main(String[] args) {
		int n = hoge(2, 4, 5);
		System.out.println(n);
	}
	
	public static int hoge(int a, int b, int c) {
		return a + b + c;
	}
}

これをコンパイルすると以下のバイトコードが得られる。

public static void main(java.lang.String[]);
  Code:
   0:	iconst_2
   1:	iconst_4
   2:	iconst_5
   3:	invokestatic	#16; //Method hoge:(III)I
   6:	istore_1
   7:	getstatic	#20; //Field java/lang/System.out:Ljava/io/PrintStream;
   10:	iload_1
   11:	invokevirtual	#26; //Method java/io/PrintStream.println:(I)V
   14:	return

public static int hoge(int, int, int);
  Code:
   0:	iload_0
   1:	iload_1
   2:	iadd
   3:	iload_2
   4:	iadd
   5:	ireturn


関数を呼び出す命令がinvokestaticだ。引数を渡すには、予めオペランドスタックと呼ばれるスタックに値を入れておき、その後でinvokestaticを呼び出す必要がある。
iconst_n命令はint型の値nをオペランドスタックに格納する命令だ。iconst_のnは-1〜5の範囲で利用出来るが、それ以上の値を格納する場合はbitpush 命令を使う。なお、floatの場合はfconst命令など、型によって別の命令を使う。

値の取り出しはiload_n命令を使う。この関数を呼び出した時にオペランドスタックに入っていた値は、新規フレーム作成時にローカル変数という領域に割り当てられる。このiload_n命令を使ってint型のローカル変数を読み出すことができる。これも型毎に命令が存在する。

戻り値は*return(int型の場合はireturn)を使う。これはカレントフレームのオペランドスタックに格納されている値をポップして、呼び出し元カレントフレームのオペランドスタックに格納する。上記の例の場合、4:のiadd命令はオペランドスタックから2つ値をポップし、その結果を再びオペランドスタックに格納する。なので5:でireturnを呼んだ時にその結果が呼び出し元のカレントフレームのオペランドスタックに格納される。