werckerで既存のRailsプロジェクトを突っ込んだら結構ハマった話し
追記: 2014/03/23 Werckerにバグ報告したら直してくれた :)
最近はクラウドCIサービスでテスト回したりするのがどんどん普及していますね。 TravisCIやCircleCIやCodeShipなどなど。。。 その中でプライベート・リポジトリでも現在は無料で使えるWerckerがどんどん注目を集めていると感じます。
そんな訳で、色々なWercker始めようぜ!って記事を参考に、GitHubにある既存のRailsプロジェクトがPushされたりしたらWercker上でTurnipとRspecが走るところまでやってみました。
が、、、超絶ハマった!!!
Gemのバージョンが古いとhoge.soが見つからないと怒られる
$ bundle exec rake db:schema:load RAILS_ENV=test rake aborted! libruby.so.2.0: cannot open shared object file: No such file or directory - /cache/bundle-install/ruby/2.0.0/gems/rmagick-2.13.2/lib/RMagick2.so
ひたすらこんなエラーがでる。 で、これはまぁRMagickなんでまた別件なんですけど、エラーがでるgemのバージョンが古かったら、gemによってはこのエラーがでる。 でないgemもあった。 pgとかは0.17.1にUPしたら動いたけど、最初入れてたバージョンだと古くて↑のようなエラーが出ましたね。
取り敢えずgemのアップデートをしたら問題なく動きましたよっと。
どう頑張ってもRMagickは使えなかった
$ bundle exec rake db:schema:load RAILS_ENV=test rake aborted! libruby.so.2.0: cannot open shared object file: No such file or directory - /cache/bundle-install/ruby/2.0.0/gems/rmagick-2.13.2/lib/RMagick2.so
rmagickは2.13.2が最新なんだけど、どう頑張っても出来なかった。 ただgemを入れているだけなら問題ないんだけど、carrierwaveで生成したuploaderで
include CarrierWave::RMagick
ってしていて、これがあるとどうしても↑のエラーがでる。
で、結局rmagickの使用を辞めてminimagickにしました。 これだと問題なくwerckerエラー吐かなかった(´・ω・`)
結論
- ちゃんとgemのアップデートしましょう
- rmagickはなんか使えなかった
誰か「それはお前の使い方が悪いんじゃボケ」とかあったら教えて下さいませ。
実用CommonLisp -第二章読了-
PAIP2章読了しました。 二日酔いで死んでいたので2日ほど空いてしまった。 生活リズム崩れまくって、今日は徹夜して一気に戻す作戦なので眠い目を擦りながら朝5時くらいからPAIPってた。
2章はDSL書きましょうって内容でした。 うーん面白い。
第2章 簡単なLispプログラム
2.1 英語のサブセット用文法
2章では任意の英文を生成するプログラムを書く。 英語のごく小さなサブセット用の簡単な文法が示される。
文 => 名詞句 + 動詞句 名詞句 => 冠詞 + 名詞 動詞句 => 動詞 + 名詞句 冠詞 => the, a, ... 名詞 => man, ball, woman, table, ... 動詞 => hit, book, saw, liked, ...
この記述は、技術的には文脈自由な句構造文法(context-free phase-structure grammar)と呼ばれる。 基礎となるパラダイムは生成統語論(generative syntax)と呼ばれる。 この文法は次のように理解すれば良い。 文(Sentence)を生成したい場合は、名詞句(Noun-Phrase)と動詞句(Verb-Phrase)を生成できる。 名詞句が特定された場合は、その代わりに冠詞(Article)と名詞句を生成する。 冠詞が特定された場合はthe, a, またはその他の冠詞を生成する。 取り囲んでいる単語にかかわらず、どの部分にも規則を適用するので、形式論としては「文脈自由」である。 規則が全体としてある言語の分の完全な集合と、その上に非文の完全な集合を定義しているので、考え方は「生成的」である。 この規則を使用して単一の文を導出してみよう。
2.2 成功法による解法
句構造文法を使用して任意の文を生成するプログラムを開発する。 成功法は、各々の文法規則を別のLisp関数によって表現することである。
(defun sentence () "文" (append (noun-phrase) (verb-phrase))) (defun noun-phrase () "名詞句" (append (Article) (Noun))) (defun verb-phrase () "動詞句" (append (Verb) (noun-phrase))) (defun Article () "冠詞" (one-of '(the a))) (defun Noun () "名詞" (one-of '(man ball woman table))) (defun Verb () "動詞" (one-of '(hit took saw liked))) (defun one-of (set) "Pick one element of set, and make a list of it." (list (random-elt set))) (defun random-elt (choices) "Choose an element from a list at rondom." (elt choices (random (length choices))))
プログラムは問題なく実行される。 しかしLispによる定義はオリジナルの文法規則よりも読みづらい。 さらに複雑な文法規則を扱う場合に、この問題が自体を悪化させる
名詞句 => 冠詞 + Adj* + 名詞 + PP* Adj* => Φ, Adj + Adj* PP* => Φ, PP + PP* PP(前置詞句) => Prep + 名詞句 Adj(形容詞) => big, little, blue, green, ... Prep => to, in, by, with, ...
この表記法で、Φ は空の選択を示す。カンマはいくつかの選択肢があることを示す。 アスタリスクは特異なものではなく、Lispで紹介したものと同様にシンボル名の一部である。 PP*はPPが0回以上繰り返すことを示す。 これは数学者Stephen Cole Kleeneの名をとって「Kleen star」(clean-Eと発音する)表記法と呼ばれる。 アスタリスクで終わる名前は、アスタリスクが付かない元の名前が0回以上繰り返されることを表している。
(defun Adj* () (if (= (random 2) 0) nil (append (Adj) (Adj*)))) (defun PP* () (if (random-elt '(t nil)) (append (PP) (PP*)) nil)) (defun noun-phrase () (append (Article) (Adj*) (Noun) (PP*))) (defun PP () (append (Prep) (noun-phrase))) (defun Adj () (one-of '(big little blue green adiabatic))) (defun Prep () (one-of '(to in by with on)))
重要な点は、最初は単純な関数だったものが、今ではかなり複雑になっていることである。 理解するためにはdefun,(),case,if,quote,評価の順序などのLispの規則を知る必要がある。 文法規則の実装は、理想的には言語学の規則だけを使うべきだ。 大きな文法を開発する場合は、問題はさらに悪化して、文法を記述する人はますますLispに依存しなくてはならない。
2.3 ルールベースによる解法
プログラムを実装する上での代替え案は、文法規則を書きやすくすることに集中して、それらを処理する方法は後で考えることである。 オリジナルの規則を見てみよう。
文 => 名詞句 + 動詞句 名詞句 => 冠詞 + 名詞 動詞句 => 動詞 + 名詞句 冠詞 => the, a, ... 名詞 => man, ball, woman, table, ... 動詞 => hit, book, saw, liked, ...
各規則は、左辺部の1つのシンボル、矢印、右辺部から構成される。 面倒なことには、右辺部が2種類あることである。すなわり、名詞句 → 冠詞+名詞のように連結されたリストの場合と、名詞 → mann, ball, ...のように選択可能な単語のリストの場合である。 これに対応するには、全ての規則が右辺部に可能性のあるもののリストを持てば良い。 例えば、連結されたリスト「冠詞+名詞」は(Article Noun)のようなLispのリストで表せる。 したがって、規則のリストは次のように表せ、ルールベースによる関数はこうなる。
(defparameter *simple-grammar* '((sentence -> (noun-phrase verb-phrase)) (noun-phrase -> (Article Noun)) (verb-phrase -> (Verb noun-phrase)) (Article -> the a) (Noun -> man ball woman table) (Verb -> hit took saw liked)) "grammar:文法 / A grammar for a trivial subset of English.") (defvar *grammar* *simple-grammar* "The grammar userd by generate. Initially, this is *simple-grammar*, but we can switch to other grammars.") (defun rule-lhs (rule) "規則の左辺部を取得する" (first rule)) (defun rule-rhs (rule) "規則の右辺部を取得する" (rest (rest rule))) (defun rewrites (category) "ある文法カテゴリに対する書き換え(右辺部)の全てを調べる" (rule-rhs (assoc category *grammar*))) (defun mappend (fn the-list) "Apply fn to each element of list add append the results." (apply #'append (mapcar fn the-list))) (defun generate (phrase) "Generate a random sentence or phrase." (cond ((listp phrase) (mappend #'generate phrase)) ((rewrites phrase) (generate (random-elt (rewrites phrase)))) (t (list phrase))))
2.4 進むべき2つの道
結論としてはルールベース(今風でいうとDSL)のほうがいいよ。
ルールベースの考え方は、余分なステップを踏むので小さい問題に対しては仕事量が大きくなるけれど、多くの場合、修正や拡張が容易になる。 AIの問題のほとんどはこの記述が適している。
この章の感想
この章では英文の生成プログラムを2つの方法で作成し、DSLは小さい問題では仕事量は増えるが、拡張性・修正容易性・ドメインの規則だけを使ってプログラムを記述できる、などの良さを伝えている。
この章で特に印象的だったのは2.2節の
重要な点は、最初は単純な関数だったものが、今ではかなり複雑になっていることである。 理解するためにはdefun,(),case,if,quote,評価の順序などのLispの規則を知る必要がある。 文法規則の実装は、理想的には言語学の規則だけを使うべきだ。 大きな文法を開発する場合は、問題はさらに悪化して、文法を記述する人はますますLispに依存しなくてはならない。
という部分です。 プログラミングやソフトウェア開発を学ぶ本で、「その言語に依存することは問題である」と言い切っている本は中々ないのではないでしょうか?
AIという分野が題材とはいえ、これは最近の「特定の言語を深く知っている俺って凄い」みたいな(一部の人達の)風潮に疑問を感じていた僕にとっては、なんだかとっても賛同したくなる一文でした.
実用CommonLisp -第一章読了-
仕事もようやく落ち着き、勉強の時間がとれるようになったので第6章までしかやってなかった(と思う)実用CommonLispを最初から勉強し直し初めた。 LISPをまともに触るのは久々で、組み込み関数を結構忘れている(汗
でも、暇な時とか煮詰まった時にCLでフィボナッチやアッカーマン関数等を書いて気持ちを切り替える、ということを普段からやっていたのであまり苦労はしなかった。
第一章Lisp入門
nullとnil
読みなおしてみて気になったのは、null関数と値nilだったりした。 あれ、nullとnilって何違うんだっけ???と。 別途こちらの記事に書いた。
pと?
あとは関数定義の際のシンボルで?が使えるんだが、CLでは?の代わりにpを使う(組み込み関数numberpなど)。 あれ、?使えるのにp使うのなんでだっけ???
ドキュメーテーション文字列
ドキュメーテーション文字列が可愛い!
(defun last-name (name) "Select the last name from a name represented as a list." (first (rest name)))
関数定義の中にコメントではなく、文字列として関数の説明を書けるのは好きだなー。
car,cdrはfirst,restの旧名
うーん、旧名って言われるとなんか凄い違和感ある。。。 原文はどうなってるんですかね?
car,cdrの正式名称
carとcdrはそれぞれcontents of the address registerとcontents of the decrement registerを表している。
おー、そうだったっけ。 この辺はかなり忘れていた。
lambdaの由来
P19にlambdaという名前が使われるようになった由来が書いてある。 豆知識として面白い。
スペシャル変数ってグローバル変数?
何か違うんだっけ? 後で調べる。
第一章感想
僅か17ページで変数への代入、関数定義、map、条件分岐、高階関数まで終わらせる。 最初に「プログラミング入門じゃなくてLISP入門」と書いているだけあって、いわゆるプログラミング入門書とは全然違う。 高階関数の後に文字列型でてくるしw
ただ、LISP入門書としてはかなり解りやすいし易しい内容だと思われる。 ただ、演習問題の解答にまだ出てきていない関数(cond, evenp, expt等)がいきなり出てくるのはどうかと思う。 「LISP入門」という章なんだから、演習問題では今まで説明したものだけを使うべきでは???
PeterNorvigさん、この章書いてる時に最後はつかれたのかなw
nullとnilの違い
実用CommonLispの以下のコードを書いていて、そういえばnullとnilの違いってなんぞや?って思い調べてみた。
(defun mappend (fn the-list) "Apply fn to each element of list and append the results." (if (null the-list nil (append (funcall fn (first the-list)) (mappend fn (rest the-list)))))
http://「NULL」と「NIL」の違いを教えてください。 どちらも「無い」みたい
両者は「品詞」が異なります。 どちらも「何もない」というような意味ですが、nullusは代名詞的形容詞といって他の名詞などを修飾するときに使います。(=英語の No news などの「no」に相当) nilは名詞「無」(=nothing)または副詞「決して...でない」(=never)といった使われ方をします。
へぇー!だからヌル判定はnullで値としてのヌルはnilなんだ。勉強になりました。
2013年振り返りと来年の抱負
2013年も残す所あと数日。 今年は色々あったので振り返っておく。
2013年振り返り
- 5月24日からフリーランスになってみた
- フリーランスとしての仕事で一杯一杯で、勉強会・技術書など全然出来なかった
- 仕事でインフラ周りを結構沢山やれた
- AWS
- Nginx
- Postgresql
- Unicorn
- フリーランスになってからずっとRails!!!
- サービスを無事に2個リリース出来た
- 企画とかも色々やったり、WebmasterToolsやAnalyticsとも仲良くなった
- エンジニアとしての技術力と、そのチームに合う・合わないは別(僕の技術力が高いとかいう意味ではなく)
- 円滑な人間関係大事
- 目標が共有できても、目標を達成するための手段やプロセスがメンバーでバラバラだと、チームが上手く動かない
- 各メンバーの能力がそれほど高くなくても、目標とプロセスの共有が上手く行われているチームだと、そのチームのほうが上手く行く
- 契約はちゃんと守ってくださいね(真顔)
- お金の問題は大人としてちゃんと対応しましょう
来年の抱負
ほーふ!
- 実用CommonLisp再開して終わらせる(この記事書き終わったらやるぞー)
- 勉強会にもそれなりに出る
- 実務と直接関係ない基礎技術を磨く(以下3冊を1年で終わらせられたらいいなー)
- 実務頑張る
さーて、clozure-clのインストール終わったからPAIPやりましょう。
PullRequestを早目にだしてみるメソッド
最近うちのチームで行なっているのが、PullRequestを
「取り敢えず動作はするけど、40%とか50%くらいの状態で早目に出す」
というメソッド。
早目にレビューしてもらうのが目的です。 これは元々チームメイトが以前からやっていたのを、僕らのチームでも導入した感じです。
よかったことにも書いてあるけど、うちのチームは一箇所に集まることが週に一回しか出来ないし、それぞれコードを書く時間が本当にバラバラでペアプロが出来ない。 そんな環境だと、ペアプロの代わりになると思っていて凄い良い。
よかったこと
- 早目にPRを出すことで根本的な間違いなどに早く気がつける
- まだ50%くらいなので、ドヤ顔で出したソースコードをボロクソに言われて凹む、というようなことがない
- 早い段階から色々と議論が出来るので、品質の良いものが出来る
- うちのチームは全員が一箇所に集まるのが週に1回くらいなので、ペアプロがあまり出来ない。だが、PRを早目に出してGitHub上で議論しながら進めることで、ペアプロ的な利点を取り入れる事ができる
よくなかったこと
- 今のところ特に思いつかないかも。
これ、エンジニアが凄い増えたら上手く回るのか解らないし、毎日同じ場所にエンジニアが集まれるならもしかして必要ないのかも? その辺は経験ないので解らない。
でも、取り敢えずうちの「少人数で作業場所・時間がバラバラ」という環境だと凄い上手く回っています。 そういう環境のチームにはおすすめです☆
2ヶ月くらい個人事業主生活をしてみた #継続中
よかったこと
- 出社しなくていい
- ずっと猫ともふもふできる
- ストレスから滅茶苦茶解放された
- 苦手だったフロント周りも(CoffeeScriptとか)結構触れるようになった
- 久々にインフラやったら意外と出来た
わるかったこと
- 人間と話す機会の減少
- 休日をまだ一回も取れてない
- 体調を結構崩しまくった
そうていがいだったこと
- 技術書読む時間すらとれない
- RoRばっかで機械学習のお仕事のフェーズまで中々たどり着けない
- お仕事って会社に所属しなくても選ぶほどあった