[2] 関数
引数を与えると、それに対し所定に計算をし値を返す。関数を呼び出すときには、
(func a b c)
または、
<func> a b c </func>
あるいは、属性リストをつかい
([func type="def"] a b c)
<func type="def"> a b c </func>
というように、構造型を使う。この構造型全体を関数func への引数と呼び、func, a, b, cをそれぞれ、関数の1番目2番目.....の引数要素と呼ぶ。また、呼び出された側から、属性を参照する場合は、属性名に相当するシンボルを参照すればよい。
関数の引数の評価の仕方は、Normal と、Applicativeとの2種類がある。Normal では、引数は評価されずに、そのまま渡される。環境は渡される時に生成され、新しいカレント環境となる。引数を評価するかしないかは、関数を実行する中で明示的に決めたいときにこのオプションを選ぶ。
一方、Applicativeでは、引数は引数要素ごとに評価されてから渡される。引数評価のために、分岐環境が生成され、その一番目の親環境に関数定義時に定義した専用の環境がセットされ、第二番目の親環境に現在のカレント環境が設定される。評価する場合の環境の検索順序は関数定義時の環境、現在のカレント環境という順番になる。この仕組みは、
<SetAgent>
"nichibun-agent"
<User> hirohisa </User>
<Passwd> abc </Passwd>
</SetAgent>
という呼び出しを考えたとき、User,Passwdを、SetAgent外部で使用したときと、別の処理をしたいときに有効である。評価用の環境でこの特殊な処理の関数を定義すればよい。つまり、以下のようにSequenceを使って新しい環境を定義してしようする。
<Sequece>
<Define> ^Env <CurrentEnvironment/> </Define>
<Define> ^User
()
<Arguments> ^name </Argments>
..... User の定義
</Define>
<Define> ^Passwd
()
<Arguments> ^password </Arguments>
..... Passwd の定義
</Define>
</Sequence>
<Define> ^SetAgent
^Env
<Arguments> ^db ^user ^passwd </Argements>
.... SetAgent の定義
</Define>
....
<SetAgent>
"nichibun-db"
<User> hirohisa </User>
<Passwd> abc </Passwd>
</SetAgent>
前段階が終わると、引数が評価され、関数本体へ実行が移る。
おおかたの関数は、前段階なしのApplicative関数であろう。
また関数には、インタプリタにあらかじめ組み込まれたプリミティブ関数と、スクリプトによって定義できる、マクロ関数がある。マクロ関数の定義の仕方はプリミティブ関数lambdaおよびdefineで実現される。
▲