トップ 追記

Route 477

過去の日記


2014-10-22

[misc] VMWare上のWindows 7にHDDを追加する

最近VMWare Fusion上のWindows 7を再インストールしたんだけど、仮想HDDの追加にちょっと手間取ったので手順をメモっておく。

  1. まずVMWareのVMの設定から「デバイスの追加」を選び、「新規ハードディスク」を追加する。(このとき仮想マシンはいったんシャットダウンしておかないと追加できない)
  2. Windowsを起動する。
  3. ここでエクスプローラを起動して、新しいHDDが見えてたりすると便利なのだけど、C:ドライブしかない。
  4. コントロールパネル→管理ツール→コンピュータの管理→ディスクの管理 を選択。
  5. ディスク0の他にディスク1があるはずなので、右クリックからフォーマットを選ぶ。
  6. あとは全部デフォルトを選べばNTFSでクイックフォーマットされ、使えるようになるはず。今回はE:ドライブとして見えるようになった。

2014-10-21

[golang] unknown flag -trimpath

このgoji-wikiを手元で動かそうとしたら表題のようなエラーが。

$ hub clone https://github.com/mattn/goji-wiki/
$ cd goji-wiki
$ go get
(しばらく待つ)
$ go build
# github.com/flosch/pongo2
/usr/local/Cellar/go/1.2.1/libexec/pkg/tool/darwin_amd64/6g: unknown flag -trimpath
(略)

エラーメッセージで検索すると、「GOROOTとGOPATHが正しいかgo envで見てみろ」との情報が
試しにgo envしてみたら、GOROOTが1.2.1のものになっていた。さっきgo 1.3にアップグレードしたはずだからこれはおかしい。

.zshrcの設定を見ると確かにGOROOTを1.2.1にしている。設定を以下のようにすれば、goをバージョンアップしても.zshrcを直さなくて良いらしい。便利。

export GOROOT=/usr/local/opt/go/libexec

2014-09-24

[mac] MacBookにRを入れてグラフ描いてみた

ちょっとグラフが欲しくなって、Rを入れてみた。*1

基本的にはhomebrewで入れたんだけど、最近は単にbrew install rでは入らないみたい。先にbrew tap homebrew/scienceする必要がある。

あとX11が要るので、brew caskかなんかでxquartsをインストールしておく。

R言語のことは全く分かってないんだけど、read.csvとかでCSVファイルが読めるみたいです。

まとめ

$ brew tap homebrew/science
# xquartsを入れる(僕の環境には既に入っていたのでスキップ)
$ brew install r
$ /usr/local/bin/r  (← r をrailsコマンドにエイリアスしているのでフルパス指定…)
> a <- read.csv("a.csv")
> plot(a)
これでXが起動してグラフが出るはず。

*1 gnuplotも試したんだけど、なんかうまく期待したものが出なくて挫折


2014-09-23

[docker][memo] Dockerでmicro PaaSつくるやつ(メモ)

会社で動かしたら面白いかなと思ったけど、ちょっとオーバースペックそう。

Dokku

「Docker使ったら100行くらいのbashでHerokuっぽいものができたよ」って書いてある。Proof-of-conceptみたいな感じか。

どうやっていろいろな言語をサポートしてるんだろう?と思ったけど、Dockerイメージの作成部分は別のものを使ってみるみたい。

Deis, Flynn

Dokkuより大規模でちゃんとしてるっぽい。DeisとFlynnは別プロジェクトだけど機能的にだいぶ被ってるっぽい。

その他


2014-09-21

[ruby][event] 近況報告@RubyHiroba2014 (パターンマッチ、Hash#map、Opal/Yeahの話)

本日行われたRubyHiroba 2014 (RubyKaigiの後夜祭的イベント) にて、「近況報告」というタイトルでRubyの話をしてきました。

以下はテキスト版です(内容は少し差異があります)。

近況について

いちおうBoomがメインの感心事のつもりなのですが、あまり進んでいません。
理由の一つはケータイを持って社寺仏閣を回るゲームにうつつを抜かしていたことですが、最近はプレイしてないのでもう大丈夫だと思います。

Rubyとパターンマッチについて

Boomの実装にはpattern-matchというgemを使っています。その名の通り、Rubyでパターンマッチをやるためのライブラリです。
Rubyにはパターンマッチがない、と多くの人が思っていると思いますが、gemを使うとそれなりにやりたいことができたりするんですよね。

Rubyでパターンマッチするためのgemはいくつか存在します。

  • pattern-match gem
    辻本さん(speaker)のやつ。

  • patm gem
    todeskingさんのやつ。pattern-match gemより機能が少ない代わりに速いらしい

  • egison gem
    エギさん(speaker)の作っているエギソンという言語のパターンマッチ機能をRubyに移植したもの。
    「..., x, x+2, ...」みたいなパターン(non-linearというらしい)が書けたりしてすごい。
    詳細はRubyKaigi1日目の録画を参照。

さてところで、パターンマッチって何なんでしょうか。HaskellやOCamlなどのいわゆる関数型言語によくある機能ですが、知らない人のために一言で言ってみると、

オブジェクトに対する正規表現

みたいなものかなと。

正規表現を使うと、文字列に対して

str = "add 1 2"
if str =~ /add (\d+) (\d+)/
  puts "Add #{$1} and #{$2}"
end

利点は、if式とかで頑張るよりもずっと簡潔に書けることで、欠点は、Rubyの文法とは別に正規表現の文法を覚えないといけないことです。

パターンマッチも同様で、例えば「こういうパターンの配列」みたいな条件を簡潔に書けるようになります。その代わりに追加でパターンの書き方を覚えないといけないのも同様です。

ary = [:add, 1, 2]
match(ary){
  with(_[:add, x, y]){
    puts "Add #{x} and #{y}"
  }
}

pattern-match gemでは配列だけでなく、ユーザ定義クラスについてもマッチさせることができます(Scala由来なのかな?)。

class Book  # has :title, :price
  def initialize(title, price)
    @title, @price = title, price
  end
  attr_reader :title, :price

  def self.deconstruct(val)
    accept_self_instance_only(val)
    return [val.title, val.price]
  end
end

book = Book.new("Programming Ruby", 3400)
match(book){
  with(Book.(/Ruby/, 0..5000)) {  # タイトルに「Ruby」が入っていて
    p book                        # 値段が5000円以下の場合にマッチ
  }
}

パターンマッチはRubyKaigi初日のRuby Commiters vs the Worldでも話が出たのですが、「本当に入れるならいろいろと詰めないといけないところがあるので、叩き台の提案をどうぞ」みたいな結論になっていましたね。

とりあえずgem i pattern-matchで簡単に入るので、ぜひ試してほしいと思います。

Enumerable#hash_by(仮)について

僕はRubyコミッタではないのですが、いくつかCRubyへの機能提案を通したことがあります。

  • __dir__ (2.0.0)
  • String#lines returns Array (2.0.0)
  • Enumerable#lazy (2.0.0)

で、あと一つ入れたいメソッドがあって、それは「Hashを返すHash#map」です。
RubyのHashって、mapするとArrayになっちゃうんですよね。

h = {a: 1, b: 2}
h.map{|k, v|
  [k.to_s, v]
}
#=> [["a", 1], ["b", 2]]
# Wanted {"a" => 1, "b" => 2}

こういうものが欲しいとき、従来のRubyではHash#[]とかを使って「キーと値の組の配列」をハッシュに変換する必要がありました。

h = {a: 1, b: 2}
Hash[h.map{|k, v|
  [k.to_s, v]
}]
#=> {"a" => 1, "b" => 2}

Ruby 2.1からはEnumerable#to_hというメソッドが入ったので、「キーと値の組の配列」をto_hすることでハッシュが作れて、だいぶ良くなりました。

h = {a: 1, b: 2}
h.map{|k, v|
  [k.to_s, v]
}.to_h
#=> {"a" => 1, "b" => 2}

が、これって「ハッシュから配列の配列を作って、それをハッシュにする」っていうコードなんですよね。やりたいのは「ハッシュを加工した別のハッシュを作る」ことなので、これでは意図が十分に表現されていない、と考えます。

議論

この問題に対しては、前に一度チケットを立てたことがあります。

このときはHash#applyかHash#hash_mapみたいな名前はどうか?と提案していますね。それに対してまつもとさんが、Hash#collectの挙動を変えたらいいじゃん、と言っています。どうでしょうか?

  • Array#mapとArray#collectはalias
  • Hash#mapとHash#collectもalias(今のところ)
  • しかしそういえばHash#reject, Hash#selectはハッシュを返す (特にHash#selectは1.9からそうなった)
  • そういわれるとHash#collectがハッシュを返すのは綺麗な気がする
  • 互換性の問題がなければ:-P

という感じで、そのあともいろいろな名前が出るのですがacceptには至らないのでした。

それで、最近また提案したのがこのチケットです。
to_hはいまブロックを取らないのですが、これに直接ブロックを渡せるようにするのはどう?という案です。

User = Struct.new(:id, :name)
users = [User.new(1, "Alice"), User.new(2, "Bob")]

users.hash_by{|u| [u.id, u.name]}
# {1 => "Alice", 2 => "Bob"}
h = {a: 1, b: 2}
h.to_h{|k, v|
  [k.to_s, v]
}
#=> {"a" => 1, "b" => 2}

この案は残念ながら「to_hという名前でこの挙動は変じゃない?」という話で終わりそうです。
が、「こういうメソッド自体は欲しい」という意見もあったので、良い名前があれば採用されるかもしれません。いまのところ自分の中で一番マシなのはEnumerable#hash_byですが、そこまで良い名前でもないような気もして…。

Opal(Ruby to Javascriptコンパイラ)について

最後はOpalの話です。

去年のRubyHirobaでもちょっと紹介しましたけど、RubyからJavaScriptへのコンパイラですね。厳密には、文字列がimmutableだったりとか100%のRubyではないんですけど、普通にRubyを書く感じで使える程度にはなっています。

Why Opal Matters #1

Opalになんで注目してるかというと、近年ではJavaScriptを使っていろいろなことが出来るようになっています。

JavaScript x HTML5
JavaScript x WebSocket
JavaScript x WebRTC
JavaScript x Mobile
 ...

Opalがあれば、このへんがぜんぶRubyを使って遊べるわけです。

Ruby(Opal) x HTML5
Ruby(Opal) x WebSocket
Ruby(Opal) x WebRTC
Ruby(Opal) x Mobile
 ...

例として、Yeahというすごい名前のゲームフレームワークがあります。gem install yeah で入ります。
会場ではこれのライブコーディングをしました。以下は別に作った(というか移植した)ゲームです。こっちはyeahのgit masterを使っています(bundle exec yeah serveしてください)。

Why Opal Matters #2

もう一つ、Opalの応用として面白いものが出ています。
VoltというWebアプリケーションフレームワークで、「サーバ側もクライアント側もRubyで書く」のですが、なんかクライアントでデータを変更するとシームレスにサーバ側に通知されるとか書いてあってヤバそうな感じです。

Webアプリのサーバ側・クライアント側を同じ言語で書く、というアイデアは昔からあるものですが(Linksとか)、Node.jsの登場で、いろいろ研究が進んでるみたいなので(RendrとかMeteorとか)、Opalでそういった技術がRubyに持ってこれると面白いのかなと思っています。


過去の日記