(apply-generic op . args)

教育者, 将軍, 栄養士, 心理学者, 親はプログラムする. 軍隊, 学生, 一部の社会はプログラムされる. - 計算機プログラムの構造と解釈 序文

Turbolinksを有効にしたままでangularjsを使用する

Turbolinks and Angularjs

最近はangularjsとRails4の組み合わせであそ、、、仕事しています。 まだまだangularjs触り始めて数日ですが、Turbolinksを有効にしているとng-showなどが画面遷移した際に上手く動かなかったのにハマったので、解決方法を自分用にメモ。

htmlからng-appを削除する

普通(?)はhtmlタグに

<html ng-app='MyApp'>

とか書くと思うんですが、これを削除します。

<html>

app.js.coffeeでbootstrapする

 window.App = angular.module('myApp', ['ngResource'])
$(document).on('ready page:load', ->
  angular.bootstrap(document.body, ['myApp'])
)

2~4行目を追記することで、turbolinkを有効にしていてもangularjsがbootstrapingされるので正常にng-showなどが動作しました。

備考

まだそこまでガッツリangularjsで書きまくっている訳ではないので、なにか問題でるかもしれませんが、

  1. inputに名前を入力
  2. /api/hoge/fugaにgetしてその名前が既に存在しているかチェック
  3. 既に存在していたら「その名前は既に使われています」みたいなalertを表示

くらいのは上記の方法でも正常に動作しました。

Good Luck!

werckerで自分のBOXを作ってみた

werckerで自分のBOXを作ってみました。 割りと簡単だったのでみんなももっと作るといいと思った(自分達のプロジェクトに最適なBOXって中々ないよね)。

作ったリポジトリはこちらです。 https://github.com/iori/box_iori_wercker

やったこと

  • Ruby2.1.1のインストール
  • ImageMagickのインストール

作り方

  • GitHubで専用のリポジトリを作る
  • WerckerとGitHubをいつもどおりに連携する
  • この辺を参考に、wercker-box.ymlを作成してPushする
  • MyApp -> 今作ったアプリ -> Settings -> Admin -> PublicAppにチェックを入れてSave

f:id:Iori_Nishizawa:20140316133050p:plain

  • AddDeployTargetでWerckerDirectoryを選択する

f:id:Iori_Nishizawa:20140316133251p:plain

  • DeployTargetNameになんか適切な名前をいれてSaveする

f:id:Iori_Nishizawa:20140316133327p:plain

  • 普段通りにBuildして、Buildが終わったらDeployする

f:id:Iori_Nishizawa:20140316133421p:plain

  • 無事デプロイが終われば、BOXに自分のBOXが出てくる!

f:id:Iori_Nishizawa:20140316133457p:plain

Rubyで無名再帰

http://kouyatakao.hatenablog.com/entry/2014/02/28/152153

を書いてて、あれ?Rubyって無名再帰どうすんの?と思って調べたらできたのでメモ

class Proc
  def self_curry
    self.curry.call(self)
  end 
end

def fib_closure
  cache = []
  lambda{|f,n| cache[n] ||= n <= 1 ? n : f.call(f, n-2) + f.call(f, n-1) }
end

fib_o = fib_closure
fib_o.self_curry.call(1000) # => 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875

Rubyでフィボナッチのメモ化

仕事つかれたー、なんかリフレッシュしたーい。 なんて時によくフィボナッチを書いて、それをメモ化してにやにやします。 で、今も仕事の合間にそんなことをしていたのですが、需要少しはあるかなーと記事にしてみた。

普通にフィボナッチ

irb(main):001:0> def fib n
irb(main):002:1>   n <= 1 ? n : fib(n-2) + fib(n-1)
irb(main):003:1> end
=> nil
irb(main):006:0* fib 10
=> 55
irb(main):007:0> require 'benchmark'
=> true
irb(main):011:0> Benchmark.measure { fib 40 }
=> #<Benchmark::Tms:0x007f84932ef3c8 @label="", @real=31.694596, @cstime=0.0, @cutime=0.0, @stime=0.04000000000000001, @utime=31.199999999999996, @total=31.239999999999995>

40とかすると遅いですね。

メモ化

irb(main):014:0* def fib_memo n
irb(main):015:1>   @memo ||= []
irb(main):016:1>   @memo[n] ||= n <= 1 ? n : fib_memo(n-2) + fib_memo(n-1)
irb(main):017:1> end
irb(main):020:0> Benchmark.measure { fib_memo 40 }
=> #<Benchmark::Tms:0x007f8493305858 @label="", @real=3.5e-05, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.0, @total=0.0>

メモ化、サラマンダーよりはや〜(ry 1000でも1瞬で終わります。

さって仕事しよう。

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書きましょうって内容でした。 うーん面白い。

https://github.com/iori/paip

第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でフィボナッチやアッカーマン関数等を書いて気持ちを切り替える、ということを普段からやっていたのであまり苦労はしなかった。

iori/paip · GitHub

第一章Lisp入門

nullとnil

読みなおしてみて気になったのは、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