2009-10-03
■ [ruby][memo] gem戦闘力362
ちょっとgem環境整理しなおすんでメモ
BlueCloth-1.0.0 GraphvizR-0.5.1 ParseTree-2.2.0 ParseTree-3.0.2 RedCloth-4.1.9 RedCloth-4.2.2 Remarkably-0.5.2 RubyInline-3.8.2 ZenTest-4.1.3 aaronp-frex-1.0.1 abstract-1.0.0 actionmailer-2.3.3 actionmailer-2.3.4 actionpack-2.3.3 actionpack-2.3.4 activerecord-2.3.3 activerecord-2.3.4 activeresource-2.3.3 activeresource-2.3.4 activesupport-2.3.3 activesupport-2.3.4 acts_as_paranoid-0.3.1 acts_as_versioned-0.2.3 addressable-2.0.2 addressable-2.1.0 amalgalite-0.7.7 archive-tar-minitar-0.5.2 arrayfields-4.7.2 autocode-1.0.0 bacon-1.1.0 bluecloth-2.0.5 bones-2.5.1 builder-2.1.2 camping-1.5 capistrano-2.5.5 case-0.5 cgi_multipart_eof_fix-2.5.0 cheat-1.2.1 chipmunk-ruby-4.1.0 choice-0.1.2 chriseppstein-compass-0.6.5 classx-0.0.5 coderay-0.8.312 colored-1.1 columnize-0.2 commonwatir-1.6.2 configatron-2.2.1 configuration-0.0.5 constructor-1.0.2 crate-0.2.1 croc-1.0.0 cucumber-0.3.101 cursesx-003 cutagem-0.0.7 daemons-1.0.10 darkfish-rdoc-1.1.5 data_mapper-0.9.8 data_objects-0.10.0 data_objects-0.9.12 datamapper-0.10.1 datamapper-0.9.11 defunkt-github-0.3.4 diamondback-ruby-0.20090421-x86-darwin-9 diff-lcs-1.1.2 dm-adjust-0.10.1 dm-adjust-0.9.11 dm-aggregates-0.10.1 dm-aggregates-0.9.11 dm-ar-finders-0.10.1 dm-ar-finders-0.9.11 dm-cli-0.10.1 dm-cli-0.9.11 dm-constraints-0.10.1 dm-constraints-0.9.11 dm-core-0.10.1 dm-core-0.9.11 dm-ferret-adapter-0.9.11 dm-is-list-0.10.1 dm-is-list-0.9.11 dm-is-nested_set-0.10.1 dm-is-nested_set-0.9.11 dm-is-remixable-0.10.1 dm-is-remixable-0.9.11 dm-is-searchable-0.10.1 dm-is-searchable-0.9.11 dm-is-state_machine-0.10.1 dm-is-state_machine-0.9.11 dm-is-tree-0.10.1 dm-is-tree-0.9.11 dm-is-versioned-0.10.1 dm-is-versioned-0.9.11 dm-is-viewable-0.10.1 dm-is-viewable-0.9.11 dm-migrations-0.10.1 dm-migrations-0.9.11 dm-more-0.10.1 dm-more-0.9.11 dm-observer-0.10.1 dm-observer-0.9.11 dm-querizer-0.10.1 dm-querizer-0.9.11 dm-rest-adapter-0.10.1 dm-rest-adapter-0.9.11 dm-serializer-0.10.1 dm-serializer-0.9.11 dm-shorthand-0.10.1 dm-shorthand-0.9.11 dm-sweatshop-0.10.1 dm-sweatshop-0.9.11 dm-tags-0.10.1 dm-tags-0.9.11 dm-timestamps-0.10.1 dm-timestamps-0.9.11 dm-types-0.10.1 dm-types-0.9.11 dm-validations-0.10.1 dm-validations-0.9.11 do_sqlite3-0.10.0 do_sqlite3-0.9.12 echoe-3.1.1 english-0.3.1 erubis-2.6.5 eventful-1.0.0 eventmachine-0.12.8 extensions-0.6.0 extlib-0.9.12 extlib-0.9.13 facets-2.5.2 faker-0.3.1 fakeweb-1.2.1 fastthread-1.0.1 ferret-0.11.6 filebase-0.3.6 firewatir-1.6.2 flexmock-0.8.4 functor-0.5.1 gamebox-0.0.6 gem_plugin-0.2.3 gembox-0.2.0 gemcutter-0.1.2 gemi-0.0.3 gemify-0.2.4 genki-cutagem-0.0.8.3 gettext-2.0.0 git-1.1.1 git-1.2.4 graph-1.1.0 haml-2.2.2 highline-1.5.0 hoe-2.3.2 hpricot-0.8.1 icalendar-1.0.2 ifchanged-1.0.0 innate-2009.07 innate-2009.10 irb_rocket-0.1.2 jackdempsey-sequel_polymorphic-0.0.1 jake-1.0.0 jbarnette-johnson-1.0.0.200808062111 jbarnette-johnson-1.0.0.20090402155420 jeremymcanally-pending-0.1 jeweler-1.0.2 jeweler-1.2.1 johnson-1.1.0 json-1.1.3 json_pure-1.1.6 langalex-culerity-0.2.3 launchy-0.3.3 less-1.1.12 linecache-0.43 live_console-0.2.0 locale-2.0.4 locale_rails-0.1.0 lockfile-1.4.3 logging-0.9.6 mack-0.8.2 mack-active_record-0.8.2 mack-asset_packager-0.8.2 mack-caching-0.8.2 mack-data_factory-0.8.2 mack-data_mapper-0.8.2 mack-distributed-0.8.2 mack-encryption-0.8.2 mack-facets-0.8.2 mack-haml-0.8.2 mack-javascript-0.8.2 mack-localization-0.8.2 mack-markaby-0.8.2 mack-more-0.8.2 mack-notifier-0.8.2 mack-orm-0.8.2 mack-pdf_writer-0.8.2 mailfactory-1.4.0 mame-simpletrace-1.0.0 manalang-bdoc-0.2.2 markaby-0.5 maruku-0.5.9 mechanize-0.9.3 meow-2.1.0 merb-1.0.12 merb-action-args-1.0.12 merb-assets-1.0.12 merb-auth-1.0.12 merb-auth-core-1.0.12 merb-auth-more-1.0.12 merb-auth-slice-password-1.0.12 merb-cache-1.0.12 merb-core-1.0.12 merb-exceptions-1.0.12 merb-gen-1.0.12 merb-haml-1.0.12 merb-helpers-1.0.12 merb-mailer-1.0.12 merb-more-1.0.12 merb-param-protection-1.0.12 merb-slices-1.0.12 merb_datamapper-1.0.12 metaid-1.0 methodphitamine-1.0.0 mime-types-1.15 mislav-will_paginate-2.3.11 mocha-0.9.5 mongrel-1.1.5 moro-open_id_authentication-1.0.0 moro-repim-0.1.7 mspec-1.5.12 ncurses-0.9.1 net-scp-1.0.2 net-sftp-2.0.2 net-ssh-2.0.11 net-ssh-gateway-1.0.1 newgem-1.2.3 nokogiri-1.3.3 ocra-1.1.1 oniguruma-1.1.0 opencv-0.0.6 openid_fu_generator-0.0.1 openid_login_generator-0.1 oyster-0.9.2 packr-3.1.0 passenger-2.2.2 pit-0.0.6 plist-3.0.0 polyglot-0.2.5 polyglot-0.2.9 publisher-1.1.1 quality_extensions-1.1.4 r18n-core-0.2.1 r18n-desktop-0.2.1 racc-1.4.6 rack-0.9.1 rack-1.0.0 rack-cache-0.2.0 rack-test-0.5.0 radiant-0.8.0 rails-2.3.3 rails-2.3.4 rails_datamapper-0.10.1 rak-0.9 rake-0.8.7 rake-compiler-0.5.0 rake-compiler-0.6.0 rakegen-0.6.6 ramaze-2009.05 ramaze-2009.07 ramaze-2009.10 randexp-0.1.4 rcodetools-0.8.1.0 rcov-0.8.1.2.0 rdiscount-1.3.5 rdoc-2.4.3 rdtool-yhara-0.0.0 reagent-simple-gem-0.4.1 red-4.1.7 redparse-0.8.0 reposh-0.1.6 resh-0.0.4 rexical-1.0.4 rmail-1.0.0 rocketstarter-0.1.0 rr-0.10.0 rspec-1.2.8 rspec-rails-1.2.7.1 rtask-010 rubigen-1.5.2 rubigraph-0.2.0 ruby-debug-0.10.3 ruby-debug-base-0.10.3 ruby-graphviz-0.9.0 ruby-growl-1.0.1 ruby-openid-2.1.4 ruby-station-0.1.1 ruby-station-0.1.3 ruby-station-runtime-0.0.4 ruby-treemap-0.0.3 ruby2ruby-1.2.1 ruby_parser-2.0.4 rubyforge-1.0.4 rubygame-2.5.3 rubygems-update-1.3.5 rubylexer-0.7.2 rubypython-0.2.7 rubyscript2exe-0.5.3 rubysdl-2.1.1 rubytter-0.8.0 rubyzip-0.9.1 rushcheck-0.8 s4t-utils-1.0.4 scrubber-scrubyt-0.4.16 scrubyt-0.4.06 sequel-3.2.0 sequence-0.2.0 sexp_processor-3.0.0 shotgun-0.4 sinatra-0.9.4 sinatra-r18n-0.2.1 sources-0.0.1 spork-0.5.7 sproutcore-0.9.20 sqlite3-ruby-1.2.5 sup-0.8.1 swdyh-gisty-0.0.11 syntax-1.0.0 systemu-1.2.0 taka-0.0.1 technicalpickles-gemstalker-0.4.0 templater-0.5.0 tenderlove-frex-1.0.1.20090313144615 term-ansicolor-1.0.3 termcolor-0.3.1 termios-0.9.4 termtter-1.3.1 test-unit-2.0.2 textpow-0.10.1 thin-1.2.2 thor-0.9.9 thoughtbot-factory_girl-1.2.1 ticketmap-0.2.0 tickets-0.1.0 tlsmail-0.0.1 treetop-1.3.0 treetop-1.4.2 trollop-1.13 ultraviolet-0.10.2 unroller-0.1.3 user-choices-1.1.6 uuidtools-1.0.7 vegas-0.0.3.1 visionmedia-bind-0.2.6 visionmedia-commander-3.2.9 visionmedia-jspec-2.0.3 waves-0.8.2 webrat-0.5.3 why-bloopsaphone-0.4 win32-api-1.4.2 wirble-0.1.3 wx_sugar-0.1.21 wxruby-1.9.9-universal-darwin-9 xml-simple-1.0.12 yard-0.2.2 yhara-ruby-sl-0.11 yhara-tickets-0.1.0.3
■ [arc] Arc 3.1はいかにしてset-car!を実装したか
pg「MzSchemeの最新版はset-car!がないから古いやつを入れてね」 ↓ pg「パッチ貰ったんで最新のMzSchemeでも動くようになったよ」
えっ、それってset-car!するたびにリストを作り直すってこと?と思ってパッチを見たら:
+(define (set-ca/dr! offset who p x) + (if (pair? p) + (let ([p* (get-ptr)]) + (ptr-set! p* _scheme p) + (ptr-set! (ptr-ref p* _pointer 0) _scheme offset x)) + (raise-type-error who "pair" p)))
ptr-set!ってなんだwww
■ [ruby-station] Windows対応
2時間ほど試行錯誤したあげく、「Open3がない」というオチ。今回は諦めるか…。
RubyStationで外部プロセスを起動したい場面は2つある。
- アプリケーションの起動。stdout, stderrは取れなくてもいい(起動に失敗した時のことを考えると取れてほしいけど…)。できれば終了を検知したい。
- gemコマンドの起動(インストール、アンインストール)。stdout, stderrが必須、できればリアルタイムに。終了の検知は必須。
で、Rubyでどうやるかというと:
- 前者
- Process.spawn (○windows対応 ×1.9のみ)
- Thread + system (○windows対応, 1.8でも)
- 後者
- Popen3 (×windows非対応)
- PTY (○リアルタイム、×windows非対応)
- そもそもgemコマンドを使うのをやめる (GemのAPIを叩く) (○リアルタイム, windows対応 △gemのバージョン間の差異を踏まないか)
という感じ。
さて、「windowsで」「1.8で」「起動したプロセスのstderrへの書き込みを取得する方法」ってあるのかな。
2009-10-06
■ [prog] 言語間のおおまかな速度差
「Computer Language Benchmarks Game」を眺めて、各言語のおおまかな速度性能をまとめてみた。
C、C++ ---- 1倍の壁 ---- Java ---- 3倍の壁 ---- Scala C#(Mono) Haskell(GHC) OCaml CommonLisp(SBCL) Fortran ---- 10倍の壁 ---- Lua(LuaJIT) Erlang Scheme(PLTScheme) ---- 30倍の壁 ---- JavaScript(V8, Tracemonkey) Smalltalk(VisualWorks) ---- 50倍の壁 ---- Python PHP ---- 100倍の壁 ---- Perl Ruby(JRuby, Ruby 1.9)
もちろん実際には、動かすプログラムによって大きく差があるんだけどね。
■ [ruby][memo] gem環境を再構築した
以下、特におすすめしないよ
やりたかったこと
- ruby 1.8とruby 1.9の共存
- ~/.gemに入れる (sudo使わない)
手順
Ruby 1.9.2のtrunk(git mirror)を取ってきて、ruby-1.9という名前でインストール
- 最近はRakefileでやってる
- rake ruby-trunk AS=ruby-1.9 で、~/bin/rubys/以下にインストールされる
sudoで入れた方を全削除 (Standards: RubyGems Best Practiceより)
$ yes | sudo gem uninstall '' -a
~/.gemにパスを通す
export PATH=/Users/yhara/.gem/ruby/1.9.1/bin:/Users/yhara/.gem/ruby/1.8/bin:$PATH
複数のgemコマンドで一括インストールするにはgemiを使う
- gem install gemi --source=http://gemcutter.org
- gemi install foo で gem install foo と gem-1.9 install foo が走る
今の.gemirc:
- :name: 'MRI 1.8' # used just for showing messages :command: 'gem' :options: '--no-format-executable --user-install' - :name: 'MRI 1.9' :command: 'gem-1.9' :options: '--format-executable --user-install'
つまりどっちも~/.gemに入れて、実行ファイルは foo と foo-1.9 のように命名される。
経緯
- 本当は foo-1.8 と foo のようにしたかったのだけど(Rubyistとして)、portsで入れたRuby 1.8が ruby という名前になってるので無理だった。
- Ruby 1.8も自前で入れるようにすれば可能。
- Rakefileをこれ以上いじるのが面倒になったので、延期。そろそろRakeじゃなくて普通のRubyスクリプトにした方が楽そう
- ~/.gemに入れるには gem install foo --user-installでOk
- 1.8.x は ~/.gem/ruby/1.8以下に入る
- 1.9.1, 1.9.2は ~/.gem/ruby/1.9.1に入る (どちらも拡張ライブラリがバイナリ互換なので)
- 1.9で~/.gem生活を送るにはtrunkが必要!
- 1.9.1には、デフォルトで~/.gemからロードしてくれないバグがある(1.9.2で直る)
- 1.9.1と1.9.2でgemを共有するためには、両方を「同じ名前で」インストールする必要がある
- 別名にしてsymlinkで切り替えるのではダメ
- なんでかというと、実行ファイルのshebangにインタプリタのパス名が入るから
- 例:~/.gem/ruby/1.9.1/bin/rake-1.9 には #!/Users/yhara/bin/rubys/ruby-1.9/bin/ruby-1.9 と書かれている
- 1.9.1を「ruby-1.9」という名前でインストールしておき、1.9.2が出たらまるごと置き換えればOK (1.9.1と1.9.2とか、1.9.2-preview1とpreview2とか同時に使いたいケースはあまりないよね?)
- --format-executableを「途中で」切り替えるのはおすすめしない
- 実行ファイルfooが入ってるときにfoo-1.8として上書きインストールすると、uninstall fooしたときにfooの方が消えてくれないバグがないだろうか
2009-10-07
■ [prog] 20分でFONCプロジェクトについて説明する
と言っている間にももう45秒(ry
FONCは、アラン・ケイ率いるViewpoint Research Institudeで行われている、 2万行でOSを書いてしまおうというプロジェクト。
OSと言ってもLinuxみたいなんじゃなくて、Smalltalkの環境的なものを考えてるんじゃないかと思うけど、 ともかく2万行でシステム全体が機械語に落ちるのが目標(じゃないかと思われ)。
んで今のところSmalltalkっぽい言語(idst, Pepsiとも, *.st)のコンパイラと、それで書かれたSchemeっぽい言語(Coke, *k)のインタプリタが動いている。 コンパイラの方はブートストラップになっていて、idstでidst自身のソースをコンパイルすると機械語で書かれたidstのバイナリができる。
また両方とも(?)OMetaとかPEGとかそのへんのパターンマッチをサポートしていて、それが行数にだいぶ貢献してるらしい。 Coke言語は角括弧で [ receiver selector [arguments...] ] とか書けるようになっていて、 これでSmalltalk側と連携するんだと思う。
まあとりあえず
$ svn co http://piumarta.com/svn2/idst/trunk
で取ってきていろいろいじってみるのが良いかと。
MacPortsでmakeが通らないときは、/usr/localを/opt/localに書き換えるとうまく行くかも。
ブートストラップで自分自身が機械語に落ちるというのはやっぱり格好いいですねw しかも、もうグラフィカルなデモとかが動く状態になっていて楽しい。
感想
20分だと全然検証できん。嘘が書いてあると思うので鵜呑みにしないように。
追記
大事なことを書き忘れたが、行数を減らすってのはゴルフするという意味ではなく、 「どこまでコードを畳めるか(抽象度を高められるか)」という話です。
■ [ruby] Shoesはgemにするつもりはないっぽい
新しいメンテナに引き継がれたRuby Shoesですが、 gemを作るつもりはないか聞いてみたところ、 「Rubyにパッチ当ててるから難しいんじゃない?」とのこと。
_why本人もShoesはライブラリじゃなくて環境と書いてますね。
2009-10-09
■ [ruby] github上でのgem生成が終わるそうです(今後はgemcutterで)
終わるというか、1週間前から既にサーバ移転の関係で生成が止まってたわけですが。
生成は終わりますが、既にgithubに上げられているgemは、少なくとも1年はインストール可能なままにしておくそうです。
gemをダウンロードさせるサイトとして、rubyforge, github, gemcutterを乱暴に比較するとこんな感じ。
rubyforgeから | githubから | gemcutterから | |
手軽さ | △ | ○ | ◎ |
利点 | デファクト・スタンダード | 「俺版gem」を作れる | コマンド一発 |
欠点 | アップロードが多少面倒 | 15分ほど待たないといけなかった | まだ初期段階 |
用途 | 「公式gem」の提供 | 「勝手版gem」の提供 | ←の両方(を目指している) |
githubでgemを作れるようになったときは「なんて簡単なんだ!」と思ったけれど、 gemcutterはそれよりさらに簡単(gem push *.gemだけ)なんですね。しかもgithubはgemspecをpushしてから gemがインストールできるようになるまで15分前後の遅延があったけど、gemcutterはそれもなし。 また、githubのように「作者名-プロジェクト名」とprefixが付いたりしないのも良いところです。
が、forkしたプロジェクトのgemを配布する場合など、prefixが付いてほしいケースもたまにあるんですよね。 現在、gemcutterのwikiや MLで そのようなケースをどう扱うかの議論が行われているようなので、いずれそれも可能になるでしょう。
2009-10-13
■ [rails] Rails3に「デフォルトでHTMLエスケープする機能」が入ったらしい
ERBでは「<%= foo %>」がエスケープなし、「<%= h foo %>」がエスケープありですが、 Rails3のtrunkで、デフォルトでHTMLエスケープを行う機能が入ったそうです。
安全のために「<%= foo %>」の方をエスケープありにすべきだろうという議論は前からあって、 実装もErubis(オプションで可能)とか SafeERB*1 *2とか あったわけですけど、できればRails標準でそうなってた方が良いし、その変更を入れるなら確かにバージョン2→3の今しかない気がします。
エスケープを無効にするにはString#html_safe!を呼ぶか、プラグインで「<%= raw foo %>」のように書けるみたいです。
これがデフォルトになると、Rails2.xのコードがそのまま動かなくなるわけですが、まだ開発版なので、実際には
- オプションを付けると古い挙動にできる
- オプションを付けると新しい挙動になる
- やっぱり取り下げられる
などいろいろな可能性が考えられます。今後も要注目ですね。
そういえばRails 3のMLってあるんでしょうか?http://groups.google.com/group/rubyonrails-core ?
2009-10-14
■ [ruby] (Ruby 1.9の)Hashが順序を保持するのは自然か
という話がありましたが:
Rubyは、ArrayがStackやQueueを含んでいるように、大クラス主義の言語です。 Hashが順序を保持するようになったというよりは、 「HashがOrderedHashを含むようになった」と考えると自然かなぁと思います。
■ [smalltalk] GNU Smalltalkなら、コマンドラインでSmalltalkを試せる
そんなものがあったのか!ということで、MacPortsで入れてみる。 *1
$ port install gst
gstコマンドで起動。
/Users/yhara/proj/smalltalk % gst GNU Smalltalk ready st> 1 + 2 3 st>
おお、動いてるっぽい。
st> nil nil
nilがnilなのでニヤリとしてしまう(笑)。
Smalltalkというと環境とセットになってるイメージが強いけど、こうやって言語の方だけ手軽に試せるのはありがたい。
目下気になってるのは、「SmalltalkはRubyとどのくらい違うのか?」という点。 「マクロ」をLispの本質だとすると、LispとRubyはそれなりに離れてるけど、もし「全てがオブジェクト」がSmalltalkの本質ならば、Lispよりも実は近いのかな? などと想像している。
まあとりあえずはチュートリアルですかね。
リンク:
それにしても、構文定義の短さには驚いた。 さすが、ifすらメソッドである言語。
*1 デフォルトだとGTKとかも入るので、時間がかかるのが嫌な人は適宜variantを指定しましょう。
□ sumim [お邪魔します。Ruby と Smalltalk の近さは、特に#collect式のようなブロック付きメソッド呼び出し..]
2009-10-15
■ [tDiary] highlight.rbがうまく動いていない
気づいたら、highlight.rbによる<title>編集が動かなくなってますね。なんでだろ。
どうりで被ブクマに長いタイトルが多いと思ったw
2009-10-16
■ [ruby] Tab Sweep
http://github.com/defunkt/mustache
ロジックを含まないテンプレートエンジン。
というのは他にもいろいろあるけど、Rails界ではいまいち流行らんよね。
erbでロジックを「含めない」ことはできるからかも。
http://github.com/defunkt/lyndon
Pure RubyのJavaScriptインタプリタ、jhonsonのMacRuby版。
どうやらWebKitのJSインタプリタを呼び出しているらしい。なのでMacRuby専用。その代わり、速度面や互換性はばっちりだと思われる。
■ [ruby] Rackミドルウェアのコンテストが開催中 (参加賞あり)
Rails, Sinatra, Merb, RamazeといったRuby用Webフレームワークで共通して使われているライブラリ「Rack」の、ミドルウェア (プラグインみたいなものです)のコンテストが行われている模様。
Rackミドルウェアは、下図のように、WebサーバとWebフレームワークの間で動くので、 有用なミドルウェアを一つ作れば、どのWebフレームワークでもその恩恵を受けることができます。
[Webアプリ] ↑ ↓ [Webフレームワーク] (Rails, Sinatra, Merb, Ramaze...) ↑ ↓ [Rackミドルウェアたち] Rack::ContentLength : Content-Lengthヘッダを付加 Rack::CommonLogger : コンソールにログを表示 Rack::ShowExceptions : 例外が起きたらエラー情報を表示 ... ↑ ↓ [Webサーバ] (Apache, Thin, Mongrel, WEBrick...) ↑ ↓ [ブラウザ] (IE, Firefox, Safari, Chrome...)
既に50件近いRackミドルウェアが集まっているようです。例えば:
- RevisionInfo : HTMLの末尾に、svnまたはgitのリビジョン情報をコメントとして付加する。
- Rack::ChromeFrame : Chrome Frame用のタグを仕込む。
- Rack::Obama : Content-type「nobel-prize/peace」に対して202 Acceptedを返す。*1
応募は、gistに上げてエントリーするだけ。 締め切りは「11:59 p.m. (EST) November 15th, 2009」。
参加賞については、"ALL valid entries will win a credit from BDDCasts and $30 credit from Heroku!" とのことです。 とりあえず良いネタを思いついたら応募しちゃえばいいんじゃないでしょうか。
*1 これがアメリカンジョークだ!
2009-10-17
■ [rails] MVCとかの話
横目で見ながら「それRailsのせいなの?」と思ってたんだけど:
ビジネス上のモデルを複数テーブルにまたがって実装する必要がある場合は本来Model層にあるべきロジックをController側に記述せざるをえないので
[Life is beautiful: デザイン・パターンとは何かより引用]
なるほど、そういうケースを想定されてたのですね。ActiveRecordの代わりにDataMapper(お、見た目が新しくなってる)使えばできるのかなぁ。 Rails3では、Model部分のライブラリを簡単に取り替えられるようになるようですが。
□ tmaeda [お邪魔します。DataMapperは関係なくて、単純に複数テーブルを扱う(AR::Baseを継承しない)モデルクラス..]
2009-10-19
■ [haskell] モナドって結局なんなの
社内勉強会でモナドについて発表しました。分かった気がするたびにすぐに手からすりぬけてしまう、それがモナド…!
追記:
モナドそのものが何なのかとか考えないほうがいいんじゃないですかね!
[Twitter / いーぐるとまとより引用]
まさにその通りだと思います(笑)。IOの使い方、Maybeの使い方、Stateの使い方などを押さえておけば、 中がどうなってるかなんて知らなくても大丈夫。
でも、モナドの持つ「なんか秘技がありそうな感じ」が、中を覗いてみたくさせるんですよね。 この、どこまで掘っても自分の知らないことが出てくる感じがHaskellの魅力なのかも。
Haskell の本当にすごいところは、「なぜなに」を問いかけることでいつまでもプログラマが成長できるところにある。
[ふぁぼったー / ikegami__より引用]
一問一答
Q. モナドって結局なんなんですか?
A. 関数型言語のための、一種のデザインパターンだと思えばいいかも。計算とその組み合わせ方を分離するという。
Q. 「モナド」っていう単語は具体的にどれのことを指すんでしょう?
A. 型コンストラクタ、>>=、returnの3つ組がモナドです。例えばIOモナド(IO, >>=, return)とか、Maybeモナド(Maybe, >>=, return)とか。
Q. >>=とreturnを定義するとどんな良いことがあるの?
A. 「do記法」という文法が使えます。
do putStr "foo" putStr "bar"
は
(putStr "foo") >>= (\_ -> putStr "bar")
のシンタックスシュガーなんですけど、上の方が読みやすいでしょ。
このように、do記法を使うと、純粋関数型言語のHaskellでも「手続き型っぽい雰囲気」を醸し出すことができます。 内部では>>=とreturnに展開されるので、結局関数呼び出しなんですけどね。
Q. モナドはどういう用途に使われてるの?
A. いろいろです。「関数のみで副作用をエミュレートする」のが多いのかな(Stateモナドなど)。他には、「途中で失敗するかもしれない計算をつなげる」(Maybeモナド)とか、「選択肢を全部ためした結果を生成する」(Listモナド)とかがあります。
Q. えっと…、いろいろできるのは分かったけど、どういう共通点があるんでしょうか?
A. だから>>=とreturnですって*1!
do x <- func1 y <- func2 return y
は、
func1 >>= (\x -> func2 >>= (\y -> return y))
のように展開されます。雰囲気的には、func1の実行結果をxとし、func2を実行して、その結果であるyを返す…みたいに読めますよね。でも、 実際に何が起こるかはモナドの種類次第(>>=とreturnの定義次第)です。
Maybeモナドならば、func1がNothingを返したら、func2は実行されません。
Listモナドならば、リストxとリストyの要素の全ての組み合わせに対して、return yが評価されます。
まとめ
関数型言語のプログラムは、ネストした関数呼び出しをよく使います。
f( g( h( i() ) ) )
この、関数呼び出しと関数呼び出しの「間」に仕掛けを組み込むのがモナドです。
…という理解でどうでしょうか先生!
一応、発表に使ったスライドを置いておきます。
リンク
- Monad (functional programming) - Wikipedia, the free encyclopedia
- All About Monads
- Rubyのある風景 - Non Determinism
- state
感想
- モナドの仕組みを知らなくても、do記法だけ知ってればHaskellのコードは書けます(多分)
- というか仕組みを知ろうとすると、すげートリッキーな感じで理解するのが大変…
- モナドを極めるとどんなことが出来るようになるんでしょうね?
- Haskell使ってないのにモナドについて語ろうとするのがそもそも間違ってるね→そこでHaskell本ですよ
以下アフィリエイト。
4797336021
これ一冊でHaskellはだいたい分かります。(って品切れじゃん)
4873114233
Real World Haskell の日本語版。エラー処理からGUI、ネットワークに、最近流行り?のSTMと、 まさにReal Worldな感じの目次ですね。
あと、0521692695の訳書が11月初旬に出るそうです。 4839919623 と合わせて、4冊目のHaskell本ですね(和書として)。
*1 共通点(モナドの本質)が結局よくわかんなかったので逆ギレ
■ [ruby] gemcutterの使い方まとめ (2009年秋)
Rubyの素敵さのうちの何割かは、ライブラリを簡単に入れられるRubyGemsが占めていると思うyharaですこんばんわ。
で、そんなgemを公開するためのサイトとしてはRubyForgeが最も有名だったのですが、 最近、より簡単にgemを公開できるgemcutter.orgというサイトが普及しつつあります。
どれくらい簡単かというと、RubyForgeではWebフォームからアップロードしたり、あるいはRakefileを書いたりなどいろいろ必要なのに対し、gemcutterの場合は
$ gem push mylibrary-1.2.3.gem
これだけです。お手軽ですね!
そんな手軽なgemcutterなので、「最新版はgemcutterに置いたよ」というライブラリがこれから増えていくものと思われます。 ここではgemcutter.orgからgemをインストールする方法を解説します。
(1) RubyGems 1.3.5以降が入ってることを確認する
$ gem --version
を実行して、1.3.5と表示されればOKです。
より古いバージョン(1.3.x)だった場合は、
$ gem update --system
で1.3.5に上がります。
もっと古いバージョン(1.1.xや1.2.x)だった場合は、
$ gem install rubygems-update $ update_rubygems
としてください。
そもそもRubyGemsが入ってなかった人は、aptitude install rubygemsなど、環境に合わせてインストールしてください。 (パッケージマネージャが利用できない場合は、ここからzipをダウンロードし、
$ ruby setup.rb
としてください。)
(2) gemcutterをインストールする
RubyGems 1.3.5が用意できれば、あとは
$ gem install gemcutter
とするだけです。その後、gem tumbleを実行して、gemcutter.orgをgemの探索先に追加してください。*1
$ gem tumble Thanks for using Gemcutter! Your gem sources are now: - http://gemcutter.org # ←これが増えた - http://gems.rubyforge.org
(3) gemcutterからgemをインストールする
gemcutter.orgでは既にたくさんのgemが公開されていますが、それらのインストールは今まで通り gem install foo とすればOKです。
(4) gemcutterでgemを公開する
ついでなのでgemの公開方法についても解説しておきます。
といっても、gemファイルさえできればあとは
$ gem push mylibrary-0.0.1.gem
とするだけなので、問題はどうやってgemファイルを作るかですね。
もしgitをお使いならば、jewelerを使うのが便利です。
- jeweler でらくらく rubygems 作成(github編) - まさにっき(コードで世界を変えたい人の記録)
- Route 477 - gemspecの作り方がわからない?ならばjewelerだ
gitが使えないならば…newgemを使うという方法があります。 gem install newgem → newgem foo → RakefileのFIXMEやTODOを編集 → rake gem でgemファイルができます。 この場合、gemファイルに含めるファイルをManifest.txtに書かなければいけないことに注意してください *2。
あるいは、mylibrary.gemspecを手書きして、gem build mylibrary.gemspec する…という手もあります。 gemspecファイルの書き方は、るりまを見るか、 githubから適当なプロジェクトのgemspecファイルを参考にすれば良いでしょう。
2009-10-24
■ [ruby] gem-depcleanについて、とりとめもないこと
RubyGemsをgentooのPortage風に管理するプラグイン、gem-depcleanをid:ursmさんが公開されています。
やりたいことは
- 依存元がなくなったgemの削除
- 必要なgem・versionだけ残すgem clean
の2つですよね。
前者について
これはRubyGemsの機能として含まれるべきでしょう。uninstallの時に、「それが必要としているが、他から必要とされていないgem」を 同時に消すオプションがあれば良いんですよね。
後者について
「gem clean railsしたら、昔書いたアプリで使ってたバージョンが消えて困った」とかの経験は僕もあります。
「このバージョンはまだ使ってます」フラグを立てることが出来たら良いのかも。(aptitudeのピンがそういうもんなのかな)
RubyGemsに手を入れない解としては、依存があればcleanされないわけだから、人工的に依存を作り出すというアプローチもありますね。 空のgemを作って、それがrails 2.1.1とかに依存していることにしておく。
例:
このpin_gem.gemspecを適当に書き換えて、gem build pin_gem.gemspec → gem install pin_gem-0.0.1.gem とする。
■ [haskell][memo] Functor, Monoid, Monad, Arrowなどについて解説した「Typeclassopedia」
注) 激しく上級者向けです。
半分くらいしか理解できた気がしないけど、面白かったです。GHCのライブラリのソースを見てて、FunctorとかMonoidとかなんなの!と思ってたので。
結局、「Rubyがeach+Enumerableで行っているようなことを、Haskellはもっと大規模に行っているのだ」という解釈をしました。
RubyのEnumerable
Rubyでは「eachメソッドを定義したクラス」にEnumerableモジュールをインクルードすることで、 eachを使って実装されたさまざまなメソッドが使えるようになります。 EnumerableをインクルードしているクラスはArray, Hash, Rangeなどたくさんありますが、 eachが定義できる、即ち「要素を列挙可能である」という性質がこれらに共通していると考えることができます。
Haskellでは?
「Enumerable(each):要素を列挙できるやつ」だとすると、
- Functor(fmap): 中になんか入ってるやつ。リストとかいろいろ
- Monoid(mempty, mappend): 「ゼロ」と「プラス」を持つやつ
- Foldable(fold/foldMap): 畳み込みできるやつ*3
- Traversable(traverse/sequenceA): 畳み込むんじゃなくて、構造を維持したまま、ええと…
- Category(id, .): 関数っぽいもの(AからBへの変換を表すもの) *4
- Arrow(arr, first): ?*5
という感じでしょうか、と書いたところで、「知らんがな!」と言われそうですが、理解したい人は本文を読んで下さい :-( これは自分用のメモです。
賢い生徒は定義と例に注目し、特定のメタファーから学びすぎないようにするでしょう。洞察はいつかそれそのものとして得ることができます。
[[Haskell] The Typeclassopediaを訳しました - #3(2009-10-20)より引用]
洞察そのものを得ることができる、って格好よすぎる。いかにも奥義っぽいw *6 *7
まとめ
Haskellを使うために数学を学ぶ必要はないが、圏論をプログラミングの世界に応用してる言語はHaskellだけなんじゃないか?
*1 ええ、分かってもらおうとはしていません :-P
*2 あるいは、「Applicativeのうち、文脈をたたみ込める(join)やつ」(でいいのかな)
*3 FoldableはMonoidと関係がある。即ち、畳み込むためには、中身がモノイドでなければならない(ゼロとプラスがないと畳み込めない)。例えば整数のリストは畳み込めるが、時刻のリストは畳み込めない(時刻どうしの足し算って定義できないから)。
*4 Categoryという名前は「圏」(←対象と変換の組)から来ているが、対象はHaskellで扱える型でないといけないから、任意の圏を表せるわけではない…らしい。
*5 これは「○○するもの」という表現がしにくいなぁ。Categoryから条件は増えてないよーな気がするぞ。
*6 一方で、洞察を得てるのに言葉にできないのは単に言葉が足らないだけじゃないか?とも思うけど…数学では良くあることなんでしょうか。感情においては、「言葉にできない気持ち」というものが存在して、それを伝えるために音楽とか、小説が媒体として使われたりするわけですが。
*7 まあ、言葉は理解を「助ける」ことしかできなくて、最後の一歩は君自身が踏まないといけないんだよ、ということかな。
■ [prog][haskell][lisp] HaskellとLispに関する考察
Haskellが将来どうなるかだけど、言葉がアレだけど、現在の(と言っておく)Lispのように、一部の人が奥義としてその恩恵を受けるような存在に留まるのではないかと。
副作用なし&遅延評価の効能はいろいろあるんだけど、しかしラジカルすぎて広く普及する気がしない。
- 副作用なし、lazy
- HaskellとかCleanとか
- 副作用なし、eager
- これは意味がない気がする (普通の言語で、副作用をなるべく使わずに書けばいいよね)
- 副作用あり、lazy
- これって作れるのかな?
- 副作用あり、eager
- 普通の言語。
一方でLispが広まらないのは言語の外の問題の方が大きいと思っている。例えばもしも90年代初頭に 「スクリプト言語としてLispを使い倒そう」というムーブメントがあれば今とはだいぶ違った世界だったのではないか。
HaskellとLispの大きな違いはもう一つ、Lispの機能(GCなり、クロージャなり、メタプログラミングなり)が他の言語にどんどん取り込まれていくのに対し、 Haskellの本質は副作用なしと遅延評価だから、他の言語が取り込むことができないということ。
…いや、軽々しく本質とかいっちゃダメですね。型システム抜きにHaskellは語れないだろうし。
追記:正直勢いで書いた、今は反省している。do記法でIOが簡単に書けるように、複雑さをうまくラップできればいいですね。
逆に、「副作用なし縛り」でどこまでいけるかを実験してるのがHaskellだとも言える。 GUIライブラリなんかもいろいろ用意されてたりして、 結構いけるみたいですね。
うん、これだけたくさんのライブラリを集めるだけの 力(魅力&表現力)があるんだから、縮小することはないような気がするなぁ。
2009-10-27
2009-10-28
■ [ruby-station] デスクトップアプリのGUIとしてブラウザを使う、というアイデアを実用化するRubyStation 0.1.5リリース
RubyStationの(事実上、最初の)リリースである 0.1.5 を公開しました。 インストール方法は、なんか公式サイトとか作っちゃったんでそっちを見て下さい。
できること:
- インストールし、起動することができます(当たり前か)
- アプリケーションを入れて遊ぶことができます
- アプリケーションを書いて遊ぶことができます
- もちろん、全ての操作はブラウザ内で完結します
1月や7月にはいろいろ喋りましたけど、一つだけ伝えられるとしたら何か?と考えた結果、 「ブラウザをデスクトップアプリのGUIにするのだ」というアイデアに絞った説明になりました。
まあそれ自体はCUPSとか、Remedieとか、既にいくつも例があるんですけど、 本気でアプリをたくさん常用しようとすると、それぞれのポート番号が覚えられなくて困るという。 あと実行するのにコマンドライン叩くのがめんどいとか、ターミナルのタブ消費するのがめんどいとか、 シェルスクリプトで自動化すればいいんだけど、アプリ増やすたびにシェルスクリプトいじるのもめんどいし、 なんかこークリックしたらインストールできてクリックしたら起動するようにしたい。そんなlazyさを形にしてみました。
RubyStation自体はただの「インストーラ兼ランチャー」なので、実際に動かすアプリがたくさんないと楽しめません。 なので、Rubyが書ける人はぜひ、アプリを作ってみてください。(作り方) *1
僕は夏頃からlifelogというメモアプリとmoneyrailという家計簿アプリを常用していますが、とても良い感じです。 使う側としては、ブラウザ内で開くので余計なウィンドウが増えないってのと、作る側としては、新しく覚えることが少ないってのが良いところですね (本当に、Webアプリを作る感覚でデスクトップアプリができます)。
*1 Ruby以外でアプリを書けるようにできないか?というのもちょっと考えたんですけど、それはつまりクロスプラットフォームなパッケージマネージャを作るということで、さすがにproof of conceptの段階としてはやりすぎだろうという結論になりました
□ なかむら(う) [Windowsに限らず、プロセス生成前に$stderrをパイプでreopenしておけば可能です。 origerr ..]
□ yhara [ありがとうございます。普通の方法でできたんですね。]