ひ日誌
2006-12-07 ( ja -> en )
_ [sicp][scheme] SICP読書会 # 42
月島にて(会場提供どうもです!)。参加者がおそらく過去最小、このままだと終了してしまう?今回は2.3.4 Huffman符号化のところ、問題2.67から2.69まで。事前に2.4, 2.5 あたりの方まで読んでたんだけど、後ろの章への伏線くさい内容。こちらに書いてある型とか generic procedure の話の方が印象が強かったりして…これは、つまり局所的なアルゴリズムの話よりも大きい設計の話の方が喰いつきやすいということなのか?P.117のオブジェクト指向言語に言及している注釈がちょっと興味深い。
_ [scheme] testing framework を自作
Practical Common Lisp の testing framework のところを読んでたら作りたくなったので、testing framework を自作(testing.scm)して使い始めた。R5RSとSRFI-28仕様のformatのみ使用。多値とかcall/ccとかerrorによる域外脱出などは未対応。例えば:
(test-case "算術演算のテスト" ((+ 1 2 3) => 6) ((+ 1 2 3) !=> 6) ((+ 1 2 3) => 5) ((+ 1 2 3) !=> 5))
を実行すると:
TEST-CASE [算術演算のテスト] ... NG (2/4 tests FAILED!) (+ 1 2 3) !=> 6 ... 6 returned. (+ 1 2 3) => 5 ... 6 returned.
というような結果を表示し #f を返す。
(test-case "算術演算のテスト" ((+ 1 2 3) => 6) ((+ 1 2 3) !=> 5))
なら:
TEST-CASE [算術演算のテスト] ... OK
と表示して #t を返す。
test-caseの構文:
(TEST-CASE テスト ...) (TEST-CASE 説明 テスト ...)
テストの構文:
( テストしたい式 => 期待値) ( テストしたい式 !=> あってはいけない値) (述語 テストしたい式 => 期待値) (述語 テストしたい式 !=> あってはいけない値)
デフォルトの述語は equal?
2006-12-09 ( ja -> en )
_ [rubycocoa][macosx][cocoa][ruby] RubyCocoa 0.5.0 リリース
RubyCocoa 0.5.0 をリリースしました(ダウンロード, 変更点)。木村さんどうもご苦労さまです!(僕はほとんど何もしてません汗)…ということで、ここでRubyCocoaアプリの簡単なサンプルをふたつほど紹介。
まずは、RubyCalc.app。これは、オープンソースマガジン11月号のRubyCocoa記事にスクリーンショットが出ている電卓アプリケーションです。50行ほどのRubyプログラムとInterfaceBuilderで作ったGUIで構成されています。
もう一つは、CocoaRuby.app。こちらは、MOSAの湘南ミーティング2006のRubyCocoaセッションのときにチュートリアルに使った対話型Rubyインタープリタアプリケーションです。やはり、50行ほどのRubyプログラムとInterfaceBuilderで作ったGUIで構成されています。
どちらも RubyCocoa.framework (0.5.0) をまるごと含んでいるので、Mac OS 10.4 で RubyCocoa をインストールしていなくても動くはずです。Finderのコンテクストメニューの「パッケージの内容を表示」で、Contents/Resources フォルダを開くとRubyプログラムのソースを見ることができます。
CocoaRuby.appの方は、ちょっとした動画をYouTubeに置いてあります。画質が悪いのでわかりにくいけど、後半、動的にGUIを変更していくあたりがポイントのつもり:
この動画で入力しているRubyプログラム片はおおよそ以下のようなものです:
puts "hello,world"
puts "こんにちは、世界"
"hello,world"
"こんにちは、世界"
1 + 2 + 3 + 4 + 5
# hoge
# raise "hoge"
include OSX
app = NSApplication.sharedApplication
win = app.keyWindow
win.setTitle "Microsoft VisualStudio 2006 Professional Edition (うそ)"
v = 0 ; (1..10).each {|i| v += i } ; v
v = 1 ; (1..10).each {|i| v *= i } ; v
v = "" ; ('a'..'z').each {|i| v << i } ; v
(1..10).inject(0) {|v,i| v + i }
(1..10).inject(1) {|v,i| v * i }
('a'..'z').inject("") {|v,i| v + i }
50.times do |i|
win.setAlphaValue((i+1) / 50.0)
sleep 0.03
end
win.setTitle "RubyCocoa"
$app = app
$win = win
swin = NSWindow.alloc.
__send__ :initWithContentRect, [750,500,50,150],
:styleMask, 15,
:backing, 2,
:defer, 0
swin.setLevel(3)
swin.display
swin.orderFrontRegardless
slider = NSSlider.alloc.init
swin.setContentView(slider)
class SlideController < NSObject
def slide(sender)
$win.setAlphaValue(sender.floatValue)
end
end
sc = SlideController.alloc.init
slider.setTarget(sc)
slider.setAction("slide:")
$win.setContentView(NSView.alloc.init)
_ [rubycocoa][macosx][cocoa][ruby] RubyCocoa 1.0 開発状況
Laurentさん中心に鋭意開発中のapple-unstableブランチ(1.0としてLoepard搭載予定)ですが、BridgeSupportのメタデータ生成器が素のCにも対応。例えば、/Developer/Examples/Quartz/Python/circle.py のような CoreGraphics のAPIを叩くプログラムをrubyで書くことができようになりつつあります([Rubycocoa-devel 472])。
2006-12-11 ( ja -> en )
_ [mac][macosx] Macの固定長フォント
「RubyCocoaサイトのスクリーンショットに写ってるEmacsで使っている固定幅フォントが気に入ったので、どのフォントか教えて」というメールをもらったのだけど、フォントにあまり頓着してないので思い出せない。Mac OS 9に入っていたフォント、例えばTerminalあたりかなぁ?小文字の'y'と大文字の'W'あたりに特徴がある気がする。もしわかる人がこれを読んでたら教えてください。
そういえば、昔、Monaco 9pt の '0' と 'O' (数字のzeroと英大文字のoh) の区別が付かなくて不便だったので、ResEditで Monacoフォントのzeroに横棒を加えてたような気がする。
2006-12-14 ( ja -> en )
_ [sicp][scheme] SICP読書会
田町にて(会場提供どうも!)。2.3.4 Huffman符号化が終って 2.4抽象データの多重表現に入る。きょうは仕切ってくれる人(なかやまさん)がいたのですんなり進行。2.4.1まで読む。音読すると全員集中するので読書会っぽくなりますね。
出来上がったHuffman符号木をテーブルにしておくと、エンコードとデコードが速くなるという話があって、なるほどと単純に納得してしまったけど、よく考えてみると、テーブルはエンコードにしか使えないような気がする。デコードするときのデータは可変長になっていて、区切りは符号木をたどることで判定するので…
_ [macosx][cocoa][ruby][rubycocoa][objective-c][wii] RubyCocoaでWiiリモコン
最近、RubyCocoaのapple-unstableブランチがTigerの環境でビルド・実行できるようになった(thanks to Laurent!)。BridgeSupportによりObjective-Cベースの任意のフレームワークに動的に対応できるようになっている。基本的には:
OSX.require_framework "WiiRemote"
とするだけ。
そんなところへ、MacでWiiリモコン(指揮棒などに見立てたCMでおもしろそうだなと気になってた)を使えるようにするDarwiinRemote 0.3.1(DarwiinRemoteプロジェクト)が登場。さらにWiiRemoteFrameworkとフレームワーク化された。素晴らしい!
…などとタイミングよく条件がそろったところで、RubyCocoa(0.9apple-unstable)でWiiRemote.frameworkを使うサンプルプログラムを書いてみました。
rWiiRemote.app は、RubyCocoa.framework (apple-unstableブランチ)と WiiRemote.framework を含めてあり、rWiiRemote.app単体で動かせるようにしてあります(単体で動かすために多少rb_main.rbに小細工しました)。Rubyプログラムのソースは、rWiiRemote.app の中に入っています(コンテクストメニューの「パッケージの内容を表示」で開くことができます)。デモ動画も作ってみました(解説つきw):
これを動かすために「はじめてのWiiパック(Wiiリモコン+はじめてのWii)」というものを買いました。しかしWii本体がない。Wii欲しい!
2006-12-16 ( ja -> en )
_ [game][rogue][nintendo][ds] 2006年のrogue - 風来のシレンDSが出た
入荷したところにたまたま居合わせたせいで釣られて買ったDSだが、実際のところやりたいゲームといえばこれしかなかった風来のシレン。なかなか発売されないのですっかり忘れてたけど、ついに発売されたということで入手。
風来のシレンの前身である初代のトルネコの大冒険にあった再現ビデオ機能がかなり気に入ってたのだけど、残念なことにシレンにはない。そこだけちょっと不満だけど、それ以外はあいかわらず楽しめる。
大昔に、仕事場にあったVAX750だか780だかに入っていたrogueで遊んでたときは、何階で戦死したかランキングも楽しみの一つだったような気がするけど、2006年のシレンでは日本全国規模でWiFi番付されてる模様。ちょっと感慨深い。ローグライクゲーム(rogue like game)には、時流や技術の進歩に左右されないゲームのおもしろさの芯があると思う。
2006-12-21 ( ja -> en )
_ [sicp][scheme] SICP読書会 #43
赤坂にて(会場提供どうも!)。2.4.3 データ主導プログラミングと加法性のところから順番に読んで問題2.73まで。ついつい、別の話をしてたりしていてすみませんでした。
二次会で、スポーツ観戦の何がおもしろいのかというような話になって、ロナウジーニョのすごさを説明するのが難しいとかいう話に…それは詩人に語って(煙に巻いて)もらうのがいいんじゃないか(これの元ネタはなんだっけ?)、などと今さっき思いついた。
_ [macosx][cocoa][programming][objective-c] Cocoa Binding のムービーを見た
ADCのページにあるCocoaセミナー上級編 Cocoa Bindingのムービーを見ました(参加しそびれてた)。ずっとCocoaバインディングが何のことだかよくわかってないままだったのだけど、今回は見えたような気がします。参考になりました。ということで、まだ理解があやしい点・疑問点・感想などをメモ書き:
Cocoa Bindingにおける「binding」の意味
手短に表現すると「ビューをある(モデル)オブジェクトに束縛(bind)する」ということらしい。
この場合のビューは、CocoaのGUI部品が持つ様々な属性値に相当。NSTextFieldの場合には、フィールドに入っている文字列や、表示に使うフォントの種類・大きさ・色などであったりする。あるオブジェクトの内容が変更されると、そのオブジェクトに束縛されているビューに反映される。オブザーバパターンっぽい。
(えー?表示するフォントをモデルが持つケースってあるのー?まあそういうときもあるかなぁ)
ここまでだと、RubyやLispでの変数と値の関係「変数に値を束縛」に近いイメージなのだけど、Cocoaバインディングでは、同時に逆方向の関係が成立していて(そうでないとうれしくないのだけど)、ビューが変更されるとモデルに反映される。お互いに束縛しあっているというズブズブ状態。bindingは、片方向ではなく双方向にと考えた方が自然な気がする。
つまり、「ビューとモデルオブジェクトが、互いに束縛(bind)し合っている」と解釈してしまった(勘違いの可能性ありあり)。
変更が通知されるタイミング
ここで、キー値コーディング(KVC, Key Value Coding)が登場。モデルオブジェクトに setValue:forKey: が送られたときに、モデルに束縛されているビューへの通知が行われるらしい(逆方向は普通プログラミングする必要がないけど、多分似たような仕組みを使っていると想像)。
つまり、Cocoaバインディングの仕組みを機能させるためには、積極的に setValue:forKey: を使う必要があるということになるような気がする。いちいち、setValue:forKey: と書くのが美しくない気がするので、自身に setValue:forKey: を送るアクセッサを用意して外からはそれを使うというのがいいかもしれない。などという考えから発展して、Objective-C 2.0 の ドット構文みたいな話が出てきたということか?
NSArrayControllerがモデルをいじるメソッドを備えている
RSSリーダーのサンプルでは、後半の方で、モデル直接ではなくコントローラ(NSArrayController)にメッセージを送ってモデルを更新していたのだけど、これがちょっと気になってしまいました。時間とか説明をシンプルにするためにやむを得なかったのだと推測いたします。無駄にMVC至上主義チック(と思われないか心配汗)な感想ですんません。
などと重箱の隅をつきつつも大変参考になるムービーでした。次はCoreDataの方も見るつもり。楽しみです。
_ キャッチキャッチキャッチ!
「大変参考になるムービーでした」とか「ビューをモデルにバインドする」とか、あまり気にせず書いてたけど、これはかなりルー大柴くさいんじゃないかと不安になりつつ、「ディスイヤーは私にとって再チャレンジのファンデーション作りのイヤーだった」を見てルー大柴かっこいいwと思ってしまったアバウト徹底的に一貫性のある芸風。テレビで見かけたときには速攻で電源オフしたくなるのに…
2006-12-22 ( ja -> en )
_ [macosx][cocoa][objective-c][ruby][rubycocoa] CoreData ムービーを見た
きのうのCocoaBindingに引き続き、ADCのページにあるCocoaセミナー上級編CoreDataのムービーを見ました。Rails的な要素だとかpstore的な要素が見え隠れ。
チュートリアルではエンティティ(モデル)が2つだけなのであまり違いはないけど、エンティティが増えて関係が複雑になってくると、モデリングツールは全体の関係の見通しやすさという点でモデリングツールはとても有効になりそう。一方で、モデルを編集するという観点からは、マウスであっちこちのテキストフィールドを編集してという自動化しがたい作業は複雑になるほどつらそう。最初に作るのはともかくとして、後で変更するときとか。コーディング量はぐーんと減ってるけど、その分に自動化しにくい手作業が増えるような…というあたりが少し気になったかも。
インターフェースビルダーとモデリングツールを使っての編集がほとんどなので、あまり違いはないけどRubyCocoaを使って書いてみた:
require 'osx/cocoa'
require 'osx/coredata'
OSX.ns_import "RSSParser"
class AppDelegate < OSX::NSObject
ib_outlet :channelController
def refresh(sender)
# 選択されたチャンネルを取得します
channel = @channelController.selectedObjects[0]
# URLを取得します
urlString = channel.valueForKey("url")
return if urlString.nil?
# RSSをパースします
parser = OSX::RSSParser.alloc.initWithURLString(urlString)
# チャンネルのタイトルとリンクを取得します
channel.setValue_forKey(parser.channelTitle, "title")
channel.setValue_forKey(parser.channelLink, "link")
# 現在のアイテムを削除します
channel.valueForKey("items").removeAllObjects
# アイテムを追加します
parser.numberOfItems.times do |i|
# アイテムを作成します
item = OSX::NSEntityDescription.
__send__( :insertNewObjectForEntityForName, "Item",
:inManagedObjectContext, self.managedObjectContext)
# アイテム情報を設定します
item.setValue_forKey(parser.itemTitleAtIndex(i), "title")
item.setValue_forKey(parser.itemLinkAtIndex(i), "link")
item.setValue_forKey(parser.itemContentAtIndex(i), "content")
# アイテムを追加します
channel.valueForKey("items").addObject(item)
end
# ビューを更新します
@channelController.rearrangeObjects
end
(以下はテンプレートのまんまなので略)
チュートリアルでは、AppDelegateのアウトレットを_channelControllerとしていたけど、RubyCocoaで先頭の'_'をどう扱ってるか忘れたので念のため取り除いてます。
Key Value Codingがちょっとうるさい感じなので、RubyCocoaでサポートしたい気はする。という考えから発展してObjective-C 2.0(以下略)
それから、RSSパーサはRubyについてるのでそちらを使ってもいいと思う。あっそうだ。RubyCocoaの売りのひとつとして、RSSパーサとかいろいろライブラリがすでにあるから自分で作らなくていいというのもあるな、細かいところだけど…。
_ [rubycocoa][ruby][objective-c][cocoa][macosx] objc_export (仮称)
RubyCocoaでWiiリモコンのPanelController.rbの中で、objc_exportというのを使っているのだけど、これは今の段階では RubyCocoa には含まれていません(個人的には採用したい)。rWiiRemote.app/Contents/Resources/rb_main.rb の中で以下のように定義しています。
module OSX
module NSBehaviorAttachment
def objc_export(name, typefmt)
name = name.to_s
name = name[0].chr << name[1..-1].gsub(/_/, ':')
if /[^:]$/ =~ name && /^.\d*@\d*:\d*[^\d]/ =~ typefmt then
name << ":" end
self.addRubyMethod_withType(name, typefmt)
end
end
end
これは、ひ日誌:20061103.html#p01に書いたような理由で実装しています。
1.0では、BridgeSupportのメタデータが充実してくると objc_method(というかaddRubyMethod_withType) の使用頻度は減ってくるけど、それでもカバーし切れないケースは結構あると思われる。野良フレームワークや野良クラスを使うときとか、あるいはcallbackなど。
WiiRemote.framework の WiiRemote/WiiRemoteDiscovery.h には:
@interface NSObject( WiiRemoteDiscoveryDelegate ) - (void) WiiRemoteDiscovered:(WiiRemote*)wiimote; - (void) WiiRemoteDiscoveryError:(int)code; @end;
というデリゲート(informal protocol)があって、これも addRubyMethod_withType を呼ぶ必要があるケースだった(ちゃんと理由がわかってない汗)。そんなとき:
addRubyMethod_withType "WiiRemoteDiscoveryError:", "v@:i"
と書いて実装の都合を説明するよりも:
objc_export :WiiRemoteDiscoveryError, "v@:i"
のように宣言として見せた方が美しい(主観入りまくり)。ポイントは:
- 宣言のように見えること
- Rubyで定義したメソッド名で指定できること (Objective-Cのselectorではなく)
型指定文字列が生々しいのもいやだけど、これをどうにかしようとすると大変なことになりそうなので触れず。最終的には、BridgeSupportのAPIが充実して解決というパターンもあるのかもしれない?
2006-12-25 ( ja -> en )
_ [javascript] JavaScriptのビックリ
啓示を受けて土曜日(23日)のRHG読書会に参加。「入門JavaScript」を読む会として始まり、JavaScriptのキモさを探る会に変貌して終了。あんまりキモいキモい言うなーと思ってたら、たしかに:
Rhino 1.6 release 4 2006 09 09 js> "0xa" + 10 0xa10 js> "0xa" * 10 100 js> "0xa" - 10 0
これはちょっと…一方:
irb(main):001:0> "0xa" * 10 => "0xa0xa0xa0xa0xa0xa0xa0xa0xa0xa"
はすんなり受け入れて、たまに使ったりもしてる。まあ、慣れてしまえばどちらもどうってことない。
_ [macosx][webkit][javascript][rubycocoa] WebKitでJavaScriptプログラムを評価する方法
RHG読書会のとき、WebKitはJavaScript処理系を持ってるはずだよなーと思って、調べてみたのでメモ。WebView#windowScriptObjectというメソッドがあって、それがJavaScript側のwindowオブジェクトに相当する模様。WebView#windowScriptObjectのevaluateWebScript:でJavaScriptプログラムを評価できる。RubyCocoa 0.5.0 リリースで紹介したCocoaRuby.appを使う場合、例えば:
def js_eval(str)
require 'osx/webkit'
$wv ||= OSX::WebView.alloc.init
$wo ||= $wv.windowScriptObject
return $wo.evaluateWebScript(str)
end
js_eval( "(function(a,b){return a*b})(3,4)" ).to_i # => 12
のような具合。
_ [rubycocoa][macosx][cocoa][ruby] RubyCocoa 1.0 Sneak Preview
Laurentが RubyCocoa 1.0 (0.9) の特徴をまとめたページを作ってくれました。
Cocoa以外のいろんなフレームワーク(CoreFoundation, Quartz, OpenGL, QTKit, WebKitなど)が使えるようになっています。/Developer/Examplesの中にあるサンプルプログラムをRubyで書き直したサンプルがぐーんと増えてきています。きょうは WebKitを使ったブラウザのサンプル RubyMiniBrowser を追加しました。QuartzCore を使った RubyCITransitionSelectorSample や、QuartzCore と OpenGL を使った RubyCIMicroPaint や RubyCIBevelSample などのサンプルはなかなか見映えがします。
2006-12-26 ( ja -> en )
_ [rubycocoa][macosx][cocoa][ruby] RubyCocoa 0.9.0 リリース
RubyCocoa 1.0 のプレビュー版に相当する RubyCocoa 0.9.0 がリリースされました(thank to Laurent!)。Mac OS X 10.4(Tiger)用のユニバーサルバイナリパッケージとソースパッケージでリリースしています。それぞれ、RubyCocoa 1.0 Sneak Previewからダウンロードできます。
自分のところでサンプルなどを動かすかぎり、かなり安定して動いているように思えます。0.9.0 (apple-unstable)を使って、「RubyCocoa で Skype に iTunes で再生してる曲を表示」てなことをなさっている方もいらっしゃいます。興味のある人はお試しください。objc_export と objc_sendは 0.9.1 あたりで入る予定です。
(追記) インストールしていくつかのサンプルを動かしている様子を動画にしてみました
2006-12-30 ( ja -> en )
_ [macosx][wii][rubycocoa][ruby][objective-c] rWiiRemote 更新
「RubyCocoaでWiiリモコン」で作ったRubyCocoa 0.9とWiiRemote.frameworkのサンプルプログラム rWiiRemote を更新しました。
WiiRemote.framework を 0.4 に更新。さらにDarwiinRemoteのソースに入っているGraphViewを使わせていただいてます。オリジナルのObjective-Cで書かれたGraphViewをOSX.ns_importして使うこともできますが(動作確認済み)、Rubyで書き直してみました。RubyCocoa で OpenGL (NSOpenGLView) を使うサンプルにもなるかと思います。また、自分の勉強がてらCocoaバインディングを使ってみました。
- rWiiRemote -- rWiiRemote.appやプロジェクトファイルなど
- GraphView.rb -- DarwiinRemote の GraphView を Ruby で書いたもの
- WiiRemocon.rb -- kvc_accessor や kvc_depends_on を使用、ビューとバインドするモデル(兼コントローラ)に相当
rWiiRemote.app自体が必要なもの(RubyCocoaやWiiRemoteなど)をすべて含んでいるので素のTiger (10.4)で動くはずです。
Wiiリモコン
はじめてのWiiパック(Wiiリモコン同梱)
不思議のダンジョン 風来のシレンDS
入門 JavaScript(久野 靖)
Before...
_ はやみず [比較する述語も指定できる高階関数みたいな構文もあると便利かもなぁ、と思ったけど具体例が思い浮かびませんでした(´・ω..]
_ yuki_neko_nyan [=>っていうと脊髄反射でHash?と思ってしまう自分がいます。!=と==じゃだめなのかな〜。矢印感が大事なのかな。 ..]
_ hisa [最近出てこないので寂しいよ… > ogijunさん、yuki_neko_nyanさん > はやみずさん 一応述語は..]