8月2007

カーソルの軌跡がきらきら

MacPeopleのオンラインウェアのところで、面白そうなソフトが紹介されていたので、試しにインストールしてみました。iBookではキャプチャするにはスペックが足りないので、YouTubeに上がっていた動画で紹介です。

Startrailというアプリケーションです。動画を見て分かる通り、カーソルをきらきらさせるアプリケーションです。Core Imageを使っているのか、意外と処理が重いので、iBookでは他のエフェクトに影響が出てしまうのが残念なところです。

歯痒い三件

iWork ’08のトライアル版のリンクが見つからない件

iWork ’08版の30日試用版がダウンロードできるはずなのに、ググらないとページが見つからない罠。ここからダウンロードできます。
http://www.apple.com/jp/iwork/trial/
結局インストールしただけで、使い道が無いのはiWork ’06と同じこと…

Enumeratorがいつもあと一歩のところで実装できない件

ジェネリックなリストで実装しようとすると、System.ObjectからSystem.Objectへ変換できませんという謎のエラー。普通のArrayListで実装できたと思いきや、GetEnumeratorの戻り値で、なぜか継承したはずのIEnumeratorの型に変換できない謎のエラー。もうちょっと詳しく調べてからコミットします。

Mac OS X(10.4)でPHPからMySQLへ接続できない件

Mac OS Xはapacheも標準インストールされてるし、RubyとかPythonとかも入ってるみったいだけど、MySQLは入ってないのでインストールしてみた。ターミナルからMySQLを使えるのに、なぜかPHPからは接続できないと思ったら、こんな罠が仕掛けられていたようだ。
Mac OS X Server 10.4: PHP から MySQL への接続時に生じる問題

とりあえず、wordpressがインストールできたので、これで自由にテーマファイルを編集する準備が整った。が、テーマファイルを編集してる暇がなさそうだ…

新コンパイラ

boost::serializationでリンカ開発の山本さんの記事を見ても分かる通り、コンパイラの大規模な改善が行われたようで、先日開発者側に公開されました。まだ少ししか使ってませんが、なかなか良い仕上がりになっている気がします。まだ改変して間もないので思い切ったコードはかけませんが、安定すれば、確実に以前のようなコンパイラを気遣ったようなコードを書くことはなくなることでしょう。

さてさて、静的リンクライブラリのおかげで毎回すべてのコードをコンパイルすることもなく、コンパイル時間は激減したのに驚きましたが、ついでにジェネリックまで実装されてたのは予想外です。というわけで、今まで使ったことの無かったジェネリックを使ってみました。

Imports System.Collections.Generic

Dim list As List<string>
list.Add("String0")
list.Add("String1")
list.Add("String2")
list.Add("String3")

Dim string As String
Dim i As Long
For i = 0 To ELM(list.Count)
	string = string + list[i] + Ex"¥r¥n"
Next

MessageBox( 0, string, "title", MB_OK )

実行結果:

String0
String1
String2
String3

何の面白みも無く、そして妙に釈然としないコードですね。Enumeratorを使っていないのは、既にバグ報告というか、機能不足というか指摘されましたが、ジェネリックの包含ができないためです。近いうちに改善されると思われます。

ちなみに、せっかくなのでNSDictionary的な物でも作ろうかと思ったのですが、こちらもListを内部使って楽しようとしたので、コンパイルが通りませんでした。

Imports System.Collections.Generic

Class Dictionary<T>
	keys As List<string>
	values As List<T>
Public
	Function Operator[] ( key As String ) As T
		Dim index = keys.IndexOf(key)
		If index <> -1 Then
			Return values[index]
		Else
			Return Nothing
		End If
	End Function

	Sub Add( key As String, value As T )
		If keys.IndexOf(key) <> -1 Then
			keys.Add(key)
			values.Add(value)
		Else
			debug 'The key is already registered.
		End If
	End Sub
End Class

コンパイラが通らないというより、「”System.Object”から”System.Object”へ変換できません」という奇妙なエラーが発生します。

ということで、ActiveBasicにもジェネリックが搭載されたので、来るところまで来ているといったところでしょうか。あともう少しですね。私含めたライブラリ開発陣は、コンパイラが整ってから本当の勝負です。AB5リリースまで頑張っていきたいですね。

5.[ライブラリ]DateTimeクラス

最近ActiveBasicとかけ離れた話題が多くて、どうなんでしょうね?まあ、次のバージョンアップもいつになるかわからないので、マイペースにクラスの紹介をすることにします。それでは、ActiveBasic5.0CP4新機能,ライブラリ紹介の第五弾、DateTimeクラスです。

概要

DateTimeクラスは、名前の通り時刻を表すクラスです。日付から時間まで、単位はミリ秒以下の単位まで保持できます。また、付加情報として、現地時刻を表しているのか、世界時刻を表しているのかという情報も保持しています。この他に、簡単な日付や時間の計算を行うことができます。以下、WikiのDateTImeクラスと合わせてご覧下さい。

コンストラクタ

それでは、まずコンストラクタから説明します。コンストラクタとは、初期化を意味します。

Dim date1 = New DateTime(2007, 7, 7)
Dim dateTime = New DateTime(2007, 7, 7, 21, 0, 0)
MessageBox(0, date1.ToString(), "date1", MB_OK)
MessageBox(0, dateTime.ToString(), "dateTime", MB_OK)

この他にも、さまざまなコンストラクタが用意されているので、詳しくはwikiの方をご覧下さい。見て何となくわかってしまうと思いますが、date1の方は、2007年7月7日が指定されています。dateTimeの方は、2007年7月7日21時0分0秒を指定して初期化しています。

時刻を表すプロパティ

DateTimeクラスには、各々の単位の時刻を取得するプロパティが用意されています。これを使用することにより、Long型でさまざまな単位の時刻を取得することが出来ます。

Dim dateTime = New DateTime(2007, 7, 7, 21, 0, 0)
Dim year = dateTime.Year
Dim month = dateTime.Month
Dim day = dateTime.Day
Dim hour = dateTime.Hour
Dim minute = dateTime.Minute
Dim second = dateTime.Second
Dim millisecond = dateTime.Millisecond
Dim dayOfYear = dateTime.DayOfYear

Dim dayOfWeek = dateTime.DayOfWeek
debug

DayOfYearは、その年で何日目かを取得するプロパティです。また、DayOfWeekは、曜日を表し、日曜から0で始まる数字で取得されます。

便利なプロパティ

その他に、便利な静的プロパティが用意されています。

MessageBox(0, DateTime.Now.ToString(), "now", MB_OK)
MessageBox(0, DateTime.ToDay.ToString(), "today", MB_OK)
MessageBox(0, DateTime.UtcNow.ToString(), "utc", MB_OK)

上から、今日の時刻、今日の日付、今日の世界時刻を取得することができます。

時刻計算をするメソッド

DateTimeは、日付を計算する計算することができます。例えば、現在の時刻から1年後は、次のようにします。

Dim now = DateTime.Now
Dim followingYear = now.AddYears(1)
MessageBox(0, followingYear.ToString(), "1年後", MB_OK)

その他、さまざまな単位で時刻を進めることができます。

Dim date = DateTime.Now
Dim date1 = date.AddMinutes(10)
Dim date2 = date.AddHours(24)
Dim date3 = date.AddDays(-1)
Dim date4 = date.AddDays(0.5)
Dim date5 = date.AddYears(1.5)
Dim date6 = date.AddYears(100)
MessageBox(0, date.ToString(), "date", MB_OK)

dateのところを好きな値に変えて見てください。date1は普通に10分加算しているだけですが、date2は24時間、すなわち1日加算していることと同じになります。date3のように、もちろん-1日を加算することで、前日の時刻を作ることもできます。また、date4のように、0.5日、すなわち小数を指定して12時間進めることもできます。

注意すべきなのは、AddYearsです。普通に整数値を加算するときは、日付は保たれたまま西暦だけ変わりますが、小数値を指定すると、例えば、date5は1年と、半年分の日数が加算されます。この場合の半年に相当する日数は、その年が閏年かどうかで変わってしまうので、確実に計算することは難しくなります。なので、AddYearsで小数値指定することはあまり推奨しません。

演算子

DateTimeクラスには、いくつかの演算子があり、それを用いて計算したり、日付を比較することができます。ただし、演算するには、時刻ではなく、期間を表すTimeSpanクラスを用いることが多いです。

Dim now = DateTime.Now
Dim tomorrow = now + TimeSpan.FromDays(1)
MessageBox(0, tomorrow.ToString(), "tomorrow", MB_OK)

+演算子は、TimeSpanを対象にしますので、TimeSpanで時刻を指定しなければなりません。TimeSpan.FromDays(1)は、TimeSpanで一日を表します。

比較演算子で、時刻を比較することができます。

Dim date = New DateTime(2007, 7, 9)
If DateTime.Now = date Then
	MessageBox(0, "同時刻", "compare", MB_OK)
ElseIf DateTime.Now < date Then
	MessageBox(0, date.ToString() + "以前", "compare", MB_OK)
ElseIf DateTime.Now > date Then
	MessageBox(0, date.ToString() + "以降", "compare", MB_OK)
End If

変換

最後に、DateTimeクラスで表されたデータを、他のデータへ変換、またはその逆を行うメソッドを紹介します。

GetDateTimeFormats

GetDateTimeFormatsメソッドは、好きな形式で時刻を文字列に変換することができます。

Dim now = DateTime.Now
MessageBox(0, now.GetDateTimeFormats("yyyy年MM月dd日 dddd"), "title", MB_OK)

以上、数ヶ月前に書いた記事です。ToFileTimeなどの変換系のメソッドが正しく動かない原因がわからなかったので公開してませんでした。今日おそらくコンパイラのバグだと突き止めたので、次のバージョンアップまで使用することはできません。ちょうど、Wikiの方に書かれているメソッドのToFileTIme以下が該当します。

ブラウザ上での縮小画像

昨日ちょっと気になって、ブログがきちんとIEでも表示されているかWindowsで確認してみたのですが、WindowsとMacでブラウザ上の画像の表示のされ方にだいぶ違いがあることに驚きました。大きな画像を小さく表示する際、よくサムネイルとオリジナルの2つの画像が用意されているのはこのためだったんですね。


Windows XP IE7で1024*768の画像を縮小表示させた場合

windows ie6 thumbnail


Mac OS X Safari で1024*768の画像を縮小表示させた場合

Mac OS X thumbnail

いつも全く気にせず画像を縮小表示させてやっていましたが、これはちょっと不便ですね。リンク先は大きな画像、ページへ貼付ける画像は縮小用の画像を用意したほうがいいでしょうか。Windowsだと縮小画像だとよく画像がわかりませんからね。

ところで、VistaのIE7では綺麗に表示されるんでしょうか?どなたかVistaを持っている方がいれば、コメントくれたらうれしいです。あと、もしかしたらIE以外のブラウザを使うと綺麗に表示されるかもしれませんね。少なくとも、Windows版SafariではMacと同じように表示されました。

アプリケーションインストールで比較する Windows – Mac OS X

WindowsからMacへ移行したときに、アプリケーションのインストールに結構違いが見られたので、それを今日は紹介しようと思います。アプリケーションのインストールには主に、インストーラーを使ったインストールと、単純コピーのインストールがありますが、今回は単純コピーする方についてXPとMacで比較することにします。本当はVistaとMacを比較したかったのですが、Vistaは持っていないので後でにします。

今回インストールするアプリケーションは、2chブラウザにしました。WindowsはJane Style、OS XのほうはBathyScapheです。


1.各アプリケーションを公開しているサイトへ行く

Jane Style :: site

BathyScaphe :: site


2.ダウンロードする。

Jane Style :: download

BathyScaphe :: download
Safariはリンクをクリックすると即ダウンロードが始まります。Macのアプリケーションはディスクイメージ(.img)、またはディスクイメージをzip圧縮したもので配布されるのが一般的です。


3.保存先を指定する。(Windows only)

Jane Style :: saving
保存先を指定するのが少し面倒だったりするときもあります。しかも、保存した場所を見失ったりすることもよくあることです。Windowsは好きな場所に保存することができます。

Safariでダウンロードしたファイルはデスクトップに保存されます。他の場所に保存した人には不便かもしれませんが、ほとんどの場合はデスクトップで問題ありません。Macは保存先を指定する手間がありません。


5.ダウンロード中…。Windows,Macともに同じような画面です

Jane Style :: downloading

BathyScaphe :: downloading


6.解凍する

Jane Style :: unpacking
適当な解凍ソフトや、デフォルトで装備されているソフトを使って展開します。

BathyScaphe :: downloading
ダウンロード後、Macはzip,ディスクイメージともに自動的に展開,マウントされます。ダウンロードしたzipファイルは自動的にゴミ箱へ送られます。BathyScapheはzipではなく直接ディスクイメージで配布されているので、自動的にディスクイメージがマウントされます。


7.ユーザー許可(Mac Only)

BathyScaphe :: permit downloading
Macは、zip展開直前、またはディスクイメージマウント直前に、アプリケーションが含まれる場合は、続けるかどうかの許可を求めてきます。


8.適当なところへ移動する

Jane Style :: copy
ダウンロードした場所が必ずしもアプリケーションを置きたいところとは限らないので、自分の気に入る場所に移動したりします。Windowsは、このようなアプリケーションを置く場所はあらかじめ用意されていので、好きなところへ置きます。整理ができない人は散らかってしまったりします。Vistaでは検索があるので問題ないでしょう。

BathyScaphe :: copy
Macは、アプリケーションフォルダにアプリケーションをコピーします。また、ディスクイメージ上でアプリケーションを起動して確認することもできるので、コピーしてからゴミ箱に捨てるなんてことにはなりません。Macは、アプリケーションフォルダ以外のフォルダにアプリケーションを置くことももちろん可能ですが、ディスクイメージ上にアプリケーションフォルダへのエイリアスが用意されているように、アプリケーションフォルダにコピーすることが当たり前です。


インストール完了。

Jane Style

BathyScaphe


おまけ

Jane Style :: shortcut
Windowsの場合、フォルダへのアクセスがあまり簡単でないので、ショートカット(エイリアス)を作ってデスクトップに置くと、簡単にアプリケーションを立ち上げられるようになります。たくさんデスクトップアイコンがあるのはこのためです。

BathyScaphe :: spotlight
Macの場合、比較的アプリケーションフォルダへアクセスしやすく、アプリケーションがフォルダでなくてアイコンになっていて見つけやすいので、アプリケーションフォルダに置いても、Windowsよりは簡単にアプリケーションを立ち上げることが出来ます。ただ、やはりちょっと手間取るので、spotlight(デスクトップ検索)を使って立ち上げたりすることができます。Windowsも、Vistaならスタートメニューに検索が付いているので、MacとWindows、両方この方法が使えます。便利ですね。

もちろん、Macで最も簡単にアプリケーションを立ち上げる場所は、Dock(デスクトップ下に表示されているアイコン群)です。毎日使用するようなものは、Dockへ登録して使います。


アンインストール

このタイプのアプリケーションは、Windows,Macともにゴミ箱へ捨てればアンインストール完了です。Macの場合、アプリケーションの設定やデータは、/Users/username/Library/Application Support/以下に保存されていることがほとんどなので、アンインストール後、再度使うとき設定が消えてないことがほとんどです。もちろん、完全に消したい場合は、ここのアプリケーションデータも削除しましょう。Windowsの場合は、アプリケーションによってデータの保存の仕方が違うので、どのようにデータが保存されたり、保存しておくかは、アプリケーションにしだいです。


まとめ

WindowsはMacに比べてセキュリティがうるさいので、てっきり何回も警告されることを想像してたのですが、意外にMacの方が1回警告されただけで終わっています。Windowsはなんでも設定次第ということでしょうか。

WindowsとMacの大きな違いは、やはり配布のファイル形式とインストール先でしょう。Windowsは、zipでフォルダが一般的で、Macはディスクイメージでバンドル形式が一般的です。バンドル形式というのは、アプリケーションフォルダをひとつのファイルに見せかけているのもで、Macのアプリケーションが単一のファイルに見えるのはこのためです。パッケージの内容を表示すると、アプリケーションの構成が見えます。

Windowsの場合、アプリケーションを置くところは任意ですが、Macの場合はアプリケーションフォルダで決まっていると言って過言ではありません。そのためか、そでないか、Windowsはアプリケーションの整理が結構面倒になってきたり、ショートカットを無駄に作成、さらにリンク切れ、といった面倒な自体も起きたりします。

今回はこれで終了です。今度は、インストーラー型のアプリケーションで比較しようと思います。

CocoaBinding + InterfaceBuilder

アウトラインビュー(ツリービュー)を使おうと、いろいろ探しまわっていたのですが、途中からCocoa Bindingについての記事を見つけ、つい試したくなってしまったので、そちらを使ってみました。

NSOutlineView using cocoa binding.

見た目通りの動作をします。特に面白いこともしません。ついでに、テーブルビューもBindingで作ってみました。

NSTableView using cocoa binding

こちらも見た目通りの動作をします。Cocoa Bindingなので、同じ値を示すところは当然同期して動きます。上のパネルの値を操作するとテーブルビューに反映するし、テーブルビューから直接編集すると、パネルの値がそれに合わされます。

それで、これの凄いところは、Interface Buider(GUI設計)だけで作ることができる点です。つまり、1行もコードを書かずにアウトラインビューやテーブルビューを作ることができるのです。当然、コンパイルもする必要がないので、Interface BuilderのTest Interfaceで、GUIのテストをするときにも動作します。

このCocoa Bindingを利用することで、テーブルビューの使い方を知らなくても、テーブルビューを簡単に利用することができます。さらに、Core Data Applicationからプロジェクトを作成すると、もっと凄いことができるようです。下のリンク先では、とてもコードを書かずには作れそうも無いアプリケーションを、コードを書かずに作成しているようです。

本日のCocoa Core Data と Cocoa Binding の驚異

参考資料:TigerのCocoaにみるMVCの完成 – スマートなデータモデルを実現するCore Data

ちなみに、Bindingは.NET Frameworkにも存在するようなので、後で調べておきたいです。ちょっと見たところ、Cocoaのようなキー値コーディングは存在しないものの、バインディングするときのみ使える感じになっているようでした。

型付け

Wikipediaのプログラミング言語のページを見ても分かる通り、プログラミング言語によっての型付けというものは、その言語の特徴を決める一つの大きな要素だということが分かります。例えば、C++は安全でない強い静的型付け、一方Objective-Cは弱い動的型付け、ちなみに、ActiveBasicは弱い静的型付けとなっています。

私がC++を好きになれない理由の一つが、この型付けと言ってもいいでしょう。C++の安全でない強い静的型付けというものに、全く魅力を感じません。静的型付け言語全般に言えることですが、確かに静的にした方がパフォーマンスも多少上がるかもしれませんが、今時それほどパフォーマンスなんて気になりません。Cocoaは動的且つ、メッセージ式というかなりコストのかかりそうなメソッドの呼び出しなどをしているのにも関わらず、GUIはWindowsより滑らかに動いています。静的型付けがパフォーマンスに影響があるというのは、一体どんなときでしょう。

次に、型を定義することで可読性が上がることは確かです。ただし、動的型付け言語もスクリプト言語でなければ、ある程度型の定義をするので、動的型付け言語だからといって、コード中に型定義がないなんてことはありません。よって、他のクラスやメソッドの名前のほうが重要になってくるでしょう。

一番納得いかないのは、C++は強い静的型付けでコンパイルを通すだけで疲れるのに、それが実行時の安全には必ずしも繋がらないところです。何のためにコンパイルの時点で厳密な型チェックを行っているのでしょうか。Objective-Cのようにルーズな型定義でも、滅多に実行時に致命的なエラーが発生することはありません。それはObjective-Cというよりは、Cocoaがよくできていると言った方がいいのかもしれませんが、nilにメッセージを送信したり、定義されていないメソッドを送信してもデバッガにエラーが出力されるのみです。

このように考えて行くと、ジェネリックやテンプレートも、ただ言語をより複雑にしているだけに見えて、とてもとても良い解決方法には思えません。静的型付けの意味をさらになくして、悪化させているようにしか見えません。しかし、静的型付けが故の、ジェネリック、テンプレートであると認識していますけどね。

と、C++でほとんどプログラミングしたことない私の机上の空論でした。
参考資料:型システム

テーマ自作したい…

wordpressのテーマファイルを自作したいのですが、テーマファイルをテストする環境を用意するのが面倒で、どうしようかと思ったりしています。まさかこのブログでテストしながら作っていくわけにもいかないでしょうし。。。

カテゴリの使い時

Objective-Cには、継承せずにクラスにメソッドを追加することのできる、カテゴリというものが存在します。元々は、大きなクラスを機能別に分けてファイルに記述する、といった使われ方だったらしいですが、既存のクラスに機能を追加する用途でも使うことができます。

せっかくカテゴリというものがあるので、この前カテゴリを使ったコードを組んでみました。

@interface NSURL (NicoNicoDougaURL)

+ (NSURL *)URLWithNicoNicoDouga;
+ (NSURL *)URLWithDouga;
+ (NSURL *)URLWithSmileVideo;
+ (NSURL *)URLWithAmebaVision;
+ (NSURL *)URLWithPhotozou;
+ (NSURL *)URLWithGetFLV;

- (BOOL)isURLWithNicoNicoDouga;
- (BOOL)isURLWithDouga;
- (BOOL)isURLWithSmileVideo;
- (BOOL)isURLWithAmebaVision;
- (BOOL)isURLWithPhotozou;
- (BOOL)isURLWithGetFLV;

@end

CocoaのNSURLクラスに対してカテゴリを追加するコードです。NSURLは、名前の通りURLを表すクラスです。追加したメソッドの”URLWith…”で始まるのはNSURLのファクトリメソッドで、例えば”URLWithNicoNicoDouga”の場合、ニコニコ動画を表したNSURLを返すようになっています。また、”isURLWith…”で始まるものは、そのURLがそれ(With以降のURL)かどうかを判断するインスタンスメソッドです。

もちろん、これらはNSURLを継承して、NicoNicoURLというサブクラスでも定義してもいいのですが、そのときは気分でカテゴリを使ってみたわけです。こんな感じで使っています。

NSString *fieldString = [URLField stringValue];
NSURL *url = [NSURL URLWithString:fieldString];

if( [url isURLWithNicoNicoDouga] ) {
    NSLog(@"The URL is NicoNicoDouga.");
} else {
    NSLog(@"The URL is not NicoNicoDouga.");
}

使ってみると意外と気分はいいもので、独自のクラス名をわざわざ使わなくても済むところがよかったりします。ただ、既存のCocoaのNSURLに、自分のメソッドを勝手に追加するので、クラス名がNS…なので気にならない訳ではありません。また、コンパイラの設定でどうにかなるとは思いますが、デフォルトの設定では、カテゴリで定義したメソッドのところで「NSURLはメソッドに応答できないかもしれない」という警告が出たりします。

というわけで、こんな感じの使い方なら個人的にはいいと思いました。これらカテゴリで定義したメソッドは、アプリケーションの至る所で使うことができるので、そういうものはNSURLとか、Cocoa既存のものに追加する価値はあるでしょう。反対に、局所的にしか使わないメソッドなら、他のところで邪魔になるだけなので、そういう場合は継承したメソッドを使った方が賢明でしょう。

NSStringなど、一部クラスは継承できないので、そういう場合にカテゴリは役立つでしょう。継承よりカテゴリのがメソッドを呼び出すコストが少ないという話はありますが、やはり最終的にはAppleのドキュメントがたよりです。きちんと使いどころも書かれているようです。
Objective-Cプログラミング言語 : クラスの拡張