6 Functions

6.1関数記法(functional notation)

Oz は関数記法を構文の利便性のために提供しています。私達は手続き呼び出しとして見た:

{P X1 ... Xn R}

これをネストした式の中で関数呼び出しとして使う事が出来ます:

{P X1 ... Xn}

Oz は手続きのための直接の構文記法として関数抽象も許します。それゆえ、以下の関数定義で:

fun {F X1 ... Xn} S E end

S は文で E は以下の関数定義に対応する式です:

proc {F X1 ... Xn R} S R=E end

注意:手続き定義への変換も含めた関数のための厳密な構文は The Oz Notation Reference Manual に定義されています。

ここでは私達は読者の直観にたよります。大雑把に言うと、関数の構文の形式のための一般的なルールは手続きのそれと非常に似て見えます。その例外として、手続きでは制御のスレッドは文で終わり、対応する関数は式で終わるという事があります。

Figure 6.1 で示されるプログラムは Figure 5.7 で示されるプログラムと機能的に等しいものです。AndThen/2 がどの様に手続き AndThen/3 に展開されるかをよく見て下さい。下で、変換プロセスの直観的理解を与えるいくつものステップをお見せします。全ての中間の形式は正しい Oz のプログラムです。

fun {AndThen BP1 BP2}
   if {BP1} then {BP2}
   else false end 
end

結果変数 B を導入する事によって手続きを作ります:

proc {AndThen BP1 BP2 B}
   B = if {BP1} then {BP2}
       else false end 
end

結果変数を外側の if-式 に移動して if-文 を作ります:

proc {AndThen BP1 BP2 B}
   if {BP1} then B = {BP2}
   else B = false end 
end


% 構文変換: 関数記法
local 
   fun {AndThen BP1 BP2}
      if {BP1} then {BP2}
      else false end 
   end 
   fun {BinaryTree T}
      case T
      of nil then true 
      [] tree(K V T1 T2) then 
         {AndThen
          fun {$} {BinaryTree T1} end 
          fun {$} {BinaryTree T2} end}
      else false end 
   end 
end

Figure 6.1: 遅延二分木チェック


もしあなたが関数型プログラマーなら、元気を出して下さい。あなたは高階関数を含むあなた自身の関数を持てます、そして遅延評価の関数型言語と同様に、Oz は正格評価の関数型言語 1 Standard ML、Scheme、そして並行関数型言語 Erlang には無い末尾再帰の特定の形式を許します。しかしながら、Oz では標準の関数定義は遅延ではありません。遅延関数は Oz 2 においてもサポートされます。

ここで、よく知られた高階関数 Map/2 の例をお見せします。これは Standard ML や Scheme においては末尾再帰ではありませんが、Oz においては末尾再帰です。

fun {Map Xs F}
   case Xs
   of nil then nil
   [] X|Xr then {F X}|{Map Xr F}
   end 
end 
{Browse {Map [1 2 3 4] fun {$ X} X*end}}

6.1.1 andthenorelse

結局、私達は多くの仕事を無料でしてきました!Oz は既に遅延(非正格)バージョンの Boolean 関数 And/2Or/2 をそれぞれ andthenorelse として提供しています。前者は関数 AndThen/2 の様に振る舞い、後者は最初の引数が false と評価された場合のみ評価されます。通常、これらの演算子はプリミティブではなく、Oz で定義されます。Figure 6.2 は関数 BinaryTree の最終版です。


fun {BinaryTree T}
    case T of nil then true  
    [] tree(K V T1 T2) then  
       {BinaryTree T1} andthen {BinaryTree T2}  
    else false end  
end

Figure 6.2: 遅延二分木チェック


6.1.2関数にするか関数にしないか?

今から、原則として、私達は手続きと関数の両方を使う事によっていくらかの構文的な重複を持っていますが、問いはいつ関数記法を使っていつ使わないのかです。誠実な回答は、「それはあなたの責任です」となります!私の個人的な意見を述べましょう。いくつかのルールの概要です:


1. 正格評価関数型言語は関数の実行の前に全ての引数を評価します。
2. これらは後で フューチャ(future) と by need 同期を論じる時に述べます。
3. 実際には、これらのケースでは Oz のオブジェクト指向スタイルが最も適切です。

Seif Haridi and Nils Franz�n
Version 1.4.0 (20080704)