グローバル プロシージャ

このセクションではグローバル プロシージャについて説明します。また、匿名プロシージャおよびクラス プロシージャを使う場合に役立つ背景知識についても説明します。このセクションは次のトピックに分かれています。

グローバル プロシージャの定義

グローバル プロシージャを定義するには、define-proc を使います。
構文:{define-proc [access] [modifier-list] {procedure-name [arg-def-list]}[:return-types]
    code-body
}
説明:
accessアクセス属性。有効な属性は publiclibraryおよび package です。access を指定しなかった場合、アクセス属性はデフォルトで package になります。詳細については、「プロシージャのアクセス属性の指定」を参照してください。
modifier-list修飾子のリスト (省略可能)。プロシージャに対して有効な修飾子は、inlinedeprecated の 2 つだけです。修飾子を複数個指定する場合は、修飾子どうしを空白で区切ります。詳細については、「プロシージャの修飾子の指定」を参照しください。
procedure-nameプロシージャの名前。Curl® 言語の命名規則に従って、有効な Curl 言語識別子を指定します。大文字は使用できません。複数の単語はハイフンで区切ります。
arg-def-listプロシージャの引数のリスト (省略可能)。リストされた引数または残余引数を指定できます。指定可能な引数のフォーマットは、位置フォーマットまたはキーワード フォーマットです。詳細については、「プロシージャの引数の指定」を参照してください。
return-typesプロシージャの戻り値のデータ型。プロシージャは、まったく値を返さないかまたは 1 個以上の値を返します。return-types を指定しなかった場合、any 型の戻り値を 1 つ指定したものと見なされます。詳細については、「プロシージャの戻り値のデータ型の指定」を参照してください。
code-bodyプロシージャのコード本体。code-body はコード ブロックです。コード ブロックは、1 つ以上の Curl 言語式で構成されます (return 式が含まれることもあります)。このプロシージャから 1 つ以上の値が返されるように定義するには、コード本体の中に必ず return 式を記述する必要があります。コード本体の中に return 式が存在する場合、Curl® 実行環境 は return 式の値を呼び出し元プロシージャに返します。

プロシージャのアクセス属性の指定

要約:
  • public は、すべてのコードがこのプロシージャにアクセスできることを示します。
  • library は、同じライブラリ内のコードだけがフィールドにアクセスすることが出来ます。
  • package は、同じパッケージ内のコードだけがこのプロシージャにアクセスできることを示します。
  • 既定値は package です。
アクセス属性とは、プロシージャにその名前でアクセスできるコードを限定するものです。アクセス属性の指定はオプションです。グローバル プロシージャでは、publicpackage の 2 種類のアクセス属性を指定できます。すべてのコードがプロシージャにアクセスできるようにするには public を使用し、プロシージャと同じパッケージ内のコードだけにアクセスを制限する場合は package を使用します。アクセス属性の既定値は package です。アクセス属性に関する詳細の情報は、library を参照してください。

プロシージャの修飾子の指定

要約:
  • inline はコンパイラに対して、プロシージャ コールをそのプロシージャの実際のコードに置換するよう指示します。
  • deprecated は、このプロシージャの使用を推奨しないこと、および、このプロシージャが将来サポート対象外になる可能性があることを示します。
修飾子は、実行環境 がプロシージャをコンパイルする方法に影響を及ぼします。修飾子の指定はオプションです。プロシージャに対して指定可能な修飾子は、inlinedeprecated の 2 つだけです。
inline 修飾子は、「プロシージャ コールをそのプロシージャの実際のコードに置換すればパフォーマンスが向上する可能性がある」という情報を 実行環境 に通知する場合に使います。特定の条件下では、プロシージャ コールをインライン プロシージャに置換するとコードの実行速度が向上します。たとえば、プロシージャのサイズが小さい場合などです。inline を指定した場合、実行環境 はインライン置換の妥当性を検査します。実行環境 が「インライン置換を実行すればパフォーマンスが向上する」と判断した場合、コンパイラは置換を行います。deprecated が指定されているプロシージャを、新規に作成するコードの中で使うことはお勧めできません。このようなプロシージャは、将来のバージョンでサポートされなくなる可能性があります。
deprecated 修飾子は、新規に作成するコードの中でこのプロシージャを使うべきでないことを示す場合に指定します。つまり、このプロシージャは現時点ではまだサポートされていますが、このソース コードの将来のバージョンでサポート対象外になる可能性があります。

プロシージャの引数の指定

要約:
  • リストされた引数を位置フォーマットまたはキーワード フォーマットで指定できます。
  • 位置フォーマットの構文は arg-name[:arg-type]です。
  • キーワード フォーマットの構文は arg-name[:arg-type]=arg-valueです。
  • 残余引数 (...) を指定できます。
  • 残余引数は、引数リストの末尾に指定します。
引数は次の 2 種類に分けられます。
このセクションでは、プロシージャの定義に適用される引数について概説します。引数の詳細については、「引数」を参照してください。
リストされた引数の指定
リストされた引数は、次の 2 種類のフォーマットのいずれかで指定できます。
引数を位置フォーマットで指定する場合は、次の構文を使います。
arg-name[:arg-type]
arg-name は有効な Curl 言語識別子、arg-type は有効な Curl 言語データ型です。arg-name は、そのプロシージャ内のすべての引数の中で一意でなければなりません。arg-type の指定はオプションです。arg-type の既定値は any 型です。つまり、データ型を指定しなかった場合、その引数は any 型であると見なされます。位置引数の定義例を次に示します。
|| A procedure that takes one integer positional
|| argument (i)
{define-proc public {my-proc1 i:int}:void
    || Body of procedure
}

|| A procedure that takes one "any" positional
|| argument (a)
{define-proc public {my-proc2 a}:void
    || Body of procedure
}

|| A procedure that takes two positional arguments:
|| a bool (b) and a char (c)
{define-proc public {my-proc3 b:bool, c:char}:void
    || Body of procedure
}
キーワード引数を指定するには、次の構文を使います。
arg-name[:arg-type]=arg-value
arg-name は一意の有効な Curl 言語識別子、arg-type は有効な Curl 言語データ型、arg-value は引数の既定値です。arg-type の既定値は any 型です。つまり、データ型を指定しなかった場合、その引数は any 型であると見なされます。キーワード引数の定義例を次に示します。
|| A procedure that takes one integer keyword
|| argument (i)
{define-proc public {my-proc4 i:int=0}:void
    || Body of procedure
}

|| A procedure that takes two keyword arguments:
|| a bool (b) and a char (c)
{define-proc public {my-proc5 b:bool=true, c:char='a'}:void
    || Body of procedure
}
残余引数の指定
残余引数を指定するには、引数リストの末尾に 3 つのピリオド (...) を追加します。次に例を示します。
|| A procedure that takes rest arguments.
{define-proc public {my-proc6 ...}:void
    || Body of procedure
}

|| A procedure that takes two keyword arguments,
|| a bool (b) and a char (c), and rest arguments.
{define-proc public {my-proc7 b:bool=true, c:char='a', ...}:void
    || Body of procedure
}

プロシージャの戻り値のデータ型の指定

要約:
  • 戻り値を 1 つも指定しない場合の構文:void または ()
  • 戻り値を 1 つ指定する場合の構文:return-type または (return-type)
  • 戻り値を複数個指定する場合の構文:(return-type-list)
  • 戻り値のないプロシージャの構文: never-returns.
  • 既定では、プロシージャは any 型の値を 1 つ返します。
プロシージャから返される値のデータ型を指定できます。値を返さないプロシージャの場合は、戻り値に対して void を指定します。(戻り値を指定しないことと戻り値が存在しないことは、同じではありません。これについては後述します。)値を返さないプロシージャの例を次に示します。
|| A procedure that does not return a value.
{define-proc public {my-proc8 i:int}:void
    || Body of procedure
}
値を 1 つ返すプロシージャの場合は、その値のデータ型を指定します。次に例を示します。
|| A procedure that returns one value: an int.
{define-proc public {my-proc9 i:int}:int
    || Body of procedure
}
値を返さないプロシージャ、つまり、例外のスローか exit の呼び出しによってのみ終了するプロシージャの場合、その戻り値に never-returns を指定してください。次に例を示します。
|| A procedure that throws an error
{define-proc public {my-error}:never-returns
    {error "Something bad happened."}
}
詳細は never-returns を参照してください。
複数の戻り値の指定
複数の値を返すプロシージャの場合は、次の構文を使います。
構文:(return-type-list)
説明:
return-type-list戻り値のデータ型のリスト。データ型どうしを区切るには、コンマを使います。戻り値の指定の中に識別子を追加できます。
次に例を示します。
|| A procedure that returns three values: an int, a String,
|| and a bool.
{define-proc public {my-proc i:int}:(int, String, bool)
    || Body of procedure
}
複数の値を返すプロシージャの場合、戻り値のデータ型の指定に識別子を追加できます。この識別子の目的は、コードを読む人に対してそれぞれの戻り値の内容を示すことだけです。つまり識別子とは、コードを読む人に対するコメントや説明です。実行環境 がコードをコンパイルするとき、識別子は無視されます。次のプロシージャを例にとって、戻り値の識別子の使い方を示します。
|| A procedure that returns three String values.
{define-proc public {my-proc i:int}:(String, String, String)
    || Body of procedure
}
それぞれの戻り値の内容を示す識別子を追加すると、このプロシージャの処理内容が明確になります。次に例を示します。
|| A procedure that returns three String values.
{define-proc public {my-proc}:(first:String, last:String, addr:String)
    || Body of procedure
}
前述したとおり、戻り値の指定はオプションです。戻り値を指定しなかった場合、any 型の戻り値が 1 つ指定されたものと見なされます。次に例を示します。
|| A procedure that returns one value: an any.
{define-proc public {my-proc i:int}
    || Body of procedure
}

プロシージャの戻り値の指定

要約:
  • 戻り値が 1 つの場合の構文:{return return-value}
  • 戻り値が複数の場合の構文:{return return-value-list}
値を返すプロシージャを定義する場合、そのプロシージャのコード本体の中に return 式を記述する必要があります。return 式の中では、プロシージャが返す値ごとに引数を 1 つ設定します。戻り値のデータ型は、プロシージャの署名における戻り値のデータ型と一致している必要があります。たとえば、次のプロシージャは整数型の値を 1 つ返します。
|| A procedure that returns one value: an int.
{define-proc public {my-proc i:int}:int
    {return i * 2}
}
次の例は、3 つの値を返すプロシージャです。戻り値どうしを区切るには、コンマを使います。
|| A procedure that returns three String values.
{define-proc public {my-proc}:(first:String, last:String, addr:String)
    || Define three variables to hold the information that
    || this procedure returns.
    let first:String
    let last:String
    let addr:String
    || Code that places information in the variables.
    ...
    || Return the information
    {return first, last, addr}
}
return 式は必ず、最も内側のプロシージャから抜け出します。あるプロシージャの内部にある匿名プロシージャの中に return 式を記述する場合、その return 式は必ず匿名プロシージャから抜け出します。外側のプロシージャから抜け出すことはありません。

グローバル プロシージャの呼び出し

要約:
  • プロシージャ コールの構文:{procedure-name [arguments-list]}
  • 戻り値が複数の場合の構文 (通常の場合):set (variable-list) = {procedure-name [arguments-list]}
コードがあるプロシージャにアクセスする権限を持っている場合、そのプロシージャを呼び出すことができます。public アクセス属性が設定されているプロシージャには、すべてのコードからアクセスできます。一方、package アクセス属性が設定されているプロシージャには、同じパッケージ内のコードからのみアクセスできます。詳細については、「パッケージ」を参照してください。
プロシージャを呼び出すには、次の構文を使います。
構文:{procedure-name [arguments-list]}
説明:
procedure-nameプロシージャの名前。
arguments-listプロシージャ コールの引数のリスト。
引数を複数個指定する場合は、引数どうしをコンマで区切ります。プロシージャを呼び出すとき、キーワード引数は任意の位置に任意の順序で指定できます。一方、位置引数はプロシージャ定義と同じ順序で指定する必要があります。位置引数の中にキーワード引数を混在させることができます。ただしその場合、位置引数の相対的な順序が正確でなければなりません。

複数の戻り値のあるプロシージャの呼び出し

プロシージャから複数の値が返される場合、let ステートメントまたは set ステートメントを使って、戻り値を変数に代入することができます。複数の変数を初期化する時に使用する let ステートメントの構文は次のとおりです。
構文:let (variable-definition-list) = {procedure-name [arguments-list]}
説明:
variable-definition-list
変数定義のリスト。変数定義どうしを区切るには、コンマを使います。それぞれの変数定義の構文は次のとおりです。
variable-name[:data-type]
例えば、数値計算ライブラリの round プロシージャは、2 つの引数の指数 (2 番目の引数は既定では 1) を最も近い整数値に丸めた値と、丸められた指数から残された剰余の 2 つの値を返します。次の例では、このプロシージャをどのように呼び出すかを示しています。 次に例を示します。

例: Using let with Multiple Return Values
|| Using the first return value directly:
The first value returned by |"{round 4.7}"| is {round 4.7}.

|| Initializing a variable to the first return value:
{value
    let rounded:double = {round 4.7}
    {text The first return value is {value rounded}.}
}

|| Initializing two variables, one per return value:
{value
    let (rounded:double, leftover:double) = {round 4.7}
    {text The rounded value is {value rounded} and the remainder
        is {value leftover}.
    }
}
複数の値を代入する場合、set ステートメントでも同様の構文を使用します。
構文:set (variable-list) = {procedure-name [arguments-list]}
次に例を示します。

例: 複数の戻り値のある set の使用
{value
    let rounded:double, leftover:double
    || Assigning only the first return value:
    set rounded = {round 4.7}  || this has value 5
    {text The first value returned is: {value rounded}}

    || Assigning both return values:
    set (rounded, leftover) = {round 4.7}
    {text The two values returned are: {value rounded}, {value leftover}}
}
複数の値を返すプロシージャを呼び出す場合、必ずしもすべての戻り値を変数に代入する必要はありません。このようなプロシージャを呼び出すとき、任意の数の戻り値を変数に代入できます。戻り値は左から順に変数に代入されます。代入されなかった戻り値は破棄されます。この仕様を利用すれば、複数の値を返すプロシージャを作成し、その戻り値の一部をケースバイケースで使わないようにすることができます。次に例を示します。

例: 複数の値を返すプロシージャの作成
|| A procedure that returns two values.
{define-proc {return-2-values}:(ch:char, i:int)
    {return '\u0061', 0x0061}
}

{value
    || Call the procedure and assign the leftmost return
    || value to x.
    let x:char = {return-2-values}
    x
}

プロシージャのデータ型

要約:
  • プロシージャにはデータ型が設定されています。
データ型は明示されていない場合もありますが、Curl 言語の関数には必ずデータ型が設定されています。プロシージャにはデータ型が設定されているので、プロシージャを次の用途に使うことができます。
Curl 言語の一部のコレクションでは、この機能を利用しています。これにより、プロシージャをメソッド呼び出しの引数として指定できます。たとえば Aggregate-of.filter メソッドでは、コレクションの要素を選別する際に指定するプロシージャが使われています。Aggregate-of.filter メソッドの使用例を次に示します。

例: プロシージャのデータ型の利用
|| Returns false if a string begins with the letter 'a'.
{define-proc {eliminate-a str:String}:bool
    {return str[0] != 'a'}
}

{value
    || A set of Strings that contains three elements.
    let fruits:{Set-of String} =
        {new {Set-of String}, "apple", "banana", "cherry"}

    || Filter out elements that begin with 'a'.  Note that
    || the filter method removes an element if a call to
    || the supplied procedure returns false.
    {fruits.filter eliminate-a}

    || Display the elements that remain in the set.
    || One way to display the members of a set is to splice
    || the elements of the set as arguments to String. Note
    || that the order of elements in a set is non-deterministic.
    {String {splice fruits}}
}
プロシージャのデータ型を設定するには、proc-type プリミティブを使います。プロシージャのデータ型は、引数リストの中、および戻り値の指定の中で利用できます。proc-type プリミティブの構文は次のとおりです。
要約:
プロシージャのデータ型を設定するには、proc-type プリミティブを使います。
構文: {proc-type {[arg-type-list]}[:return-type-list]}
説明:
arg-type-listプロシージャの引数のデータ型のリスト。データ型どうしを区切るには、コンマを使います。
return-type-listプロシージャの戻り値のデータ型。プロシージャは、まったく値を返さないかまたは 1 個以上の値を返します。return-types を指定しなかった場合、any 型の戻り値を 1 つ指定したものと見なされます。詳細については、「プロシージャの戻り値のデータ型の指定」を参照してください。
たとえば、次のようなプロシージャが定義されているとします。
|| A procedure that returns the value of the argument
|| multiplied by 3.
{define-proc {triple x:int}:int
    {return 3 * x}
}
このプロシージャを保持するための変数を定義できます。
let my-proc:{proc-type {int}:int} = triple
この場合、triple を呼び出すことと my-proc を呼び出すことは同じです。proc-type プリミティブは、グローバル プロシージャよりも匿名プロシージャに対してよく使われます。関数呼び出しの引数としてプロシージャを指定する場合、グローバル プロシージャではなく匿名プロシージャを使いたいことがあります。匿名プロシージャを使った場合、コード内の識別子の数を減らすことができます。また、レキシカル変数の閉鎖など、強力な機能を利用できます。詳細については、「匿名プロシージャ」を参照してください。