「Arduinoをはじめようキット」を購入したよ

全くの初心者なのでとりあえずキットを買ってみた.

Arduinoをはじめようキット

Arduinoをはじめようキット

ついでに本も注文してみた.

Arduinoをはじめよう 第2版 (Make:PROJECTS)

Arduinoをはじめよう 第2版 (Make:PROJECTS)

遊ぶぞー.

mecab-rubyのMeCab::Tagger#parseToNodeの戻り値が気に入らないのでアレする

mecab-rubyでテキストを形態素解析するときによく使うMeCab::Tagger#parseToNodeですが,戻り値がMeCab::NodeのArrayやEnumeratorではなく,以下のようにMeCab::Node#nextを使って各要素にアクセスしなければならないので使い勝手が悪いです.

# -*- coding: utf-8 -*-

require "MeCab"

if __FILE__ == $0
  node = MeCab::Tagger.new.parseToNode("俺、この戦争が終わったら結婚するんだ。")

  while node
    puts "#{node.surface}\t#{node.feature}"
    node = node.next
  end
end

while nodeとかnode = node.nextとか,非常にRubyらしくない感じでアレですね.eachとか使いたい.(メソッド名がCamelCaseなのも非常にアレですが,mecab-rubyはSWIGでコードを自動生成しているみたいなのである程度は仕方ないのかも)

幸いなことにRubyは既存のクラスを自由に書き換えられるので(オープンクラス),以下のようにparseToNodeを再定義してNodeのArrayを返すようにすればこの問題は解決します.

# -*- coding: utf-8 -*-

require "MeCab"

module MeCab
  class Tagger
    # parseToNodeの別名(エイリアス)を作ってprivate化する
    alias_method :parseToNode_org, :parseToNode
    private :parseToNode_org

    # parseToNodeを再定義する
    def parseToNode(*args)
      #オリジナルのparseToNodeを呼び出す
      node = parseToNode_org(*args)
      # NodeのArrayを作って返す
      nodes = []
      while node
        nodes.push(node)
        node = node.next
      end
      nodes
    end
  end
end

if __FILE__ == $0
  nodes = MeCab::Tagger.new.parseToNode("俺、この戦争が終わったら結婚するんだ。")

  # Array#eachが使える!
  nodes.each do |node|
    puts "#{node.surface}\t#{node.feature}"
  end
end

オープンクラスって素敵.

上のRubyスクリプトをMeCabの代わりにrequireするだけでNodeのArrayを返すparseToNodeが使えるようになるので,while nodeとnode = node.nextに嫌気が差したら是非試してみてください.

Ubuntu 10.04でMeCabをRubyから使えるようにする

MeCabのインストール

MeCabと辞書のインストールはapt先生にお任せします.辞書はUTF-8のものを使います.

$ sudo apt-get install mecab mecab-ipadic-utf8

MeCabが正常に動くことを確認します.

$ echo "俺、この戦争が終わったら結婚するんだ。" | mecab
俺      名詞,代名詞,一般,*,*,*,俺,オレ,オレ
、      記号,読点,*,*,*,*,、,、,、
この    連体詞,*,*,*,*,*,この,コノ,コノ
戦争    名詞,サ変接続,*,*,*,*,戦争,センソウ,センソー
が      助詞,格助詞,一般,*,*,*,が,ガ,ガ
終わっ  動詞,自立,*,*,五段・ラ行,連用タ接続,終わる,オワッ,オワッ
たら    助動詞,*,*,*,特殊・タ,仮定形,た,タラ,タラ
結婚    名詞,サ変接続,*,*,*,*,結婚,ケッコン,ケッコン
する    動詞,自立,*,*,サ変・スル,基本形,する,スル,スル
ん      名詞,非自立,一般,*,*,*,ん,ン,ン
だ      助動詞,*,*,*,特殊・ダ,基本形,だ,ダ,ダ
。      記号,句点,*,*,*,*,。,。,。
EOS

mecab-rubyのインストール

apt-getでインストールされたRubyのgemにmecab-rubyを追加する場合は,libmecab-ruby(もしくはlibmecab-ruby1.9.1など)をインストールすれば大丈夫だと思います(未確認).

$ sudo apt-get install libmecab-ruby

RVMrbenvでインストールしたRuby,ソースから自前でインストールしたRubyなど,aptの管理下にないRubyを使っている場合は,以下のように自前でmecab-rubyをインストールする必要があります.

mecab-rubyを自前で入れる前にlibmecab-devをインストールしておきます.これがないとmecab-rubyのビルド時に大量のエラーが出て失敗します.

$ sudo apt-get install libmecab-dev

mecab-rubyはgem installですぐインストールできるわけではなく,自前でソースをダウンロードしてくる必要があります.
MeCabのバージョンを確認し,それに近いバージョンのmecab-rubyをMeCabのGoogle Codeからダウンロードします.MeCabとmecab-rubyのバージョンがあまりにも違いすぎるとmecab-rubyのインストールに失敗することがあるので注意が必要です.

$ mecab --version
mecab of 0.97

Ubuntu 10.04のMeCabのバージョンは0.97のようです.mecab-ruby-0.97はGoogle Codeにはないため,ここではmecab-ruby-0.98を使います.

$ wget http://mecab.googlecode.com/files/mecab-ruby-0.98.tar.gz 
$ tar zxvf mecab-ruby-0.98.tar.gz
$ cd mecab-ruby-0.98
$ gem build mecab-ruby.gemspec
$ gem install mecab-ruby-0.97.gem  # 環境によってはsudoが必要

インストール完了.

動作確認

あとは以下のようなRubyスクリプトを動かして,mecab-rubyが正常に動くことを確認すればOKです.

# -*- coding: utf-8 -*-

require "MeCab"

if __FILE__ == $0
  node = MeCab::Tagger.new.parseToNode("俺、この戦争が終わったら結婚するんだ。")
  while node
    puts "#{node.surface}\t#{node.feature}"
    node = node.next
  end 
end

rbenvでインストールしたRubyのgemコマンドがzlib云々ほざいて動かない時の対処法

rbenvでインストールしたRubyのgemを動かしたら以下のようなエラーを吐いて死にました.

$ gem install -V twitter
ERROR:  Loading command: install (LoadError)
    no such file to load -- zlib
ERROR:  While executing gem ... (NameError)
    uninitialized constant Gem::Commands::InstallCommand

何が原因だろうと思ったら単純にzlib1g-devがインストールされてないだけでした.ついでにopensslやlibreadline-devも必要みたいなので念のためapt-getで入れて,再度Rubyをインストールします.

$ sudo apt-get install zlib1g-dev openssl libreadline-dev
$ rbenv install ruby 1.9.2-p290
$ rbenv rehash
$ rbenv global 1.9.2-p290

もう一度gemコマンドを実行.

$ gem install -V twitter
GET http://rubygems.org/latest_specs.4.8.gz
302 Moved Temporarily
GET http://production.s3.rubygems.org/latest_specs.4.8.gz
200 OK
...

動いた.

こういう基本的なパッケージが初期インストールされてないことも意外とあるんですね….

JavaScriptで記号だけを使ってFizzBuzz

ブラウザ環境ではalert関数で,Rhinoなどではprint関数でFizzBuzzの結果を出力するようになっています.ブラウザで実行して出たダイアログのOKボタンが押せない場合はエンターキーを押してください.

$=+[];$={___:$++,__$:$++,_$_:$++,_$$:$++,$__:$++,$_$:$++,$$_:$++,$$$:$++};_=($.
___)[({}+"")[$.$_$]+({}+"")[$.__$]+({}.$+"")[$.__$]+(!{}+"")[$._$$]+(!!{}+"")[$
.___]+(!!{}+"")[$.__$]+({}.$+"")[$.___]+({}+"")[$.$_$]+(!!{}+"")[$.___]+({}+"")
[$.__$]+(!!{}+"")[$.__$]][({}+"")[$.$_$]+({}+"")[$.__$]+({}.$+"")[$.__$]+(!{}+
"")[$._$$]+(!!{}+"")[$.___]+(!!{}+"")[$.__$]+({}.$+"")[$.___]+({}+"")[$.$_$]+(!
!{}+"")[$.___]+({}+"")[$.__$]+(!!{}+"")[$.__$]]((!!{}+"")[$.__$]+(!!{}+"")[$._$$
]+(!!{}+"")[$.___]+(!!{}+"")[$._$_]+(!!{}+"")[$.__$]+({}.$+"")[$.__$]+"\""+"\\"
+$.__$+$.$$_+$._$$+"\\"+$.$$$+$.$_$+"\\"+$.$__+$.$$$+"\\"+$.$__+$.$$$+"\\"+$.$$$
+$._$$+"\\"+$.__$+$.$__+$.$$_+"\\"+$.__$+$.$_$+$.$$$+"\\"+$.__$+$.$$_+$._$_+"\\"
+$.$_$+$.___+"\\"+$.__$+$.$_$+$.__$+"\\"+$.$$$+$.$_$+"\\"+$.$$_+$.__$+"\\"+$.$$$
+$._$$+"\\"+$.__$+$.$_$+$.__$+"\\"+$.$$$+$.$__+"\\"+$.$$$+$.$_$+"\\"+$.$$_+$.__$
+"\\"+$.$$_+$.___+"\\"+$.$$_+$.___+"\\"+$.$$$+$._$$+"\\"+$.$_$+$._$$+"\\"+$.$_$+
$._$$+"\\"+$.__$+$.$_$+$.__$+"\\"+$.$_$+$.__$+"\\"+$.__$+$.$$$+$._$$+"\\"+$.__$+
$.$$_+$._$$+"\\"+$.$_$+$._$$+"\\"+$.$$$+$.$_$+"\\"+$.$_$+$.___+"\\"+$.__$+$.$_$+
$.__$+"\\"+$.$__+$.$_$+"\\"+$.$$_+$.__$+"\\"+$.$$_+$.$_$+"\\"+$.$$$+$.$_$+"\\"+$
.$$$+$.$_$+"\\"+$.$$_+$.___+"\\"+$.$$$+$.$$$+"\\"+$.$__+$.$$$+"\\"+$.__$+$.___+$
.$$_+"\\"+$.__$+$.$_$+$.__$+"\\"+$.__$+$.$$$+$._$_+"\\"+$.__$+$.$$$+$._$_+"\\"+$
.__$+$.___+$._$_+"\\"+$.__$+$.$$_+$.$_$+"\\"+$.__$+$.$$$+$._$_+"\\"+$.__$+$.$$$+
$._$_+"\\"+$.$__+$.$$$+"\\"+$.$$$+$._$_+"\\"+$.__$+$.$_$+$.__$+"\\"+$.$__+$.$_$+
"\\"+$.$$_+$._$$+"\\"+$.$$$+$.$_$+"\\"+$.$$$+$.$_$+"\\"+$.$$_+$.___+"\\"+$.$$$+$
.$$$+"\\"+$.$__+$.$$$+"\\"+$.__$+$.___+$.$$_+"\\"+$.__$+$.$_$+$.__$+"\\"+$.__$+$
.$$$+$._$_+"\\"+$.__$+$.$$$+$._$_+"\\"+$.$__+$.$$$+"\\"+$.$$$+$._$_+"\\"+$.__$+$
.$_$+$.__$+"\\"+$.$__+$.$_$+"\\"+$.$$_+$.$_$+"\\"+$.$$$+$.$_$+"\\"+$.$$$+$.$_$+
"\\"+$.$$_+$.___+"\\"+$.$$$+$.$$$+"\\"+$.$__+$.$$$+"\\"+$.__$+$.___+$._$_+"\\"+$
.__$+$.$$_+$.$_$+"\\"+$.__$+$.$$$+$._$_+"\\"+$.__$+$.$$$+$._$_+"\\"+$.$__+$.$$$+
"\\"+$.$$$+$._$_+"\\"+$.__$+$.$_$+$.__$+"\\"+$.$_$+$.__$+"\\"+$.$_$+$._$$+"\\"+$
.$__+$.$$$+"\\"+$.__$+$._$$+$.$__+"\\"+$.__$+$.$_$+$.$$_+"\\"+$.$__+$.$$$+"\\"+$
.__$+$.$$$+$.$_$+"\\"+$.__$+$.$__+$.$$_+"\\"+$.$$$+$.$_$+"\\"+$.$_$+$.___+"\\"+$
.__$+$.$$_+$.$__+"\\"+$.__$+$.$$$+$.__$+"\\"+$.__$+$.$$_+$.___+"\\"+$.__$+$.$__+
$.$_$+"\\"+$.__$+$.$_$+$.$$$+"\\"+$.__$+$.$__+$.$$_+"\\"+$.$__+$.___+"\\"+$.__$+
$.$__+$.__$+"\\"+$.__$+$.$_$+$.$__+"\\"+$.__$+$.$__+$.$_$+"\\"+$.__$+$.$$_+$._$_
+"\\"+$.__$+$.$$_+$.$__+"\\"+$.$$$+$.$_$+"\\"+$.$$$+$.$_$+"\\"+$.$__+$.$$$+"\\"+
$.__$+$.$__+$.$$_+"\\"+$.__$+$.$$_+$.$_$+"\\"+$.__$+$.$_$+$.$$_+"\\"+$.__$+$.$__
+$._$$+"\\"+$.__$+$.$$_+$.$__+"\\"+$.__$+$.$_$+$.__$+"\\"+$.__$+$.$_$+$.$$$+"\\"
+$.__$+$.$_$+$.$$_+"\\"+$.$__+$.$$$+"\\"+$.$_$+$.__$+"\\"+$.$$$+$.$$$+"\\"+$.__$
+$.$__+$.__$+"\\"+$.__$+$.$_$+$.$__+"\\"+$.__$+$.$__+$.$_$+"\\"+$.__$+$.$$_+$.
_$_+"\\"+$.__$+$.$$_+$.$__+"\\"+$.$$$+$._$_+"\\"+$.__$+$.$$_+$.___+"\\"+$.__$+$
.$$_+$._$_+"\\"+$.__$+$.$_$+$.__$+"\\"+$.__$+$.$_$+$.$$_+"\\"+$.__$+$.$$_+$.$__
+"\\"+$.$$$+$._$$+"\\"+$.__$+$.$__+$.$$_+"\\"+$.$_$+$.___+"\\"+$.__$+$.$$_+$._$$
+"\\"+$.$_$+$.__$+"\"");($.___)[({}+"")[$.$_$]+({}+"")[$.__$]+({}.$+"")[$.__$]+(
!{}+"")[$._$$]+(!!{}+"")[$.___]+(!!{}+"")[$.__$]+({}.$+"")[$.___]+({}+"")[$.$_$]
+(!!{}+"")[$.___]+({}+"")[$.__$]+(!!{}+"")[$.__$]][({}+"")[$.$_$]+({}+"")[$.__$]
+({}.$+"")[$.__$]+(!{}+"")[$._$$]+(!!{}+"")[$.___]+(!!{}+"")[$.__$]+({}.$+"")[$.
___]+({}+"")[$.$_$]+(!!{}+"")[$.___]+({}+"")[$.__$]+(!!{}+"")[$.__$]](_())()

超適当に書いたのでRubyの記号Fizzbuzzプログラムと比べてずいぶん長くなってしまいましたが,一応誰が見てもFizzBuzzだと分かる範囲に落ち着いたので概ね満足しています.

JavaScript勉強中

2ヶ月くらい前からJavaScriptの勉強を始めました.とりあえずJavaScript: The Good Partsを読んで「JavaScriptの良い部分」だけを使ったコードを書く練習をしているところです.

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

それにしても,他の言語にはないような落とし穴が結構あってアレですね.特にブラウザによって挙動が変わるタイプの落とし穴は本当にやめて欲しいです.

例えば,以下のコードの場合,

var foo = [1, 2, 3,];   // 末尾に余分なカンマが付いている
document.writeln(foo.length);

IE9,Firefox,Google Chromeの場合はfoo.lengthの値は3,IE8以前の場合は4になります.配列リテラルがカンマで終わっていた場合,IE9,Firefox,Google Chromeでは最後のカンマは無視されますが,IE8以前ではカンマの後にundefinedが要素として追加されて[1, 2, 3, undefined]となるみたいです.これはひどい.

JavaScriptのこういう落とし穴をまとめた本ってないのかしらん.

Rubyの文字列リテラルの種類と使い分け方

Rubyでは文字列リテラルの記述にダブルクォート("),シングルクォート('),そして%記法が使える.Rubyでコードを書く上でそれぞれをどのように使い分ければいいか迷ったことがある人も多いのではないかと思う.というわけで自分なりの使い分け方を簡単にまとめてみることにした.

文字列リテラルの括りの種類

ダブルクォート ("str")
  • バックスラッシュ記法 ("\n"など) や式展開 ("#{exp}") が使える
  • 文字列中のダブルクォートはバックスラッシュでエスケープする必要がある ("\"")
シングルクォート ('str')
  • バックスラッシュ記法や式展開は使えない
  • 文字列中のシングルクォートはバックスラッシュでエスケープする必要がある ('\'')
%記法 (%!str! や %Q{str} など)
  • 文字列を任意の非英数字で括ることができる.
  • %!str! や %Q!str! はダブルクォート文字列と同様にバックスラッシュや式展開が使える.文字列中のダブルクォートのエスケープは必要ない.
  • %q!str! はシングルクォート文字列と同様にバックスラッシュや式展開が使えない.文字列中のシングルクォートのエスケープは必要ない.

括りの使い分け方

  • バックスラッシュ記法や式展開を使うかどうかにかかわらず,基本的にダブルクォートを使う.
  • 文字列中にダブルクォートが2回以上出現してエスケープが面倒な場合は,バックスラッシュ記法や式展開が有効な%記法 (%!str!) を使う.
  • シングルクォートは基本的に使わない.

ダブルクォートを優先的に使う理由

  • シングルクォートは後の修正でバックスラッシュ記法や式展開が必要になった時に括りをダブルクォートに変える必要があり面倒.また,うっかり括りを変えずにそのままバックスラッシュ記法や式展開を追加してしまうと意図通りの文字列にならずenbugしてしまう可能性がある.そのため,シングルクォートはあまり使わない方がいいと思う.
  • %記法は基本的に見た目が文字列らしくなくなるので,\"を何度も書かなければならないケースを除いてダブルクォートを優先的に使った方がいい.

以上

というわけで,迷ったらダブルクォートを使うといいと思います.