こうなる。どっちが良いかね (・ω・)?
img の alt は空で貼り込まれるようだ。ここに画像のタイトルなんかを流し込んでもらいたいんだけど。
img の alt は空で貼り込まれるようだ。ここに画像のタイトルなんかを流し込んでもらいたいんだけど。
数式が混じったメモやノートを Mac や PC で作るのはメンドウだ。ワープロを使ったり、TeX に頼るっていう手もあるけど、どうしても入力のスピードで手書きに劣る。本を書くとかなら手間に見合うと思うけど。
いっそ、手書きでも良いじゃないか。今はスキャンという手段があるのだ。紙と鉛筆(ペンの方がスキャンに向いている)で、じゃかじゃか書いて、ささっとスキャン。あとは Picasa に上げてブログに貼り付け。検索の手は届かないけど、どうせ数式なんて検索できない。計算の目的や理由をブログのテキストで書くなり、画像の説明に付ければ十分だろう。
そんなわけで、ちょっと手書きの計算メモを貼りつけるテスト。Picasa だと画像の説明が埋め込まれないんだよな。改良を希望するぞ > Google
送信者 taocp |
今日はスタイルをいじる日。引用のためのスタイルだとか、ブログタイトルの下にあるナビゲーションメニューを整えたりだとか。勢い余って、iPhone で見たときにそれっぽく見えるようにしてみた。まずは、これが始めの第一歩。
iPhone 対応にするには、大きく 2 つの作業が必要になる。 ひとつは、iPhone 特有の Viewport を適切に設定することだ。これには JavaScript でユーザエージェントを判定した後、iPhone (あるいは iPod touch) の場合は meta 要素を使って viewport を設定する。 もうひとつは、iPhone とその他(Mac や PC、等)でスタイルを切り替えられるようにすること。これには、メディアクエリーという CSS 3 の機能を使う。
(「iPhoneサイト制作ハンドブック」p.95)
Mobile Safari には、一般的な PC の Web ブラウザのような、サイズを変えらえるウィンドウがありません。Mobile Safari でコンテンツを配置するのに使われるのは、仮想的な表示領域である「Viewport」です。Mobile Safari の表示と Viewport の関係は、スクリーンの背後にある Viewport の "風景" を、スクリーンのサイズに切り抜かれた "窓" を通して見ているようなイメージです。この "窓" のサイズは変えられませんが、Viewport の "風景" は、大きくなったり小さくなったり、拡大率が変わったりします。
iPhone の Safari で一般の(ie iPhone 対応になっていない)ページを開くと、ダブルクリックやピンチ操作で表示部分を拡大したり、縮小したりできる。あれはこの Viewport が変わっているのだ。コンテンツのレイアウトを iPhone 用に定義するのであれば、Viewport の拡大や縮小は不要。よって、今回、やるべきことは Viewport をサイズ、倍率ともに固定してしまうことだ。
属性 | 設定値 |
---|---|
width | device-width |
user-scalable | no |
initial-scale | 1 |
maximum-scale | 1 |
他のデバイスでは意味のない定義だから、iPhone かどうかの判別をした上で meta 要素を挿入する (あっても邪魔にはならないと思うけどね)。これはは以下の JavaScript コードで行う。長い行は "\" で折り返してある。
(iPhone 判定)
1: var is_iphone = navigator.userAgent.indexOf("iPhone", 0);
2: var is_ipod = navigator.userAgent.indexOf("iPod", 0);
3: if ((is_iphone & is_ipod) > -1) {
4: document.write('<meta name="viewport" \
content="width=device-width, \
user-scalable=no, initial-scale=1, \
maximum-scale=1" />');
}
これを script タグで囲って、テンプレートの head 要素内に置く。title 要素の前とか、すぐ後ろとか、その辺り。
引用文(blockquote 要素)を目立たせようと、スタイルを定義した。こんな風(↓)になる。
SICP:
Program must be written for people to read, only incidentally for machine to execute.
色は、Mail.app の「メモ」で使われている色(「#FEF8BC」)。
ノートのような罫線はぐぐって見つけたここからパクり(→ mugu - memo - CSSでノート風罫線)。画像はサイズを変更した上で使用させてもらっている。
作者に感謝。
公式ブログのリリース告知をざっとまとめていたんだけど、公式なロードマップが存在していた(→ MacRuby >> Roadmap)。こっちの方がコンパクトなので、それを元に、さらに最新版の 0.5 beta 2 までの特徴を入れ込んでみる。
0.5 beta 2 の後、0.7 までについてはこちらを参照 → 「MacRuby 0.7 を iMac にインストール」
Roadmap で特色とされているのは以下の 5 項目。
BridgeSupport ファイルはフレームワークやライブラリの API シンボル情報を記載した XML ファイルで、RubyCocoa や PyObjC のようなスクリプト言語と Objective-C ランタイムとのブリッジ機能で使われる。以上、Snow Leopard の man ページより。
Laurent が MacRuby-devl ML に投げた告知メールによれば、
MacRuby is a version of Ruby that runs on top of Objective-C. More precisely, MacRuby is currently a port of the Ruby 1.9 implementation for the Objective-C runtime and garbage collector.
肝心なことは Objective-C のオブジェクトがそのまま Ruby のオブジェクトになっているよ、というとだろう。MRI 1.9 を Objective-C のランタイムと GC に移植した、と言っている。
MacRuby に関しては以下の記事も参照のこと:
MacRuby の 0.5 beta 2 がリリースされたというので、試してみる気になった。
アナウンスに貼られたリンクから zip のインストールパッケージをダウンロード。zip を展開し、中の PKG ファイルをダブルクリックすればインストール開始。MacRuby の本体などは /usr/local/bin
以下に、Xcode のプロジェクトテンプレートは /Library/Application Support/Developer/3.0/Xcode
以下にそれぞれインストールされる。
インストールが完了するとこうなる(↓):
[macmini:~] mnbi% which macruby /usr/local/bin/macruby [macmini:~] mnbi% macruby -v MacRuby version 0.5 (ruby 1.9.0) [universal-darwin10.0, x86_64]
また、Xcode の新規プロジェクト作成パネルはこう(↓):
送信者 Macをプログラムする |
「RubyによるMac OS Xデスクトップアプリケーション開発入門」を見ながらサンプルを試してみたり(p.224 〜 234)。
Go の channel のようなものとして、Ruby には Queue クラスが用意されている。これを使えば、Rob Pike の説明していたサンプル (A multiplexed server) をほぼそのままの形で Ruby に直すことができる。対応するプログラミング要素はこんな感じ(↓):
Go | Ruby | |
---|---|---|
channel型 | → | Queue クラス |
func型 | → | ブロック |
goroutine | → | Thread クラス |
ちなみに、今回使った Ruby は Snow Leopard に標準のもの。バージョンはこれ(↓):
[macmini:~] mnbi% which ruby /usr/bin/ruby [macmini:~] mnbi% ruby -v ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0]
コードはこうなる。コメントもオリジナルのものをそのまま相当する場所に記入しておいた。
(multi_server.rb)
1: require 'thread'
2:
3: class Request
4: def initialize(a, b, q)
5: @a = a
6: @b = b
7: @replyq = q # reply queue inside the Request
8: end
9: attr_reader :a, :b, :replyq
10: end
11:
12: def run(req, op)
13: req.replyq.enq(op.call(req.a, req.b))
14: end
15:
16: def server(service, op)
17: loop {
18: req = service.deq # requests arrive here
19: Thread.start(req) do |r|
20: run(r, op)
21: end
22: }
23: end
24:
25: def start_server(&op)
26: req_queue = Queue.new
27: Thread.start(req_queue, op) do |rq, o|
28: server(rq, o)
29: end
30: return req_queue
31: end
32:
33: # Start server; recieve a queue on which to send requests.
34: server = start_server {|a, b| (a + b)}
35:
36: # Create requests
37: req1 = Request.new(23, 45, Queue.new)
38: req2 = Request.new(-17, 1 << 4, Queue.new)
39:
40: # Send them in arbitrary order
41: server.enq(req1)
42: server.enq(req2)
43:
44: # Wait for the answers in arbitrary order
45: puts "Answer2: #{req2.replyq.deq}"
46: puts "Answer1: #{req1.replyq.deq}"
オリジナルの Go コードと並べてみれば、ほぼ一対一に対応していることがわかる。
Go のサンプルにあった、channel に対する select を使った server は、Ruby の Queue では簡単に実現できない。Ruby に用意されている select (Kernel.select または IO.select) には IO オブジェクトしか使えない。Queue ではダメなのだ。Queue に対する select に相当する仕組みを Queue や Thread のメソッドを使って作ることは可能だ(と思う)けど、ちょっと面倒なことになる。
ちなみに実行結果は以下のとおり。ちゃんと動いた。
[macmini:~] mnbi% ruby multi_server.rb Answer2: -1 Answer1: 68
Rob Pile が Go の channel の説明で使っていたサンプルを読んでみよう。 以下のコードはどれも、Rob Pike のスライドよりコピペしたもの。
まずはサーバのコード(スライドの 30 枚目)。
[A multiplexed Server]
1: type Request struct {
2: a, b int;
3: replyc chan int; // reply channel inside the Request
4: }
5:
6: type binOp func(a, b int) int
7: func run(op binOp, req *request) {
8: req.replyc <- op(req.a, req.b)
9: }
10:
11: func server(op binOp, service chan *request) {
12: for {
13: req := <-service; // requests arrive here
14: go run(op, req); // don't wait for op
15: }
16: }
17:
18: func StartServer(op binOp) chan *request {
19: reqChan := make(chan *request);
20: go server(op, reqChan);
21: return reqChan;
22: }
Go の文法はよくわからないが、このコードが何をするものなのかは、なんとなくわかる。
1 〜 4 行目は構造体の定義。replyc
が整数の通る channel。その名前から、サーバへのリクエストに対する結果を返すものだと想像がつく。
6 〜 9 行目; サーバにおける処理の定義。2 つの整数に対して、2項演算を適用して、その結果を replyc に送る。
11 〜 16 行目; サーバ本体。引数は処理すべき 2 項演算とリクエストが通ってくる channel。for
は無限ループ。13 行目でクライアントからのリクエストを取り出して、14 行目で実行。ところで、この 14 行目にある go
が goroutine と呼ばれるスレッドを起動するものらしい。run
はすぐ上の 7 行目で定義されている関数。それを別スレッドで処理するってことだ。
18 〜 22 行目が、サーバを起動する関数。引数としてサーバが処理する演算を受け取る。実行する内容は、リクエストを受け付ける channel を用意し(19 行目)、サーバ本体を別スレッドで起動し(20 行目)、リクエストを流す channel をクライアントに返す(21行目)。