脳・神経系などの未知のシステムの構造,機能を解明するには,信号解析,モデリング・シミュレーション等が必要です.これらを容易に扱うことができるように,数式処理と文章作成の統合システムである Mathematica,計測制御とデータの収録,解析,および表示を行うための LabVIEW,データ解析とビジュアライゼーションのための AVS など,様々なソフトウェアシステムが整備されてきています.しかし,これらのソストウェアシステムを用いて,一貫した処理を行う場合,他のシステムとのデータ変換が必要であり,全体の効率が著しく低下してしまいます.一方,SATELLITE 言語では,シミュレータや信号処理パッケージなどのアプリケーション・ソフトウェアを SATELLITE 言語の外部関数として位置付け,API (Application Program Interface) 仕様に沿って構成することで,全く異なるアプリケーション・ソフトウェアであっても,一貫した処理を行うことが可能になります.
また,生体システムにおいては,(多次元) 時系列やマトリックスのようにいくつかの要素からなるデータ集合が解析対象となります.SATELLITE 言語では,こうした時系列データを扱えることが特徴です.さらに,実数型,文字列型等のデータの型に関わらず,同一の処理をデータに施すことも可能です.
SATELLITE 言語の処理系はインタプリタであり,計算機と対話を行いながら処理 (解析) を行うことができます.プログラムは,端末またはファイルから読み込まれると,いくつかのフェーズを経てスタックマシンのコードに変換されます.スタックマシンコードは,スタックマシンにより実行されます.従って,for 文,while 文等の繰り返し処理や関数等は,幾分高速に実行されます.内部構成を 図 2.1. 「処理系の内部構成」 に示します.
本処理系は,プログラムが構文規則どおりに記述されていれば受理し,スタックマシンコードに変換・実行します.しかし,エディタの使用,ファイル名の確認,ディレクトリの移動等,外部コマンドを使用したい状況が頻繁に起こることは明らかです.したがって,行頭に現れるトークンが未定義で,かつ代入文でない限り,外部コマンドとして解釈して処理を行います.
Windows
MacOS X/Linux/FreeBSD
以下のコマンドを入力することで,SATELLITE を実行することができます.
% /usr/local/satellite4/bin/sl4
SATELLITE 起動後の様子を 図 2.6. 「SATELLITE 起動後の様子」 に示します.
本処理系は以下に示すように "exit" とタイプすることにより終了することができます.また,行頭で Ctrl-D (CTRL キーと D を同時に押す) を入力によっても終了できます.
[]SATELLITE[]~/home/demo:[1]% exit []SATELLITE[]~/home/demo:[2]% ^D
起動時には,システムが用意したシステムリソースファイル rc.sl
が読み込まれたあとに,セットアップファイル setup.sl
が自動的に読み込まれます.このとき,セットアップファイルはユーザ設定ディレクトリ以下にユーザセットアップファイルを配置することにより,ユーザが内容を自由に変更することができます.一般的には,rc.sl
にはシステムモジュールの定義,setup.sl
にはユーザモジュールの定義・読み込み,エイリアス,サンプリング周波数,よく使用する関数定義,常に同じ意味で使用する変数定義などを記述します.
また,終了時には,クリーンファイルが実行され,その後,システムモジュールの終了関数の実行,システムコモンエリアの開放,システムパラメータエリア (テンポラリディレクトリ) の破壊,全ての子プロセスに対する終了シグナルの発信等が行われた後,コマンド実行履歴がセーブされます.
各設定ファイルの配置場所は以下の通りです.
システムリソースファイル
Windows : %INSTDIR%[1]\etc\rc.sl
MacOS X/Linux/FreeBSD : ${prefix}[2]/etc/satellite4/rc.sl
システムセットアップファイル
Windows : %INSTDIR%/etc/setup.sl
MacOS X/Linux/FreeBSD : ${prefix}/etc/satellite/setup.sl
ユーザセットアップファイル
Windows : Document and Settings\%USERNAME%[3]\Application Data\SATELLITE4\setup.sl
MacOS X/Linux/FreeBSD : ~/.sl4rc/setup.sl
システムクリーンファイル
Windows : %INSTDIR%/etc/clean.sl
MacOS X/Linux/FreeBSD : ${prefix}/etc/satellite/clean.sl
ユーザクリーンファイル
Windows : Document and Settings\%USERNAME%\Application Data\SATELLITE4\clean.sl
MacOS X/Linux/FreeBSD : ~/.sl4rc/clean.sl
SATELLITE 起動時に引き数を指定することにより,いくつかの挙動を変更できます.以下に SATELLITE 起動時の引き数を示します.
- : 標準入力 (端末) からプログラムの読み込みを行います.
-rc : システム rc ファイルを読み込みません.
-setup : ユーザ setup ファイルを読み込みません.
-clean : ユーザ clean ファイルを読み込みません.
-help : 起動オプションの説明を表示します.
また,ユーザセットアップファイルの他に自動的に読み込ませたいファイルがあれば
% sl4 setup2.sl -
とします.引数の最後に "-" がなければ標準入力 (端末) からの読み込みは行われず実行終了と同時に処理系も終了します.
SATELLITE で利用される環境変数を以下に示します.
SL_HOME
この環境変数で指定されたディレクトリをホームディレクトリとし,起動時に読み込まれる設定ファイルの格納場所などをこのディレクトリから検索します.この環境変数が指定されていなければ,SATELLITE は,システムの提供するホームディレクトリ 環境変数 HOME を利用します.また,Windowsでは,SL_HOME や HOME が設定されていない場合 My Documents\My SATELLITE を使用します.
SL_TEMP
この環境変数で指定されたディレクトリに作業ディレクトリ (SATELLITE-Langxxxx
) を作成し,実行中に作成される一時ファイルの格納場所に利用します.この環境変数が指定されていなければ,SATELLITE は,システムの提供するテンポラリディレクトリを使用します.
インタプリタは,ユーザのプログラム入力を催促するためにプロンプトを表示します.プロンプトには,以下に示すような SATELLITE 言語のプロンプトであることを明示する文字とカレントディレクトリ名,行番号が含まれます.カレントディレクトリ名はプロンプトが長くなるのを防ぐために最後の 2 つのパスだけ表示されます.完全なパス名でないときには,パス名の前に "~" がつき,それ以外は絶対パスを示すために "/" からはじまるパス名が使用されます.例えば,
[]SATELLITE[]~/home/demo:[1]% cd Tex []SATELLITE[]~/home/demo/Tex:[2]%
です.また,プログラムが 1 行で終らず継続する場合には "+" のプロンプトで催促されます.例えば,
[]SATELLITE[]~/home/demo:[3]% n=0 []SATELLITE[]~/home/demo:[4]% for( i = 0; i < 10; i++) {
と入力した場合,
+
と表示されます.この時,
n = n + 1 }
と入力することで,式が評価され,処理が終了します.
端末からの対話的なプログラム入力においては,文字の削除,挿入等を処理するマクロライン・エディタが快適な環境を提供します.
このラインエディタは,内部にエディットバッファを持っており,編集作業は全てこのバッファ内で行われます.エディットバッファは通常ユーザが入力した文字列と一致し,エディット行 (プロンプトより後ろ) に表示されます.
●エディット行の編集
本処理系においては対話処理を円滑にすすめるため,GNU-Emacs ライクな操作性をもつマイクロ・ラインエディタを装備しています.すなわち,エディット行は常にインサートモードになっており,^F,^B,^A,^E によりカーソルを移動し編集できます.また,DEL,^H (BS),^K により文字の削除等を行うことができます.但し,^ はコントロールキーを押した状態であることを示しています.例えば,
[]SATELLITE[]~/home/demo:[1]% n=0
を入力した時,カーソルは 0 の右隣にあります.ここで,^H を入力することにより,0 が消去され,カーソルはひとつ左に移動します.すなわち,0 が存在した位置です.一方,^B を入力することにより,0 は消去されずに,カーソルはひとつ左に移動します.また,^A を入力することにより,行頭すなわち n の位置にカーソルが移動します.このように,GNU-Emacs ライクな操作を行うことが可能です.キーバインドの一覧を 表 2.1. 「キーバインド一覧」 に示します.
表 2.1. キーバインド一覧
イベント | キーバインド |
---|---|
set mark | ^@ (Ctrl-SPACE) |
begining of line | ^A |
backward char | ^B,← |
interrupt | ^C |
delete char | DEL |
end of file | ^D |
file listup | ^D |
end of line | ^E |
forward char | ^F,→ |
backward delete char | ^H,BS |
newline | ^J,^M |
kill line | ^K |
search next history | ^N,↓ |
search prev history | ^P,↑ |
transpose chars | ^T |
yank kill | ^Y |
kill region | ^W |
filename completion | TAB |
command completion | TAB |
●ヒストリの検索
端末から入力されたプログラムは,ヒストリとしてバッファに記録されます.^P によりヒストリバッファをわたってエディットバッファへヒストリをコピーすることができます.また,^N は,ヒストリバッファを順方向へ検索します.ヒストリバッファからエディットバッファにコピーされたプログラムは,自由に編集,実行することができます.
例えば,
[]SATELLITE[]~/home/demo:[2]% n = 0 []SATELLITE[]~/home/demo:[3]% j = 0
を入力したとします.ここで,^P を入力することにより,
[]SATELLITE[]~/home/demo:[4]% j = 0
を表示されることができます.再び,^P を入力することにより,
[]SATELLITE[]~/home/demo:[5]% n = 0
を表示させることができます.また,ここで,^N を入力することにより,
[]SATELLITE[]~/home/demo:[6]% j = 0
を表示させることができます.
あらかじめエディットバッファに文字列が入力されている場合は,先頭がその文字列とマッチするヒストリだけ呼び出されます.例えば,
[]SATELLITE[]~/home/demo:[7]% n = 0 []SATELLITE[]~/home/demo:[8]% j = 0
を入力したとすると,ここで,^P を入力することにより
[]SATELLITE[]~/home/demo:[9]% j = 0
が表示されます.
●ファイル名,キーワードの補完
関数を入力する際に,エディットバッファの先頭において文字列を入力したあと,TAB を入力すれば,文字列に一致する実行可能な関数名もしくは外部コマンド名を補完できます.このとき,補完すべき残りの文字列に対して複数の選択肢がある場合,一致するところまでが端末に表示されます.
[]SATELLITE[]~/home/demo:[10]% ii[TAB] []SATELLITE[]~/home/demo:[11]% iir
このとき,^D を入力すれば,残りの補完対象の選択肢一覧が表示されます.
[]SATELLITE[]~/home/demo:[12]% iir^D iir() iirmake()
引き続き,ユニークに一致する続きの文字を入力したあと,再度 TAB を入力すれば,補完が完了します.
[]SATELLITE[]~/home/demo:[13]% iirm[TAB] []SATELLITE[]~/home/demo:[14]% iirmake
●ファイルのリストアップ機能
文字の入力途中に ^D を入力すれば,ファイル名をリストアップすることができます.この機能は,プログラムを記述している途中でのファイル名の確認や,ディレクトリ変更 (cd コマンド) を利用する時に有効です.例えば,
[]SATELLITE[]~/home/demo:[15]% cd /home/okumura/TeX/
と入力したあと,/home/okumura/Tex/ の下にあるサブディレクトリ名が知りたいときには,^D を入力することにより,以下に示すように文字列の入力を中断する事なく確認することができます.
[]SATELLITE[]~/home/demo:[16]% cd /home/okumura/TeX/^D DSP/ report1.tex report2.tex report3.tex RETINA1/ RETINA2/ work1.tex work2.tex work2.tex []SATELLITE[]~/home/demo:[17]% cd /home/okumura/TeX/
この時ディレクトリは "/" が付けられます.また,実行可能なファイルには "*" が,さらに MacOS X/Linux/FreeBSD 環境では,シンボリックリンクには "@" が,ソケットには "=" がそして FIFO (名前付きパイプ) には "|" が,キャラクタデバイスには "%" が,ブロックデバイスには "#" がそれぞれ最後に付けられます.一覧が表示された後,入力中のコマンドが再表示されます.
さらに,ある文字からはじまるファイルの一覧を知ることもできます.ユーザが次のように入力すると,
[]SATELLITE[]~/home/demo:[18]% cd /home/okumura/TeX/RE^D /home/okumura/RETINA1/ /home/okumura/RETINA2/ []SATELLITE[]~/home/demo:[19]% cd /home/okumura/TeX/
このように "RE" から始まる全てのファイルとサブディレクトリが表示されます.
●外部コマンドの呼びだし
本処理系では,行頭に予約語や変数として登録されていないトークンが現れたときには外部コマンドとして取り扱い,UNIX のシェル (Windows ではコマンドプロンプト) と同じ感覚で外部コマンドを扱うことができます.すでに外部のコマンドと同じ名前の変数が登録されている場合には,行頭に相対パス,もしくは絶対パスを付けて明示的にコマンドを実行することで名前の衝突を回避できます.
簡易ラインエディタにより編集された文字列は,次にプリプロセッサへ引き渡されます.ここでは,主に 「 エイリアス置換 」,「 SATELLITE 関数のパラメータの読み込み 」が行われます.
エイリアス置換
あらかじめエイリアスが定義されている場合に,入力されたコマンドのトークンの置換を行います.
関数パラメータの取得
SATELLITE 言語の特徴であるインタラクティブに関数パラメータの説明を表示しながら入力を催促する機能です.詳細は 項9.1. 「パラメータ補完機能」で述べます.
ここでは,算術演算を行う SATELLITE 言語の操作方法について述べます.例えば,3 と 6 の乗算を行うには,以下に示すように 3*6 を入力することで,乗算結果が表示されます.
[]SATELLITE[]~/home/demo:[1]% 3*6 18
また,3 を 6 で除算するには,^P を入力すれば,前回入力した行が,
[]SATELLITE[]~/home/demo:[2]% 3*6
と表示されるので,^B および^D を用いて "*" を "/" に変更することで,以下に示すように除算結果が表示されます.
[]SATELLITE[]~/home/demo:[3]% 3/6 0.5
実環境から観測されたデータ,もしくはシミュレーション等で得られたデータは,時間的・空間的,又は何らかの変化に伴う多次元の系列です.従って 1 点のみの値が大きな意味をもつことはまれであり,時系列全体を対象にして解析を進めることが多くなります.そこで,本言語処理系では時系列を一つのデータ型 (オブジェクトクラス) とみなし, 図 2.7. 「時系列オブジェクトの構造及びその関連図」 に示すように時系列を空間的なデータとその時間的変化を区別して扱える Series オブジェクトを中心としたデータ構造を提供しています.ここでは,SATELLITE 言語において対象となる実体をオブジェクトと呼びます.
オブジェクトクラスには,多次元時系列配列を効率良く扱える Series クラスを中心に Snapshot,String,Scalar,File の 5 種類があります.それらのクラスは数値と文字列を扱うものに大別されます.数値を扱うオブジェクトには,Scalar,Snapshot,Series,File があり,Scalar をスーパークラスとして列挙順に特性が継承されています.Snapshot は,Scalar の集合であり汎用言語の多次元配列に相当します.また,Series は,Snapshot が時刻順に並んだオブジェクトを表し,Snapshot の 1 次元配列と考えることもできます.File オブジェクトに関しては,メッセージとしてファイル名を受け取り指定された UNIX のファイルシステム上にあるデータを操作します.
また,オブジェクトは,データの他にそのデータに対する処理方法 (Method) も含みます.同じ足し算 (+) でも Scalar,Series,Snapshot,String,File オブジェクトによってその処理方法は異なるのが普通です.例えば,Scalar オブジェクトは 図 2.8. 「Scalar オブジェクトの足し算の概念図」 に示すように 1 点のみの足し算です.
一方 Series オブジェクトでは 図 2.9. 「Series オブジェクトの足し算の概念図」 に示すように時間軸全てについて値を加えなければなりません.
このような処理方法の違いをオブジェクト自身に持たせておき,"+" というメッセージのみ送れば,オブジェクト自身がメッセージを解釈し処理を行います.以下に SATELLITE 言語で用いられる 5 種類のオブジェクトクラスについて説明します.
●Scalar クラス
制御変数や Series 要素の操作等を行うためにスカラ値を扱うオブジェクトクラスです (図 2.10. 「Scalar オブジェクト」).処理系内部では,倍精度の浮動小数点数として表現されます.Scalar オブジェクトのデータ操作は以下のように行います.
[]SATELLITE[]~/home/demo:[1]% k=0.8 []SATELLITE[]~/home/demo:[2]% k 0.8
●Snapshot クラス
Series が空間的な次元に加え,陰に時間軸方向としてもう一つ次元を持つのに対し,Snapshot は空間的な次元しか持たないオブジェクトクラスです (図 2.7. 「時系列オブジェクトの構造及びその関連図」).つまり,時間的に静止したデータを取り扱うためのオブジェクトクラスであり,Series のサブセットや多次元のマトリックスとして使用することができます.演算は,同じ大きさの Snapshot 同士のみ行えます.Snapshot との混合演算では,Snapshot の全要素について同じ演算が繰り返し行われます.Snapshot オブジェクトのデータ操作の例を示します (図 2.11. 「2 次元 Snapshot オブジェクトのデータ操作の例」).
まず,以下に示すようにオブジェクトクラスの演算を行います (項4.2. 「クラス宣言」 参照).
[]SATELLITE[]~/home/demo:[3]% snapshot z[2][2]
これより,以下に示すように 2 次元の Snapshot オブジェクトが確保されます.
[]SATELLITE[]~/home/demo:[4]% z [0]:[1]:% 0 0 [0]:[0]:% 0 0
このオブジェクトの一部に値を代入するには,
[]SATELLITE[]~/home/demo:[5]% z[0][1]=4
とします.これより,以下に示すように値が代入されます.
[]SATELLITE[]~/home/demo:[6]% z [0]:[1]:% 0 4 [0]:[0]:% 0 0
以下のように入力することで,ある空間のデータを参照することができます.
[]SATELLITE[]~/home/demo:[7]% z[0][1] [0]:[1]:%4
●Series クラス
空間的な多次元データの集合が時間軸方向に伸びている様子を表現するオブジェクトクラスです (図 2.7. 「時系列オブジェクトの構造及びその関連図」).空間的に 1 点しかないような Series は,汎用言語では 1 次元配列などで表現される単純な時系列です (図 2.12. 「1 次元 Series オブジェクトの概念図」).Series 同士の演算は,空間的なデータ集合 (Snapshot) の大きさが同じときのみ可能です.
すなわち,2 次元 Series オブジェクトと 1 次元 Series オブジェクトの演算はできません.また,時間軸方向の長さが異なる場合には,短い方の範囲内で演算が行われ,残りはそのままコピーされます.また,Series と Scalar の混合演算においては,Series 全体に Scalar を巡回させて計算が行われます.Series の大きな特徴は,各要素ごとに繰り返される隠れた反復演算と,"[]",":[]" 演算子による時系列,空間データの切り出し,書き込みなどの操作機能を持つことです.ここで,Series オブジェクトのデータ操作の例を示します.
[]SATELLITE[]~/home/demo:[8]% x=1~7
これより,1 次元 Series オブジェクトに 1 から 7 が格納されます (図 2.13. 「1 次元 Series オブジェクトのデータ操作の例」).ここで,"~" は交差 1 の数列を生成する数列生成演算子です (項5. 「式と演算子」 参照).
[]SATELLITE[]~/home/demo:[9] x [0]:% 1 2 3 4 5 [5]:% 6 7 []SATELLITE[]~/home/demo:[10]% x:[3] 4
により時間軸方向の 3 番目のデータを参照することができます.次に,2 次元オブジェクトのデータ操作の例を示します.以下のようにオブジェクトクラスの宣言を行います (項4.2. 「クラス宣言」 参照).
[]SATELLITE[]~/home/demo:[11]% series y[2][2]
以下に示すように y に値を格納します.
[]SATELLITE[]~/home/demo:[12]% y[0][1]=x
以下のように入力することで,ある空間の時系列方向のデータを参照することができます (図 2.14. 「2 次元 Series オブジェクトのデータ操作の例 1」).
[]SATELLITE[]~/home/demo:[13]% y[0][1] [0]:% 1 2 3 4 5 [5]:% 6 7
また,以下のように入力することで,ある時刻の空間的なデータを参照することができます (図 2.15. 「2 次元 Series オブジェクトのデータ操作の例 2」).
[]SATELLITE[]~/home/demo:[14]% y:[3] [0][1]:% 0 4 [0][0]:% 0 0
●File クラス
実験データ,シミュレーション結果等をハードディスク内にファイル形式で,半永久的に保存したいときに使用します.ファイルへのロードおよびストアは,オブジェクトの評価,代入で操作できます.従って,ファイルのフォーマットやデータ型などを気にすることなく他のオブジェクトと同じように操作できます.また,series オブジェクトとの混合演算も可能です.
File クラスは Series とほぼ同じ構造を持ち,多次元データ (Series,Snapshot) をレコード方向に複数格納することができます (図 2.16. 「データファイル構造」).レコードとは Series の時刻に相当し,レコード方向は伸縮自在の長さを持ちます.各レコードに格納するデータは同じサイズでなければなりません.また,File オブジェクトの次元数,インデックスは最初にストアされたオブジェクトに依存し,異なる次元数,インデックスを持つオブジェクトは強制変換された後ストアされます.
データのストアは,File オブジェクトへの代入によって行えます.例えば,
[]SATELLITE[]~/home/demo:[15]% $"data.dat":[0] = y
は y (Serries または Snapshot オブジェクト) を data.dat のレコード 0 にストアします.
データをロードする場合には,式中に File オブジェクトをそのまま記述すればよく,処理系により自動的に評価されて Series に変換されます.例えば,
[]SATELLITE[]~/home/demo:[16]% x = $"data.dat":[0]
は x に data.dat のレコード 0 のデータをロードします.また,
[]SATELLITE[]~/home/demo:[17]% y = $"data.dat"
は y に data.dat の全てのレコードをロードします.x,y は共に Series オブジェクトであり,次元,インデックスは data.dat に依存します.例えばレコードに 2 次元データが格納されている場合には,x は 2 次元,y は 3 次元の Series オブジェクトとなります.
●String クラス
実験データ,シミュレーション結果等は,最終的にデータファイルとして保存されます.ファイル名には,データの属性や通し番号等を含む場合が多く,データを管理する上で基本となる情報です.String オブジェクトは単にファイル名を記憶するだけでなく,作図の際のラベル,プログラムからのメッセージ出力として使用する.String オブジェクトの,連結,削除,繰り返し,分割などは "+","-","*","/" などのメッセージを送ることによって行うことができます.また,文字列はダブルクウォート (") で囲まれます.例えば,文字列と文字列の連結は以下のように "+" を用います.
[]SATELLITE[]~/home/demo:[18]% y = "test" + ".dat" []SATELLITE[]~/home/demo:[19]% y test.dat
また,文字列から文字列の削除は以下に示すように "-" を用います.
[]SATELLITE[]~/home/demo:[20]% y = "test.dat" - ".dat" []SATELLITE[]~/home/demo:[21]% y test
文字列を繰り返すには以下に示すように "*" を用います.
[]SATELLITE[]~/home/demo:[22]% "ABC" * 4 ABCABCABCABC
文字列を分割するには以下に示すように "/" を用います.
[]SATELLITE[]~/home/demo:[23]% "A,BC,D,EFG,H,IJK" / "," [0]% A BC D EFG H [5]% IJK
ここで,"[0]%","[5]%" は複数の要素を表示するときのインデックスの先頭を表します.
本処理系における変数のクラス宣言は,永久的な型の束縛を意味するものではなく,値の定まらないオブジェクトを生成するものです.
Series の宣言では,以下に示すように添え字として,空間的な大きさが指定されなければ 1 次元の時系列を扱うことを表します.
[]SATELLITE[]~/home/demo:[1]% series x
また,64×64 の空間的な大きさを持つ時系列は以下のように宣言します.
[]SATELLITE[]~/home/demo:[2]% series y[64][64]
Snapshot の宣言は,以下のように行います.
[]SATELLITE[]~/home/demo:[3]% snapshot a[10], b[20][20]
この Snapshot の宣言では,空間的な大きさを省略することは出来ません.また,Scalar の宣言は,以下のように行います.
[]SATELLITE[]~/home/demo:[4]% scalar i, j, k
Scalar は,空間的な大きさを持つことは許されず 1 つの値のみ扱います.また,String の宣言は,以下のように行います.
[]SATELLITE[]~/home/demo:[5]% string str, mstr[10]
この String の宣言においては,空間的な大きさを指定することも可能です.
本処理系における変数のオブジェクトクラス (型) の決定は代入時に行われ,右辺のオブジェクトクラスが用いられます.従って,前述のクラス宣言は,関数の引数として値を受け取る場合や,多次元オブジェクトの要素にオブジェクトを代入する場合のみ用いられています.すなわち,
[]SATELLITE[]~/home/demo:[1]% a = 1
のように代入文によって,a のオブジェクトクラスが決定する場合はクラス宣言する必要はありません.しかし,クラス宣言されていない変数を関数および手続きの引数として指定できない場合があります.例えば,以下に示す ISPP モジュールの fftc 関数です.
[]SATELLITE[]~/home/demo:[2]% fftc("P", x, y, u, v)
ここで,"P" は計算方式フラグ,x,y は入力時系列,u,v は出力時系列です.この場合は fftc 関数を実行する前に u,v のクラス宣言を行う必要があります.
また,オブジェクトクラスの変換は演算により自動的に行われます.演算は演算子の左側にあるオブジェクト (左被演算オブジェクト) に,演算子と右側のオブジェクト (右被演算オブジェクト) をメッセージとして送ると解釈されるので,演算結果は左被演算オブジェクトのクラスになります.
これを利用するとオブジェクトクラスの変換を行うことができます.例えば,String と Scalar の演算においては Scalar が String に強制変換された後,文字列の処理が施されます.
[]SATELLITE[]~/home/demo:[3]% "test" + 3 test3 []SATELLITE[]~/home/demo:[4]% "" + 3.1415926 3.14159
ここで," " +3.1415926 の結果が 3.14159 になるのは数値の表示精度によるものです.また,Scalar と String の演算においては String が Scalar に変換された後,数値演算が施されます.例えば,
[]SATELLITE[]~/home/demo:[5]% 6 + "3.1415926" 9.1415926 []SATELLITE[]~/home/demo:[6]% 0 + "1.08e-2" 0.0108
です.この操作は,その他のオブジェクトでもよく,Series から String への変換,または Series から String への変換も行うことができます.さらに,複数の要素を持つオブジェクト同士などでも同様に行うことができます.
オブジェクトクラスがわからない変数のオブジェクトクラスを得るには,typeof 関数を使用します.今,変数 x が series オブジェクト,変数 y が Snapshot オブジェクトとします.これらの変数のオブジェクトクラスを得る場合には,
[]SATELLITE[]~/home/demo:[1]% typeof(x) series []SATELLITE[]~/home/demo:[2]% typeof(y) snapshot
このように,オブジェクトクラスを得ることができます.
また,オブジェクトのインデックスを得るには,index 関数を使用します.例えば,
[]SATELLITE[]~/home/demo:[3]% a = 1~10
とした場合,
[]SATELLITE[]~/home/demo:[4]% index(a) 10
このように,オブジェクトのインデックスを得ることができます.また,データが b[10][50] のように多次元データの場合は,
[]SATELLITE[]~/home/demo:[5]% index(b) [0]:% 10 50
のように出力されます.
単純な算術演算だけでなく代入文,関数なども式として評価します.式が評価されると自動的にその値が表示されます.ただし,代入文だけは例外的に値を表示しません.本言語処理系においては,演算子と組み込み関数は表記法が異なるだけで内部では同様に扱われます.式中に現れる演算子はその直前にあるオブジェクトに,組み込み関数は第一引数のオブジェクトにメッセージとして送られます.従って,同じ演算子,組込み関数でもオブジェクトクラスの違いにより,その処理は異なるものとなります.演算子には,算術演算子,関係演算子,インクリメント・ディクリメント演算子,代入演算子に加えて,公差 1 の数列を生成する "~" 演算子,時系列の結合を行う "()" 演算子があります.数列生成演算子 "~" と時系列結合演算子 "()" の使用例を挙げます.
[]SATELLITE[]~/home/demo:[1]% x = -3~-1 []SATELLITE[]~/home/demo:[2]% x [0]:% -3 -2 -1 []SATELLITE[]~/home/demo:[3]% y = 1~3 []SATELLITE[]~/home/demo:[4]% y [0]:% 1 2 3 []SATELLITE[]~/home/demo:[5]% z = (x, 0, y) []SATELLITE[]~/home/demo:[6]% z [0]:% -3 -2 -1 0 1 [5]:% 2 3
演算子には優先順位があり,表 2.2. 「演算子の優先度 (高い順)」 に従って解釈されます.
表 2.2. 演算子の優先度 (高い順)
演算子 | 優先順位 |
---|---|
() [] : [] | |
^ | 右結合 |
! - ++ -- | 左結合 |
~ | 左結合 |
* / % | 左結合 |
+ - | 左結合 |
> >= < <= = = != | 左結合 |
&& | 左結合 |
|| | 左結合 |
= + = - = * = /= ^= | 右結合 |
Series に対する比較演算子の使用例として,(z > 0) * zを示します.
[]SATELLITE[]~/home/demo:[7]% (z > 0) * z [0]:% 0 0 0 0 1 [5]:% 2 3
オブジェクトは演算が終了すると消えてしまいます.演算結果を残すためには変数に代入しておかなければなりません.ここで扱う変数は,束縛されたデータ型を持たない単なるオブジェクトの入れものとして考えます.従って,同じ名前の変数でも代入されるごとにオブジェクトが変化する可能性があり,代入される以前のオブジェクトはゴミとなります.ゴミとなったオブジェクトはある期間保管されますが,ある一定時間に達すると回収された後,破壊されます.
インタラクティブに処理するときに,ユーザからの入力を軽減するため,または組み込み関数を容易に操作できるように組み込み定数を用意しています.その種類には
(1) 円周率を表す PI や自然対数の底 E などの組み込み定数 (表 2.3. 「定数一覧」)
(2) const 文によるユーザ定義の定数,例えば,
[]SATELLITE[]~/home/demo:[1]% const Degree = PI/180
があります.定数には,オブジェクトを代入することはできません.また,本言語処理系では組み込み定数とユーザ定義の定数は同等に扱われ,組み込みの定数を const 文で変更することも可能です.const 文は右辺が計算式,また Series などのオブジェクトでもよく,その時点で評価された結果が設定されます.組み込み定数,ユーザ定義の定数が変数と異なるのは代入が禁止されている点だけです.
制御構造は,C 言語と同様な if 文や while 文,do-while 文,for 文,{ … } を使用した文のグループ化が使用できます.
if ( expr ) stmt
if ( expr ) stmt else stmt
while ( expr ) stmt
do stmt while ( expr )
for ( expr ; expr ; expr ) stmt
ここで,expr は,代入式,関係も含めた一般的な式です.また,stmt は単文であり,{ ,} で囲みグループ化した文も stmt とみなします.expr において,論理演算子には AND 演算子 "&&" や OR 演算子 "||",及び全ての関係演算子が使用できます.論理演算の結果が 0 ならば偽,それ以外は真と扱われます.また,論理演算の結果が複数の要素を持つ場合 (Series 同士の比較など) は,すべての要素が 0 でないとき真になります.
選択文は制御の幾つかの流れの一つを選ぶためのものです.以下に示すように二つの if 文のどちらも,条件式の結果が偽でなければ,最初のサブ文が実行されます.第 2 の形 (else 付き) の場合は,式が偽であれば,第 2 のサブ文に実行が移ります.
if 文第 1 形式:
if ( 条件式 ) { サブ文; }
if 文第 2 形式:
if ( 条件式 ) { 第1サブ文; } else { 第2サブ文; }
例えば,「x が n より小さい場合,s に x を加算する」 という処理は,
[]SATELLITE[]~/home/demo:[1]% if (x < n){ + s = s + x + }
と記述します.また,「x が n より小さい場合,s に x を加算し,それ以外なら s から x を減算する」という処理は,
[]SATELLITE[]~/home/demo:[2]% if (x < n){ + s = s + x + } else { + s = s - x + }
と記述します.
繰り返し文はループを指定するのに使用されます.while 文と do-while 文では,条件式の値が偽でない限り,サブ文が繰り返し実行されます.while 文では,その式のすべての副作用も含めて,条件式の評価 (テスト) は文の各実行の前に行われます.これに対し do 文では,テストが行われるのは各繰り返しの後で行われます.
while 文:
while ( 条件式 ) { サブ文; }
do-while 文:
do { サブ文; } while ( 条件式 ) ;
例えば,while 文において,「x が n より小さい間,s に x を加算する」 という処理は,
[]SATELLITE[]~/home/demo:[1]% while (x < n) { + s = s + x + n++ + }
と記述します.また,do-while 文においては,
[]SATELLITE[]~/home/demo:[2]% do { + s = s + x + n++ + } while( x < n )
と記述します.
for 文では,最初の式が一度だけ評価されます.従って,これはループの初期化の指定にあたります.第 2 の式は各繰り返しの前に評価され,結果が偽になると for は終了します.一方,第 3 の式は繰り返しの後に評価され,ループの再初期化を指定します.
for 文:
for ( 初期化 ; 条件式 ; 再初期化 ) { サブ文; }
例えば,「s に x を n 回加算する」 という処理は
[]SATELLITE[]~/home/demo:[1]% for( i = 1; i <= n; i++) { + s = s + x + }
で記述されます.
これらの繰り返し文においては,break 文を使用すると,while や for 文の中から即座に抜けることができ,continue 文によりループの開始点に戻ることができます.
SATELLITE における変数は,その関数・手続きの中でのみ有効なローカル変数として扱われます.関数・手続きの定義部以外で宣言された変数の有効範囲は関数・手続きの外のみであり,一種のローカル変数とみなせます.
関数・手続き内において,その外で宣言された変数を参照するには予約語 external により外部参照を明示する必要があります.ただし,ある関数・手続き内で宣言されている変数を別の関数・手続きにおいて参照することはできません.
組み込み定数および予約語 const で定義される定数は,その定義以後,いずれの関数・手続き内でも有効です.関数・手続き内で定数を定義することも可能ですが,関数・手続きの定義時には有効にならず,それらを実行した時点で有効になるため,ある関数内で定義した定数をその関数以外で参照する場合には,それ以前にその関数が実行されている必要があります.
SATELLITE では,関数・手続きの引数は,すべて変数渡しであるため,関数・手続き内で引数変数の値を操作した場合,呼び出し側にその操作した結果が反映されることになります.
数学ライブラリ,その他システム内の状態を制御する関数は,あらかじめ組み込み関数として定義されています.数学ライブラリは,series,snapshot,scalar のどれにも適用できます.また,各組み込み関数の優先順位は同じです.表 2.4. 「数学ライブラリ一覧」 に数学ライブラリ,表 2.5. 「システム関数一覧」 にシステム内部の状態を参照,変更するためのシステム関数を示します (詳しくはリファレンスマニュアル参照).
表 2.4. 数学ライブラリ一覧
関数名 | 内容 |
---|---|
abs(x) | x の絶対値 |
acos(x) | x の逆余弦 |
asin(x) | x の逆正弦 |
atan(x) | x の逆正接 |
atan2(x,y) | x/y の逆正接,atan(x/y) に同じ |
cos(x) | x の余弦 |
exp(x) |
![]() |
int(x) | x の整数部,0 に近い向きに切り捨て |
mod(x) | x/y のあまり,x%y に同じ |
log(x) |
![]() |
log2(x) | 2 を底とする x の対数 |
log10(x) | 10 を底とする x の対数 (常用対数) |
pow(x,y) |
![]() |
sgn(x) | x の符号 |
sin(x) | x の正弦 |
sqrt(x) |
![]() |
tan(x) | x の正接 |
ユーザは関数および手続きを定義することができます.例えば,「引数 n に 10 を加える」 という処理をする関数 plusten は,
[]SATELLITE[]~/home/demo:[1]% func plusten (n) { + f = n + 10 + return f + }
で定義することができます.この関数は例えば,以下に示すように呼び出すことで目的とする処理が行えます.
[]SATELLITE[]~/home/demo:[2]% num = 8 []SATELLITE[]~/home/demo:[3]% plusten (num) 18
また,関数は再帰呼び出しが可能です.以下に 「引数 x の階乗を求める」 という処理をする関数 fac を示します.
[]SATELLITE[]~/home/demo:[4]% func fac(x) { + if(x<=0) return 1 else return x*fac(x-1) + }
さらに,手続きを用いて,「引数 x に引数 n の値,引数 y に引数 n+1 の値を代入する」 という処理をする手続きを以下に示します.まず,項4.3. 「オブジェクトクラスの変換」 で述べたように,クラス宣言されていない変数を関数および手続きの引数として指定できないため,手続きを呼び出す前に x,y をクラス宣言します.
[]SATELLITE[]~/home/demo:[5]% scalar x,y []SATELLITE[]~/home/demo:[6]% proc plusten(n, x, y) { + x = n + y = n + 1 + }
例えば,この手続きは以下に示すように呼びだすことで目的とする処理が行えます.
[]SATELLITE[]~/home/demo:[7]% plusten(14, x, y) []SATELLITE[]~/home/demo:[8]% x 14 []SATELLITE[]~/home/demo:[9]% y 15
また,関数,手続きの中で使用される変数は,外部参照を明示しない場合は,すべてローカル変数 (すなわち,その関数・手続き中でのみ有効) です.グローバル変数の宣言 (外部参照の明示) は予約語 external を用いて行います.グローバル変数を使用したい場合は使用したい関数の中で,その都度宣言する必要があります.前述の例と同じような処理を行う関数を予約語 external を用いて示します.
[]SATELLITE[]~/home/demo:[10]% proc subplusone(n) { + external x,y + x = n + y = n + 1 + } []SATELLITE[]~/home/demo:[11]% func glplusone (gn) { + external x,y + subplusone(gn) + z = x + y + return z + }
このように使用する関数を定義します.定義した関数を以下のように呼び出します.
[]SATELLITE[]~/home/demo:[12]% scalar x,y,z []SATELLITE[]~/home/demo:[13]% glplusone (4) 9 []SATELLITE[]~/home/demo:[14]% x 4 []SATELLITE[]~/home/demo:[15]% y 5 []SATELLITE[]~/home/demo:[16]% z 0
関数において引数の型をチェックしないため,多重定義された演算子,数学関数だけからなる関数は,実引数のオブジェクトクラスに関係なく正常な動作が得られます (多態関数).ただし,関数内の演算子がサポートされていないオブジェクトクラスは除きます.以下にシグモイド関数を用いた例を示します.まず,シグモイド関数を以下に示すように定義します.
[]SATELLITE[]~/home/demo:[17]% func sigmoid(t){ + r=1/(1+exp(-t)) + return r + }
引数 t を Scalar オブジェクトとして,関数を呼び出した場合は,
[]SATELLITE[]~/home/demo:[18]% sigmoid(0) 0.5
また,引数 t を Series オブジェクトとして,関数を呼び出した場合は,
[]SATELLITE[]~/home/demo:[19]% sigmoid(-10~10) [ 0]:% 0.0000 0.0001 0.0003 0.0009 0.0025 [ 5]:% 0.0067 0.0180 0.0474 0.1192 0.2689 [10]:% 0.5000 0.7311 0.8808 0.9526 0.9820 [15]:% 0.9933 0.9975 0.9991 0.9997 0.9999 [20]:% 1.0000
また,引数tを String オブジェクトとして,関数を呼び出した場合は,対応していない演算子の処理を実行できずにエラーとなります.
[]SATELLITE[]~/home/demo:[20]% sigmoid("test") sl: string not supported method
このように,Series オブジェクトを使用する例では,"~" 演算子により -10 から 10 までの時系列 (21 データポイント) を sigmoid 関数に渡すと,21 個の要素をもつ Series が結果として得られます.従って,時系列を扱うプログラムが数式に従って容易に記述できることがわかります.また,この関数例では,実引数として Scalar,Snapshot,Series,File オブジェクトクラスのいずれかを与えた場合には期待した処理結果が得られます.
プログラム中でオブジェクトの表示や入力などは,組み込み関数や外部関数の他に組み込みコマンドでもいくつか提供されています.
printf 文は,表示するときの精度などが指定できます.使用方法は,C 言語の printf 関数に類似していますが,時系列の要素全てが自動的に表示される点が異なります.
[]SATELLITE[]~/home/demo:[1]% x = 3 []SATELLITE[]~/home/demo:[2]% printf("x = %d\n",x) x=3 []SATELLITE[]~/home/demo:[3]% printf("%1.7f\n",(1,2,3,4,5)) [0]:% 1.000000 2.000000 3.000000 [3]:% 4.000000 5.000000
また,オブジェクトを端末からの入力で読み込むときには,read 関数があります.read 関数は読み込むオブジェクトクラスを引数として受け取り,入力された文字列をそのオブジェクトクラスに強制変換します.読み込まれたオブジェクトは read の戻り値となります.時系列のように複数の要素からなるオブジェクトは,コンマを区切り記号として分解され読み込まれます.例えば,
[]SATELLITE[]~/home/demo:[4]% y = read(series)
と入力した後,
1, 2, 3, 4, 5, 6, 7, 8
と入力すると,以下に示すように y には入力した数値が格納されます.
[]SATELLITE[]~/home/demo:[5]% y [0]:% 1 2 3 4 5 [3]:% 6 7 8
SATELLITE 言語の特徴であるインタラクティブにパラメータの説明を表示しながら入力を催促する機能です.パラメータの区切り記号は,"," で表されます.例えば,グラフを表示する graph 関数を扱う場合には,
[]SATELLITE[]~/home/demo:[1]% graph []SATELLITE[]~/home/demo:[2]% graph(x ・・・・・ Y-AXIS DATA ( Object or "T","F","D" )
ここで,Y 軸に表示するオブジェクトを入力します.例えば,"volt" を入力すると,
[]SATELLITE[]~/home/demo:[3]% graph(volt []SATELLITE[]~/home/demo:[4]% graph(volt,"T" ・・・・・ X-AXIS DATA ( Object or "T","F","D" )
と表示され,X 軸に表示するオブジェクトを入力します.このように,オブジェクト入力を表示されるパラメータ全てについて行います.もし,デフォルトのパラメータで構わない場合についてはリターン入力で次の表示に移ります.
SATELLITE コマンドは,全て関数として構文解析をされるのでパラメータ列を丸括弧で括らなければなりません.また,入力されたパラメータは,エディットバッファに格納されているので自由に編集ができます.
ファイルに記述されているプログラムをインタプリタに読み込ませるためには,inline 関数を使用します.inline 関数は,ファイル名を引数にとり,そのファイルを標準入力として展開します.従って,端末からの入力と同様にプログラムが次々に評価されます.ファイル中に他のファイルをインライン展開することも可能です.inline 関数は実行の段階で処理されます.また,関数定義中で使用されたときも同様です.また,ファイルから読み込んでいる途中でエラーが生じたときには,その後のプログラムはそれ以降評価されません.作成したファイル (ファイル名は testsum.sl とします) の例を以下に示します.
sum = 0; for( i = 1; i <= 10; i++){ sum = sum + i; } printf("sum = %d\n", sum);
このファイルをインタプリタに読み込み実行させるには,
[]SATELLITE[]~/home/demo:[1]% inline("testsum.sl")
と入力することで,
[]SATELLITE[]~/home/demo:[2]% inline("testsum.sl") sum = 55
目的とする処理が行われます.また,ファイルの中で,別ファイルを読み込むときは,以下のように inline 関数を用いてプログラミングします.
sum = 0; for( i = 1; i <= 10; i++) { sum = sum + i; } printf("sum = %d\n",sum); inline("別のファイル名");