F-Script Guide - 目次 1 - 16
------------------------------------------------------------------------------------------
訳注:
F-Script Guide の以下のような内容のうち、この文書は、最初の「1 - 16 章」の部分の翻訳です。
・ 1 - 16 章: F-Script の「Smalltalk」としての機能とその使い方の解説
・17 - 21 章: F-Script の「配列言語」としての機能とその使い方の解説
・22 - 28 章: F-Script 全体に関わる機能の解説
・29 - 57 章 既存の Cocoa に対して、F-Script で独自に拡張、追加された機能(カテゴリ、クラス、メソッド)のリファレンス
------------------------------------------------------------------------------------------
1 はじめに
2 F-Script のソフトウェアアーキテクチャ
3 F-Script の使い方
4 基礎概念
4.1 リテラル表記
4.2 メッセージ送信
4.3 優先順位と括弧付け
4.4 変数 及び 式の評価の検討
4.5 式のリスト
4.6 コメント
4.7 カスケード
5 Cocoa への直接アクセス
5.1 例:描画する
5.2 例:音を鳴らす
5.3 例:ウィンドウを一つ開く
5.4 例:ちょっとしたグラフィカルアニメーション
6 グラフィカル オブジェクト ブラウザ
7 標準入出力ストリーム
8 基本データ型 の紹介
8.1 数 Numbers
8.2 文字列 Strings
8.3 配列 Arrays
8.4 真偽値 Booleans
8.5 ブロック Blocks
8.6 範囲 Ranges, 点 Points,
矩形 Rectangles 及び、大きさ Sizes
8.6.1 範囲 Ranges
8.6.2 点 Points
8.6.3 矩形 Rectangles
8.6.4 大きさ Sizes
9 制御構造
9.1 条件選択 Conditional
9.2 繰り返し Loop
10 永続化
11 カスタムクラスの統合
12 オブジェクトの同等性と同値性
13 オブジェクトの複製
14 例外
15 Objective-C マッピング
15.1 演算子 Operators
15.2 非オブジェクト型
15.3 nil オブジェクト
15.2 例外処理
15.2 シンボル定数
16 メモリの管理
F-Script Guide 1 - 16 章
1 はじめに
F-Script は、Mac OS X
オブジェクトシステム(Cocoa)に対して、手軽にスクリプティングを行なったり、対話的に操作したりする為の環境である。F-Script
は、オブジェクトの内部を覗いたり、操作したりすることができる洗練されたツール類(インタプリタやオブジェクトブラウザ)を提供する。また、独自のクラ
スを動的に定義することもできる。
F-Script の構文は Smalltalk に基づいている。そのオブジェクトモデルは、Mac OS X
のオブジェクトモデルそのものである。
この文書は、F-Script
インタプリタの前で、本文にでてくる F-Script の様々な概念を、対話的に、実験したり調べたりしながら読むと良いだろう。
注:原著者特記
F-Script は、Smalltalk や Self それに APL といくつかの言語的な特徴を共有している。
この文書の幾つかの箇所は、IBM
の Paul Berry による素晴しい APL 360 Primer か
ら直接翻案された。
また、以下の文書から直接着想を得ている箇所もある:
-
|
Inside
Smalltalk, Volume 1.
Wif R. Lalonde / John R. Pugh. Prentice Hall |
- |
The
SELF 4.0 Programmer’s
Reference Manual, Agesen / Bak / Chambers /
Chang / Hölzle / Maloney / Smith /Ungar / Wolczko. Sun Microsystem |
- |
NCITS J20 DRAFT of ANSI
Smalltalk Standard revision 1.9 |
いくつかの例題は、Les APL étendus,
Bernard Legrand. Masson から着想を得たものである。
2 F-Script のソフトウェアアーキテクチャ
(図を省略)
3 F-Script の使い方
F-Script
の標準的なパッケージには「F-Script.app」と言う名前のアプリケーションが入っている。このアプリケーションは、F-Script
インタプリタとの対話的なインタフェースで、これにはコマンドラインインタフェースとグラフィカルオブジェクトブラウザが含まれている。
コマンドラインインタフェースは、ウィンドウを表示して、読者にコマンドを入力するよう促す。コマンドを入力し終えた後、リターン
キーを押してそれを実行すると、ウィンドウは、コマンド実行の結果を表示する。例えば、「3 +
4」とタイプして、リターンキーを押してみよう。こうなるはずだ:
> 3 + 4
7
ユーザーインタフェースは読者が入力したコマンドの履歴を保持しており、いくつかの特別なキー操作で、このインタフェースを制御することができる:
キーの組み合わせ |
|
[Control +]↑
|
一つ前の履歴のコマンドを得る
|
[Control +]↓ |
一つ次の履歴のコマンドを得る |
Control + →
|
現在のコマンドの最後に移動する
|
Control + ←
|
現在のコマンドの先頭に移動する |
Control
+ BackSpace
|
現在のコマンドを削除する
|
Control + Return
|
改行する
|
Control + \
|
次の引数入力箇所に移動する
|
F5
または option + Esc
|
コード補完
|
F7
|
ペーストパースモードを切り替える(つまり、コマンドをペーストした
時、改行をコマンド区切りと見なすかどうかを決定する)
|
F8
|
カッコ付けする
|
コード補完の機構は、クラス名 や Cocoa
定数、メソッドセレクタを認識しており、新しいバンドルをロードすると、クラス名やメソッドセレクタの名称が、自動的にこの補完用リストに追加される。
グラフィカルオブジェクトブラウザを起動するには、ワークスペースメニューの「Open Object Browser」を選択すればよい。
4 基礎概念
4.1 リテラル表記
リテラル表記を評価すると、オブジェクトが生成される。
リテラル式の例:
1
-3.14
1.23e-2
|
NSNumber オブジェクト
NSNumber オブジェクト
NSNumber オブジェクト
|
'Hello'
|
NSString オブジェクト |
true
false
|
FSBoolean オブジェクト
FSBoolean オブジェクト
|
{1, 2, 'bill'}
|
FSArray オブジェクト(NSMutableArray
のサブクラス)
|
#{'one'->1, 'two'->2}
|
NSMutableDictionary オブジェクト
|
[:a :b | a + b]
#+
|
FSBlock オブジェクト
コンパクト形式の FSBlock オブジェクト |
nil
|
nil オブジェクト
|
4.2 メッセージ送信
F-Script では、メッセージを送る(つまり、メソッドを起動する)ことでオブジェクトを操作する。
F-Script のメッセージ式は Smalltalk
におけるものに似ており、メッセージの受け手、選択した操作、それに、要求された操作を実行するのに必要な幾つかの引数を記述する。メッセージ式の各要素
は、それぞれ、レシーバ、セレクタ、そして、それに続く引数と呼ばれる。
メッセージ送信の例:
5 sin
|
単項メッセージ「sin」が、値5の数値オブジェクト(レシーバ)に送
られている。
-0.95892427466313845 を値に持つ数値オブジェクトが戻る。
|
2 + 4
|
二項メッセージ「+」が、値4の数値オブジェクトを引数として、値2の
数値オブジェクトに送られている。値6の数値オブジェクトが戻る。
|
35 between:
0 and: 100
|
キーワードメッセージ「between:and:」が、値0と100の
値を持つ二つの数値オブジェクトを引数として、値35の数値オブジェクトに送られている。FSBoolean オブジェクト「true」が戻る。
|
上の例にも示されているように、F-Script は、単項、二項、
それにキーワード
メッセージとして知られる、3つの基本的なタイプのメッセージをサポートしている:
- 単項メッセージには引数がない。レシーバとセレクタがあるだけだ。
- 二項メッセージは、レシーバの他に、引数を一つ取る。二項メッセージのセレクタは一連の特殊文字で形成される。二項メッセージセレクタは、以
下の文字の組み合わせである: + - * / = >
< ~ ? % ! & | \
。二項メッセージは 演算子(オペレータ)と呼ばれることもある。
- キーワードメッセージには、一つ以上のキーワードが含まれ、各キーワード毎にそれぞれ関連する引数を一つずつ取る。キーワードは常にコロン
(:)で終わる。このコロンは名称の一部であり、特殊な終端記号ではない。
オブジェクトが実装していないメソッドを呼び出すと、その命令の実行は停止して、エラーとなる。例を示そう:
> 3 unrealMethod
error: an instance of FSNumber does not respond to "unrealMethod"
4.3 優先順位と括弧付け
メッセージ式の、レシーバや引数それ自身がメッセージ式であっても良い。そのため、複雑なメッセージ式と、その評価順序の必要性が生じる。例えば、
次のメッセージ式には、単項、二項、及び、キーワードメッセージが含まれている。
> 4 sin between: 2 * 3 and: 100
Cを含む多くの言語は、異なる演算子に割り付けられた優先順位に基づいて、式を評価する。例えば、乗法(*)には、普通、加法(+)より高い優先順
位が割り付けられている。しかし、F-Script の評価規則は(Smalltalk
と同じように)式の中で呼び出されるメッセージのタイプ(単項、二項、キーワード)に基づいている。適用の順番としては、評価は次の順に行われる。
1)カッコ付けされた式
2)単項式(左から右に評価される)
3)二項式(左から右に評価される)
4)キーワード式
注意:二項演算子の優先順位は、全て同格である
メッセージ式を完全にカッコ付けすれば、評価順位に関する曖昧さは完全に排除できる。そこで、以下の例では、各々の場合の評価順序を、完全にカッコ
付けした形式を使って説明しよう。
式
|
完
全にカッコ付けされた式
|
2 sin negated
|
(2 sin) negated |
3 + 4 * 6 + 3
|
((3 + 4) * 6) + 3 |
15 max: 32 / 3
|
15 max: (32 / 3) |
2 sin + 4
|
(2 sin) + 4 |
5 between: 1 and: 3 sin + 4
|
5 between: 1 and: ((3 sin) + 4) |
4 sin max: 4 * 6
|
(4 sin) max: (4 * 6)
|
4.4 変数 及び 式の評価の検討
F-Script
における変数名は、文字、数字とアンダースコア(_)の並びからなる単純な識別子で、文字またはアンダースコアで始まる。全ての変数はオブジェクトへの参
照である。代入式は「:=」構文要素で表される。式「x :=
4」は、値4を持つ数値オブジェクトを、ターゲットの変数に束縛する。代入式の値は、ターゲット変数に代入された値であることに注意しよう。この式の続く
式「x」は、それ自身の値に評価される。さらに続く命令「x := x + 1」は、以下の様に評価される。
1)
|
(代入式の右側の部分の)部分式「x」が評価され、x
に束縛されている値4を持つ数値オブジェクトが返される。 |
2)
|
部分式「1」が評価される:値1を持つ数値オブジェクトが生成され、返
される。 |
3)
|
ステップ1で返された数値オブジェクトの二項メソッド「+」が、ステッ
プ2で返された数値オブジェクトを引数として、起動される。数値を表すクラスは、Objective-C クラスの一つなので、メソッド「+」は
Objective-C に実装されている(実は、Objective-C
はメソッド名として「+」のようなシンボルを使うことを許していないので、F-Script
が自動的にマッピングを行って「operator_plus」というメソッドを呼び出すのだが)。このメソッドが、値5を持つ数値オブジェクトを生成して
返してくる。
|
4)
|
代入がなされる:x
は、ステップ3で返される数値オブジェクトに束縛される。
|
5)
|
ステップ3で返される数値オブジェクトが、代入式の値として返される。
|
読者は、オブジェクトを、読者の好きな、ほとんどどんな名前の変数にでも束縛できる。しかし、もしも何らかのオブジェクトを代入する前に、その変数
の値を表示しようとしたり、使おうとしたりすると、インタプリタは、その変数に関するオブジェクトを提供できない為に、その命令の実行を進めようとはしな
いだろう。インタプリタは「error: undefined identifier
xxx」という形式のメッセージで、エラーを発生させ、問題が起こったことを報告する。読者のワークスペース上のユーザーが定義した識別子のリストを得る
には、前もって定義されているオブジェクト sys に identifiers メッセージを送れば良い。
4.5 式のリスト
複数の式をドット(.)セパレータを使って繋ぐことができる。こうすることで、式のリストが創られる。
式のリストは、リスト中の最後の式の評価結果へと評価される。
例えば:「x := 3. y :=5. x + y」は、8 と評価される。シンボル「.」は、命令の区切りと呼ばれることもある。
4.6 コメント
コメントは、ダブルクオートで括られる:
"これは、コメントです"
4.7 カスケード
カスケードとは、全てが同一のオブジェクトに向けられた一連のメッセージ送信である。その一連のメッセージの最初のものだけが、明示的に指定されたレシー
バを持っている。その後に続くメッセージのレシーバは、並びの最初のメッセージのレシーバと同じオブジェクトである。その点を除けば、それぞれのメッセー
ジ送信は、カスケードの一部ではない通常のメッセージ送信であるかの様に生じる。カスケードの中の各メッセージ送信の結果返ってくるオブジェクトは、一番
右側のメッセージの結果を除き、捨てられる。カスケードの結果は、その一番右端のメッセージの返す値である。カスケードを形成するメッセージは、「;」で
区切られる。
例:
> myArray := {}
> myArray add: 99; add: 100; add: 101; count
3
> myArray
{99, 100, 101}
5 Cocoa への直接アクセス
F-Script は、Cocoa API 群への直接アクセスを提供する。
5.1 例:描画する
この例では、Cocoa のグラフィック API を使って、青い円を描いてみよう。
現在の描画色を設定する:
> NSColor blueColor set
円を描く:
> (NSBezierPath bezierPathWithOvalInRect: (500<>300 extent:
100<>100)) stroke
5.2 例:音を鳴らす
この例では、Cocoa の NSSound クラスを使って、音を鳴らしてみよう:
> (NSSound soundNamed: 'Submarine') play
5.3 例:ウィンドウを一つ開く
NSWindow を一つ開く:
> w :=
|
NSWindow
alloc initWithContentRect:
|
(100<>100
extent:300<>300) |
|
styleMask: |
NSTitledWindowMask+NSClosableWindowMask |
|
backing: |
NSBackingStoreBuffered |
|
defer: |
false |
では、これを画面に表示してみよう。
> w orderFront: nil
このウィンドウのタイトル設定は簡単だ:
> w setTitle: 'this is a nice title'
透明度を変えるには:
> w setAlphaValue: 0.5
5.4
例:ちょっとしたグラフィカルアニメーション
この例では、Cocoa のグラフィカル API を使って、ちょっとしたグラフィカルアニメーションを創ってみよう:
keyWindow := NSApplication sharedApplication keyWindow.
NSBezierPath setDefaultLineWidth: 20.
keyWindow contentView lockFocus.
1 to: 550 by: 4 do:
[:x |
path := NSBezierPath bezierPathWithOvalInRect:
(x<>130 extent: 200-(x/3)<>(x/2)).
(NSColor colorWithDeviceRed: x / 570 green:
0.1 blue: 1 - (x / 570) alpha: 1) set.
path stroke.
keyWindow flushWindow.
NSColor whiteColor set.
path setLineWidth: path lineWidth + 2.
path stroke.
].
keyWindow contentView unlockFocus.
keyWindow display.
6 グラフィカル オブジェクト ブラウザ
F-Script は、グラフィカルな操作でオブジェクトと対話できる強力なツールを提供している。この F-Script
オブジェクトブラウザは、FSSystem クラス(各対話セッションのワークスペースには、「sys」という名前で、現在のF-Script
インタプリタを表す FSSystem の特別なインスタンスが定義されている)の browse や browse:
メソッドを使って開くことができる。
例えば、数値 99 についてオブジェクトブラウザを開くには、 sys broese: 99 とタイプすれば良い。
F-Script アプリケーションの workspace メニューから「Open Object
Browser」を選択してブラウザを開くこともできる。
7 標準入出力ストリーム
stdin、stdout、stderr という3つのグローバルオブジェクトを使って、標準入出力ストリームにアクセスすることができる。
これらのオブジェクトは、NSFileHandle クラスを継承している。しかも、stdout と stderr
は、文字列を出力する便利なメソッド:-(void)print:(NSString *)string を提供する。例えば:
stdout print: 'hello world'
8 基本データ型 の紹介
このセクションでは、基本的な F-Script のデータ型のいくつかの特徴を紹介する。
8.1 数 Numbers
F-Script における数は、標準的な NSNumber オブジェクトである。 NSNumber のカテゴリ FSNSNumber
が、古典的な数学演算子(+, -, *, /)や、比較記号(>, >=, <, <=)を提供する。数の等価性は =
メソッドで、等価でないことは ~= メソッドでテストされる。また、abs sin cos ln sqrt
等の様な、いくつかの数学関数も提供されている。数値を扱う為に F-Script が提供するメソッドは、倍精度で動く。
2つの数値の大きい方を得るには、 max: メソッドを使えば良い。また、小さい方は min: メソッドで得ることができる。。
例えば:
|
> 5 max: 100
100 |
|
|
> 5 min: 100
5 |
|
数値の切り上げ、切り捨ては、こうすれば得ることができる:
|
> 5.7 ceiling
6
|
|
|
> 5.7 floor
5
|
|
8.2 文字列 Strings
F-Script における文字列は、標準的な NSString や NSMutableString である。F-Script は、Cocoa
の文字列メソッド群に加えて、古典的な比較演算子や、いくつかの文字列操作サポート機能を追加している。これらのメソッドは、NSString や
NSMutableString のカテゴリー:FSNSString と FSNSMutableString に定義されている。
例:
|
> 'aaa' <
'abc'
true
|
” 比較 ” |
|
> 'oliver' at:2
'i'
|
" インデックス指定 " |
|
> 'oliver' length
6
|
" 長さを得る " |
|
> 'oliver' reverse
'revilo'
|
" 並びの反転 " |
|
> 'Dear ' ++ 'oliver'
'Dear oliver'
|
" 文字列の連結 " |
文字列のリテラル表記は、変更ができない NSString オブジェクトを返す。
8.3 配列 Arrays
F-Script の配列は、NSArray 及び NSMutableArray オブジェクトである。F-Script
では、配列オブジェクトが非常に重要だ。というのは、 F-Script
の配列がいくつかの高度なデータ操作機能をサポートしているからである。これらの機能については、このガイドのそれぞれ対応するセクションに記してある。
NSArray のカテゴリである FSNSArray と、NSMutableArray のカテゴリである FSNSMutableArray
には、配列操作の為の数多くのメソッドが追加されている。
リテラル表記は、可変配列を返す。
配列の基本的な機能には(0 で始まる)インデクス操作、要素の追加と削除が含まれる。
例を示そう:
|
>
{1,2,3,'oliver',5*5}
{1, 2, 3, 'oliver', 25} |
" 配列リテラルを評価する " |
|
> {1,2,3,4} count
4 |
" 配列の大きさを得る " |
|
> {2,4,6,8} at:2
6 |
" インデクス操作 " |
|
> {2,4,6,8} at:4
error: index of an array must be a number less than the size of the
array
|
" 無効なインデクス操作 " |
|
> myArray :=
{1,2,3,4}
> myArray insert:'hello' at:2
> myArray
{1, 2, 'hello', 3, 4} |
" 要素の挿入 "
|
|
> myArray removeAt:1
> myArray
{1, 'hello', 3, 4} |
" 要素の削除 " |
|
> myArray at:0 put:100
> myArray
{100, 'hello', 3, 4}
|
" 要素の置換 " |
|
> {{1,2,3}, {10,11}}
{{1,2,3}, {10,11}}
|
" 配列の配列 " |
|
> {1,2,3} ++ {10,20}
{1, 2, 3, 10, 20}
|
" 配列の結合 " |
注:配列
は NSArray と NSMutableArray で表されるので、F-Script においても、配列を操作する為に、Cocoa
の標準的なメソッドを使ってもよい。しかし、このガイドを読めば分るように、F-Script
は配列言語であり、上の例に示す様なメソッドは、標準メソッドには無い、配列を扱う為に付加された力を提供する。例えば、上の例に示すように、配列のイン
デクス操作をする at: メソッドを使うと、インデクスに一つの整数を指定できるだけでなく、整数の配列を丸ごと指定できる
|
8.4 真偽値 Booleans
真偽値オブジェクト(true, false 及び YES, NO として入力できる)は FSBoolean
クラスで表される。それらは、古典的なブール演算子:AND 演算子は二項メソッド & で、OR 演算子は二項メソッド |
で、NOT演算子は、単項メソッド not を提供する。
例えば:
|
> true &
false
false
|
|
|
> true | false
true |
|
|
> false not
true
|
|
真偽値は、ブロックと共に、ifTrue: や ifTrue:ifFalse: メソッドで制御構造もサポートする。
「true」と「YES」は、どちらも値 true に評価される。
「false」と「NO」は、どちらも値 false に評価される。
8.5 ブロック Blocks
ブロックは、何らかの F-Script
コードを内部に含むオブジェクトである。コード片をカギカッコで括ることによってブロックオブジェクトを生成するのが一般的である。例えば:[x :=
x + 1] はブロックである。このブロックの内部のコードを実行するには、このブロックに value メッセージを送れば良い。例えば:
|
> x:=1 |
" x に 1 を代入 " |
|
> x
1
|
" x を評価する "
" x は 1 "
|
|
> myBlock := [x:=x+1]
|
" ブロック [x := x + 1] を myBlock
に代入する " |
|
> x
1 |
" x を評価する "
" x の値はもとのまま "
|
|
> myBlock value |
" ブロックを評価する " |
|
> x
2
|
" x を評価する "
" x の値が変化した "
|
ブロックには、パラメータがあって良い。例えば [:a :b | a + b] は、a 及び b
という名称の二つのパラメータを持つブロックである。これを実行するには、適切な value: ...
メソッドを使って、引数に値を渡す必要がある。例えば:
|
> myBlock :=
[:a :b| a + b]
> myBlock value:3 value:4
7 |
|
ブロックはまた、ローカル変数を持ち、他のオブジェクトを束縛しても良い。それらは再帰的に実行させることができる。
以下に示すのは、二つの引数と一つのローカル変数を持つブロックの例である。
|
> [:a :b|
|local| local := a + b. local * 2] value:3 value:4
14
|
|
最初の引数に対して、もう一つの引数をその引数とするようなメッセージを一つ送るだけのブロックは、ブロックリテラルのコンパクト記法を使って表しても良
い。この記法は、ブロックを、このブロックが実行された時に使う必要のあるメッセージセレクタをすぐ後ろに伴った「#」で表す。例えば、[:a :b
| a + b] は「#+」というコンパクト形式でも表すことができる。
ブロックは、それに inspect メッセージを送って独自のインスペクタを呼び出し、編集することができる。
8.6 範囲 Ranges,
点 Points, 矩形 Rectangles 及び、大きさ Sizes
Cocoa API の多くが、NSRange型、NSPoint型、NSRect型 それに NSSize型の引数や戻り値を取る。
これらの型は C の構造体として定義されているので、オブジェクトだけを扱う F-Script
からは直接操作することができない。しかし、Cocoa の NSValue
クラスが、これらの型の値をオブジェクトにラップするサポートを提供している。F-Script
は、このサポートを利用して、メソッド起動時に自動的に、このラップとアンラップを実行する。それで、F-Script
からでもNSRange型、NSPoint型、NSRect型 それに NSSize型の引数や戻り値を取るメソッドを起動できるのである。
F-Script はまた(FSNSValue カテゴリで)NSValue に、そして(FSNSNumber カテゴリで)NSNumber
に、範囲 Ranges、点 Points、矩形 Rectangles や、大きさ Sizes を扱う為のいくつかの便利メソッドを追加している。
8.6.1 範囲 Ranges
FSNSValue カテゴリで NSValue に定義されたクラスメソッド rangeWithLocation:length:
を呼び出せば、内部に NSRange のインスタンスを含む NSValue のインスタンスを F-Script から生成することができる。
例えば:
|
> myRange := NSValue rangeWithLocation:10 length:5
|
" 範囲を生成して、変数 myRange に代入 " |
|
> myRange
(Range location=10 length=5)
|
" 変数 myRange を評価 " |
|
> myRange location
10
|
" 範囲 myRange の開始位置 location を尋ねる
" |
|
> myRange length
5
|
" 範囲 myRange の幅 length を尋ねる "
|
|
> myRange = (NSValue
rangeWithLocation:10 length:5)
true
|
" myRange が別の範囲と同じかを比較判定する " |
8.6.2 点 Points
ある数に対して、もう一つの数を引数にして <> メソッドを呼び出せば、内部に NSPoint のインスタンスを含む NSValue
のインスタンスを F-Script から生成することができる。
このメソッドは、x 座標がレシーバの値に等しく、y 座標が引数の値に等しい point オブジェクトを生成して返す。
point オブジェクトにメッセージ x や y を送って、その x 座標や y 座標を尋ねることができる。
例えば:
|
> myPoint :=
100<>150
|
" ある点を生成して、変数 myPoint に代入 " |
|
> myPoint
(100<>150) |
" 変数を評価 " |
|
> myPoint x
100
|
" 点 myRange の x 座標を尋ねる " |
|
> myPoint y
150
|
" 点 myRange の y 座標を尋ねる " |
|
> myPoint=(100<>150)
true
|
" myPoint
が別の点と同じかを比較判定する。必ずカッコで括
らなければならない。さもないと、式は (myPoint = 100) <>
150 と解釈されてしまう " |
注:Smalltalk では、点は伝統的に<> ではなく @ 演算子を使って生成される(つまり、100<>150
ではなく 100@150 とタイプする)。しかし、F-Script では、シンボル @
は、メッセージングパターンを指定する為に使われるので、演算子としては使うことができない。
|
8.6.3 矩形 Rectangles
ある NSPoint オブジェクトを含む NSValue オブジェクトの extent: や corner: メソッドを、別の point
オブジェクトを引数にして呼び出せば、NSRect オブジェクトを含む NSValue オブジェクトを F-Script
から生成することができる。
extent: メソッドは、その原点がレシーバで、その幅と高さが引数で与えられる矩形を生成して返す。
corner: メソッドは、その原点がレシーバで、その対角が引数の矩形を生成して返す。
矩形オブジェクトに対して、その extent(矩形の幅と高さで定義される point オブジェクト)や corner(原点の向かいの角を表す
point オブジェクト)を尋ねることができる。
例えば:
|
> myRect :=
100<>150 extent:20<>20 |
" 矩形 rectangle を生成し、変数 myRect
に代入する " |
|
> myRect2 := 100<>150
corner:120<>170 |
" 矩形 rectangle を生成し、変数 myRect2
に代入する " |
|
> myRect
(100<>150 extent:20<>20)
|
" 変数 myRect を評価する " |
|
> myRect extent
(20<>20)
|
" 矩形 myRect に幅と高さ extent を尋ねる " |
|
> myRect corner
(120<>170)
|
" 矩形 myRect に対角座標 corner を尋ねる " |
|
> myRect origin
(100<>150) |
" 矩形 myRect に原点座標 origin を尋ねる " |
|
> myRect = myRect2
true |
" 矩形 myRect は矩形 myRect2 と同じか "
|
8.6.4 大きさ Sizes
FSNSValue カテゴリで NSValue に定義されたクラスメソッド sizeWithWidth:height: を起動すれば、
NSSize を含む NSValue オブジェクトを F-Script から生成することができる。ある size オブジェクトに対して、その幅
width と高さ height を尋ねることができる。
例えば:
|
> mySize :=
NSValue sizeWithWidth:20 height:30 |
" 大きさ size を生成して、変数 mySize に代入 "
|
|
> mySize
(Size width=20 height=30)
|
" mySize を評価 "
|
|
> mySize width
20
|
" 大きさ mySize に幅 width を尋ねる "
|
|
> mySize height
30
|
" 大きさ mySize に高さ height を尋ねる "
|
|
> mySize = (NSValue
sizeWithWidth:20 height:30)
true
|
" 大きさ mySize が他の大きさと等しいか比較判定する "
|
9 制御構造
多くの言語とは異なり、旧来の条件や繰り返しの制御構造を記述するために付加的な構文構造を追加する必要はない。これらの制御構造は、F-Script
では、オブジェクトとメッセージ送信の言葉で実装されている。特に、ブロックと真偽値 Boolean
オブジェクトが、必要なサポートを提供する。また、F-Script
はこの節で説明するものより高レベルの制御構造もいくつか提供している;実はその為に、F-Script では、他の言語に比べて、明示的に if や
while 型の構造が使われる頻度は非常に少ない。
9.1 条件選択 Conditional
条件選択は、真偽値 Boolean オブジェクトに対して、普通、引数に二つのブロックを取って、ifTrue:ifFalse:
メッセージを送ることで表現される。真偽値オブジェクトは、送られたメッセージに対し、適切な方のブロックを評価して、応答を返す。もし、真偽値の値が
true ならば、最初のブロックが評価され、二番目のブロックは無視される。その一方で、もし、真偽値の値が false
ならば、二番目のブロックが評価され、最初のブロックは無視される。最終的には、選ばれたブロックの評価結果が返されることになる。
以下に、条件選択に関する F-Script コードと C のコードを対比させて示す。
F-Script
|
C |
number1 < number2 ifTrue:
[
maximum :=
number2.
minimum := number1.
]
ifFalse:
[
maximum := number1.
minimum := number2.
] |
if
(number1 < number2)
{
maximum = number2;
minimum = number1;
}
else
{
maximum = number1;
minimum = number2;
}
|
真偽値オブジェクト true 及び false は、また、単一のキーワードメッセージ ifTrue: も受け入れる。真偽値 true
は、ブロック引数の値を返すことでメッセージに応答し;false は、特別なオブジェクト nil を返してメッセージに応答する。
ifFalse: や ifFalse:ifTrue: というメソッドも存在する。
9.2 繰り返し Loop
F-Script は、C の while 文に相当する条件繰り
返しを提供する。これもまたブロックを基礎にしていて、ブロックがオブジェクトで、それ自身のメッセージプロトコルをサポートできるという事実を利用して
いる。
100 までの整数の和を計算する以下のプログラム片を考察してみよう:
F-Script |
C |
sum := 0.
number := 1.
[number1 <= 100] whileTrue:
[
sum := sum +
number.
number := number + 1.
]
|
sum = 0;
number = 1;
while (number <= 100)
{
sum = sum + number;
number = number + 1;
}
|
whileTrue:
メッセージを受け取るブロックは、繰り返し、自分自身を評価し、終了条件にまだ出会わなければ、引数のブロックを評価する。(引数無しの)
whileTrue、whileFalse それに whileFalse: メソッドも存在する。
F-Script はまた(NSNumber のカテゴリ)FSNSNumber カテゴリが提供する to:do: や to:do:by:
メソッドの形式で、for 文のようなものも提供している。
F-Script |
C |
sum := 0.
1 to: 100 do:
[:i |
sum := sum + i.
]
|
sum = 0;
for (i = 0; i <= 100; i++)
{
sum = sum + i;
}
|
10 永続化
save: や save メッセージを使えば、オブジェクトをファイルに保管することができる:
|
> myObject
save: 'myFile' |
" myObject を指定したファイルに保管する "
|
|
> myObject save |
" ファイルブラウザを開き、選んだファイルに保管する "
|
load: や load を既定のオブジェクト sys に送れば、オブジェクトをロードすることができる。
|
> myObject :=
sys load: 'myFile' |
" 指定ファイルに保管したオブジェクトをロードする "
|
|
> myObject := sys load |
" ファイルブラウザを開き、選んだファイルからロードする"
|
F-Script は、オブジェクトの保管に NSArchiver を使用する。そのため、保管されるオブジェクトは、標準的な Cocoa
NSCoding プロトコルに準拠していなければならない。生成されるファイルは、標準的な NSArchiver ファイルなので;Cocoa
NSUnarchiver API を使えば、他のアプリケーションでも、アーカイブされたオブジェクトをロードすることができる。
訳注:save:ファイル名 や
load:ファイル名
の「ファイル名」には、ルートからのフルパスで、パスを指定することができる。ホームディレクトリを「~」と略記した「~/」のような表現は使えない。ま
た、ファイル名だけを指定すると、ルートの直下(Macintosh HD 直下)と解釈される。
11 カスタムクラスの統合
F-Script は、読者が創ったカスタムクラスを自動的にシステムに統合することができる。読者は、自分のクラスを含むバンドルを
F-Script リポジトリの中に置くだけで良い。このリポジトリは、F-Script.app を初めて起動した時に、F-Script.app
によって創られ、デフォルトでは、それは「~/Library/Application Support/F-Script」(~
はホームディレクトリ)になるだろう。読者は、自分のバンドル(フレームワーク丸ごとであっても良い)を「~/Library/Application
Support/F-Script/classes」ディレクトリの下に置くのである。
F-Script
の起動時に、自動的にインタプリタがこれらのバンドルに繋がるのだ。読者は、望むだけ多くのバンドルを、このリポジトリに置くことができる。
もちろん、クラスを動的にロードする為に、標準的な Cocoa メソッドを使っても良い。例えば、以下の F-Script 命令は、GLUT
フレームワーク(OpenGL ユーティリティキット)を動的にロードする。
(NSBundle bundleWithPath:'/System/Library/Frameworks/GLUT.framework')
load
64bit での実行を要求するフレームワークは(64bit ハード上ではデフォルトの)64bit で動作中の F-Script
の中でロードしなければならない。32bit 用のフレームワークに対しては、 F-Script を 32bit
モードで起動する必要がある。これは、他のアプリと同じやり方で実行すれば良い: F-Script のファインダインスペクタ(訳注:ファインダのメニューで「ファイル」>「情報を見る」)を
開いて、「 32bit
モードで開く」にチェックを入れる。自動ガベージコレクションモードで実行する必要のあるフレームワークもあるし、参照カウントモードで実行する必要のあ
るものもある。F-Script のプリファレンスパネルを使えば、F-Script.app が正しいモードで実行されるよう設定することができる。
12 オブジェクトの同等性と同値性
同等性 identity は、== と ~~ メソッドを使ってテストすることができる。==
メソッドは、レシーバと引数が、メモリ内の同一のオブジェクトなら true を返し、そうでなければ false を返す。~~
メソッドは、レシーバと引数が、メモリ内の同一のオブジェクトでないなら true を返し、そうでなければ false
を返す。これらのメソッドは、NSObject のカテゴリ FSNSObject の中で定義されているので、全てのオブジェクトで使うことができる。
同値性 equality は、Cocoa では isEqual: メソッドで定義されている。F-Script
でもこのメソッドを使うが、利便性の為に、F-Script で提供されるクラスやカテゴリの中には、isEqual:
で定義されているのと同じ同値性と非同値性のテストの為に、= や ~= メソッドも実装しているものもある。この = や ~= メソッドは、
NSNumber、NSString、NSDate、NSValue、FSBoolean、FSPointer、FSBlock、...
等のクラスで提供されている。
自分のクラスの中で isEqual: を実装しても良いのと同様、 = や ~= を実装しても良い。
訳注:同値性 equality
が、異なるインスタンスであってもその「値」が等しいことを指すのに対し、同等性 identity は、全く同一のインスタンスであることを指す
13 オブジェクトの複製
setValue: メッセージはレシーバの値に、引数の値を設定する。通常、レシーバと引数は同じクラスでなければならない。
F-Script のほとんどの組み込みクラスは、setValue: メソッドを実装している。
訳注:obj2 setValue: obj1
とすることによって、obj2 は obj1 の複製になる。この場合、obj2 = obj1 → YES だが、obj2 == obj1 →
NO である。
つまり、obj2 は、obj1 と同じ値を持つ別のインスタンス(複製)になったのである。
14 例外
F-Script は、Objective-C の例外モデルを使って、例外の発生や処理を行う。F-Script
例外ハンドラを定義するには、FSBlock クラスの onException:
メソッドを使用する。このメソッドは、引数としてブロック(例外ハンドラ)を取る。このメソッドは、まずレシーバを評価して、レシーバの処理の何処かで例
外が生じた場合に、ハンドラが評価される。
もし、ハンドラが引数を持っていれば、その引数には実際の例外が渡される。
一般的な表記法:
[例外が発生するかも知れないブロック] onException: [:exception | 例外処理コード]
例:
" ゼロによる除算で例外を発生させ、それを記録して、音を鳴らしてみよう "
[ 1/0 ] onException:[:e | sys beep. stdout print:e description]
明示的に例外を発生させる為には、NSException API を使えば良い。例を示そう:
(NSException exceptionWithName:'MyException' reason:'testing'
userInfo:nil) raise
15 Objective-C マッピング
F-Script は Objective-C のオブジェクトモデルに基づいている。しかし、ある状況下においては、F-Script と
Objective-C の間でマッピングが必要になる。
15.1 演算子 Operators
Objective-C は、メソッドセレクタとしては、アルファベットでないシンボルをサポートしていない。F-Script
でそのようなセレクタを使うと、アルファベットを使ったセレクタを生成する為にマッピングが実行される。セレクタ名の形成に使われる可能性のあるアルファ
ベッ
トでないシンボルは、それぞれ以下の表に示すようなアルファベット名を持っている。このアルファベット名が、アルファベットを使った
Objective-C セレクタを生成する為に使われる。
シ
ンボル
|
ア
ルファベット名
|
+
-
<
>
=
*
/
?
~
!
%
&
|
\
|
plus
hyphen
less
greater
equal
asterisk
slash
question
tilde
exclam
percent
ampersand
bar
backslash
|
マッピングは、区切り記号に「_」を使い、シンボルの名称を追加するように行われる。
Objective-C のセレクタ名は「operator_」で始まり、「:」で終わる。
例:
演算子
|
+
|
は
|
operator_plus:
|
にマップされる
|
演算子 |
-
|
は
|
operator_hyphen: |
にマップされる |
演算子 |
++
|
は
|
operator_plus_plus: |
にマップされる |
15.2 非オブジェクト型
F-Script では、メッセージの全ての引数や戻り値はオブジェクトである。しかし、Objective-C
はオブジェクト型の他に、非オブジェクト型もサポートしており、非オブジェクト型を使う Objective-C メソッドを F-Script
から呼び出せるようにする為には、オブジェクトの引数は非オブジェクトの引数にマップされなければならないし、非オブジェクトの戻り値はオブジェクトの戻
り値にマップされなければならない。このマッピングは、自動的に行われる。
メ
ソッドが期待している引数の型は
|
メ
ソッドに提供すべき引数の型は
|
char
(BOOL を含む)
|
NSNumber または FSBoolean
|
unsigned char
|
NSNumber
|
short
|
NSNumber |
unsigned short(unichar を含む)
|
NSNumber または 一文字だけの NSString
|
int
|
NSNumber |
unsigned int
|
NSNumber |
long
|
NSNumber |
unsigned long
|
NSNumber |
long long
|
NSNumber |
unsigned long long
|
NSNumber |
float
|
NSNumber |
double
|
NSNumber |
_Bool
|
FSBoolean
|
SEL
|
FSBlock のコンパクト形式
|
NSPointer または CGPoint
|
NSValue(内部に NSPoint を持つ) |
NSSize または CGSize
|
NSValue(内部に NSSize を持つ) |
NSRect または CGRect
|
NSValue(内部に NSRect を持つ) |
NSRange
|
NSValue(内部に NSRange を持つ)
|
CGAffineTransform
|
NSAffineTransform
|
pointer(例えば int *)
|
FSPointer か nil(nil は NULL
にマップされる)
|
Objective-C
メソッドの戻り値の型は
|
F-Script
における戻り値の型は
|
char
(BOOL を含む)
|
NSBoolean
|
unsigned char
|
NSNumber
|
short
|
NSNumber |
unsigned short(unichar を含む)
|
NSNumber
|
int
|
NSNumber |
unsigned int
|
NSNumber |
long
|
NSNumber |
unsigned long
|
NSNumber |
long long
|
NSNumber |
unsigned long long
|
NSNumber |
float
|
NSNumber |
double
|
NSNumber |
_Bool
|
FSBoolean
|
SEL
|
FSBlock のコンパクト形式
|
NSPoint または CGPoint
|
NSValue(内部に NSPoint を持つ) |
NSSize または CGSize
|
NSValue(内部に NSSize を持つ) |
NSRect または CGRect
|
NSValue(内部に NSRect を持つ) |
NSRange
|
NSValue(内部に NSRange を持つ)
|
CGAffineTransform
|
NSAffineTransform
|
C ポインタ(例えば int *)
|
FSGenericPointer か nil(nil は
NULL にマップされる)
|
void
|
FSVoid
|
このマッピング仕様は Objective-C の全ての型をカバーしてはいない。そうした F-Script
がカバーしていない非オブジェクト型の引数や戻り値を使う Objective-C メソッドは、F-Script から直接呼び出すことはできない。
15.3 nil オブジェクト
特殊な Objective-C の値である nil にも F-Script は対応している。F-Script から nil
にメッセージを送ると、それぞれレシーバが nil かどうかを判定させる為のメッセージ(12 節の「オブジェクトの同等性と同値性」を見よ)である
== 及び ~~ の場合を除き、常に nil を返す。
15.2 例外処理
Objective-C の例外は、それが例外ハンドラ(14 節を見よ)によって処理されない場合は、インタプリタによって、F-Script
実行エラー(このガイドのリファレンス編 FSInterpreter 及び FSInterpreterResult
クラスを見よ)として報告される。
もしF-Script.app
からインタプリタが使われていて、例外が発生し、例外ハンドラで処理されなければ、現在の命令の実行は停止され、ユーザーには、例外の内容を説明するメッ
セージが表示される。
15.2 シンボル定数
Cocoa には、数多くのシンボル定数(例えば、NSNotFound)が定義されている。それらのほとんどは F-Script
の中でも事前に定義されており、F-Script から直接使うことができる。
16 メモリの管理
Cocoa
の実行形式は、自動ガベジコレクションを有効にするか、代わりに、マニュアル参照カウントの枠組みを使って実行することができる。どちらの場合でも、F-
Script は、その実行形式を稼働させている Cocoa メモリ管理システムのルールに従う。
F-Script のスタンドアロン版である F-Script.app
は、自動ガベジコレクションを使っても、参照カウントモードででも、どちらでも動かすことができる。ほとんどの場合、読者は、自動ガベジコレクションを使
い
たいと思うだろう。それは、このモードが参照カウントモードの制約や複雑さから読者を解放してくれるからである。しかし、参照カウントモードを使わざるを
得ない
場合もある。例えば、自動ガベジコレクションに対応した設計がなされていない既存のクラスをロードせざるを得ない様な場合である。
参照カウントモードでは、オブジェクトをある変数に代入するとそれを retain
し、同じ変数に別のオブジェクトを再代入したらそれを release するという作業を、F-Script
が自動的に実行してくれる。但し、例外がある:F-Script
クラスのメソッド中で、Objective-C
のクラスから継承したインスタンス変数にオブジェクトを代入する場合だ。この時には、Objective-C
ではそうするのと同様に、自分で、そのオブジェクトの retain や release の面倒を見る必要がある。
参照カウントモードでは、ブロックオブジェクトへの参照を生成する際、循環参照が発生しないようにする為に、ある特別な手当てが必要になる。ブロックオブ
ジェクトは、自分を囲んでいるブロックや自分を生成したメソッドが自分を起動したことを記録した参照カウントを維持しているので、もしも、その起動処理の中に、こ
のオブジェクトへの参照があると、循環参照が生じて、メモリリークを引き起すのである。そのような循環参照を避ける為、そうしたブロックへの参照は、使
い終ったら必ず破棄しなければならない。例えば、以下の例の場合、ローカル変数「internalBlock」が内部のブロックを保持してしまう
為、メモリリークを生じることになる。
[ | internalBlock |
internalBlock := [ 'hello' ].
... 何らかの処理 ...
] value.
メモリリークを避ける為には、例えば以下の様に、外側のブロック(やメソッド)の処理の最後で、使い終えた内部のブロックへの参照を破棄すれば
よい:
[ | internalBlock |
internalBlock := [ 'hello' ].
... 何らかの処理 ...
internalBlock := nil.
] value.