関数

関数はプログラミングの基本的な構成要素であり、タスクを実行するステートメントをグループ化するための便利で強力な方法です。これらは、Citrix ADCアプライアンスと拡張コードの間のインターフェイスです。ポリシーの場合は、ポリシー拡張関数を定義します。プロトコルの場合は、プロトコル動作のコールバック関数を実装します。関数は、関数との間で渡される値とその関数に対して実行されるステートメントを指定する関数定義、および特定の入力データで関数を実行し、関数から結果を取得する関数呼び出しで構成されます。

プロトコル動作コールバック関数

TCP クライアントの動作は、TCP クライアントデータストリームイベントを処理するコールバック関数(on_data)で構成されます。TCP ベースのプロトコルのメッセージベース負荷分散 (MBLB) を実装するには、このコールバック関数のコードを追加して、クライアントからの TCP データストリームを処理し、バイトストリームを解析してプロトコルメッセージにします。

ビヘイビアのコールバック関数は、処理モジュールの状態であるコンテキストとともに呼び出されます。コンテキストは、処理モジュールのインスタンスです。たとえば、TCP クライアント動作コールバックは、クライアント TCP 接続ごとに異なるコンテキストで呼び出されます。

コンテキストに加えて、ビヘイビアコールバックは他の引数を持つことができます。通常、残りの引数はペイロードとして渡されます。ペイロードはすべての引数のコレクションです。したがって、プログラマブルプロセッシングモジュールのインスタンスは、インスタンス状態とイベントコールバック関数の組み合わせ、つまりコンテキストと動作の組み合わせと見なすことができます。トラフィックはイベントペイロードとしてパイプラインを通過します。

TCPクライアントコールバック関数のプロトタイプ:



                Function                client on_data (ctxt, payload)

                                                //.code

                end


<!--NeedCopy-->

各項目の意味は次のとおりです。

  • ctxt-TCP クライアント処理コンテキスト
  • payload — イベントペイロード
    • payload.data-受信した TCP データ。バイトのストリームとして利用可能

ポリシー拡張関数

NetScalerポリシー式言語は型指定されているため、拡張関数の定義では、入力の種類と戻り値を指定する必要があります。Lua 関数定義は 、次の型を含むように拡張されました。


function self-type: function-name(parameter1: parameter1-type, and so on): return-type
     statements
end

<!--NeedCopy-->

各項目の意味は次のとおりです。

型はNSTEXT、NSNUM、NSBOOL、またはNSDOUBLE。

自己型は、関数に渡される暗黙的な自己パラメータの型です。拡張関数がCitrix ADCポリシー式で使用される場合、これは関数の左側の式によって生成される値です。これを表示するもう1つの方法は、関数がそのタイプをCitrix ADCポリシー言語で拡張することです。

parameter-types は、ポリシー式の拡張関数呼び出しで指定された各パラメータの型です。拡張関数は 0 個以上のパラメータを持つことができます。

return-type は、拡張関数の呼び出しによって返される値の型です。これは、ポリシー式の部分(存在する場合)への入力であり、関数の右側にある場合、または式の結果の値です。

例:

function NSTEXT:COMBINE_HEADERS() : NSTEXT

ポリシー式での拡張関数の使用:

HTTP.REQ.FULL_HEADER.AFTER_STR("HTTP/1.1\r\n").COMBINE_HEADERS()

ここで、自己パラメータはHTTP.REQ.FULL_HEADER.AFTER_STR("HTTP/1.1\r\n")の結果であり、これはテキスト値です。COMBINE_HEADERS () 呼び出しの結果はテキストであり、この呼び出しの右側に何もないので、式全体の結果はテキストになります。

ローカル関数定義

拡張関数のほかに、拡張ファイルにグローバル関数を定義することはできません。しかし、ローカル関数は、通常の Lua 関数ステートメントを使用して拡張関数内で定義できます。これは、関数の名前とそのパラメータの名前 (引数とも呼ばれます) を宣言し、Lua のすべての宣言と同様に、型を指定しません。この構文は次のとおりです。


local function function-name(parameter1-name, parameter2-name, and so on)
     statements
end

<!--NeedCopy-->

関数名とパラメータ名はすべて識別子です。(関数名は実際には変数であり、関数ステートメントはローカル関数名 = 関数(parameter1 など)の省略形ですが、関数を使用するためにこの微妙なことを理解する必要はありません。)

ここでは、通常の… の代わりにパラメータ名のパターンの継続に使用されていることに注意してください。これは、… 自体が実際には可変パラメータリストを意味するためです。ここでは説明しません。

関数本体とリターン

function ステートメントと end ステートメントの間のステートメントのブロックは、関数本体です。関数本体では、関数パラメータはローカル変数のように動作し、前述のように関数呼び出しによって提供される値を持ちます。

return 文は、関数の呼び出し元に返される値を提供します。これは、ブロックの最後 (関数内、if then、for ループなど) に出現しなければなりません。それはそれ自身のブロックにあることができます do return… end)。戻り値を指定しない、1 つ、または複数指定する。


return -- returns nil
return expression -- one return value
return expression1, expression2, ... -- multiple return values

<!--NeedCopy-->

例:


local function fsum(a)
     local sum = 0
     for i = 1, #a do
          sum = sum + a[i]
     end
     return sum
end

Local function fsum_and_average(a)
     local sum = 0
     for i = 1, #a do
          sum = sum + a[i]
     end
     return sum, sum/#a
end

<!--NeedCopy-->

関数呼び出し

関数呼び出しは、関数の本体を実行し、そのパラメータの値を指定し、結果を受け取ります。関数呼び出しの構文は関数名 (式 1、式 2 など) で、関数パラメーターは対応する式に設定されます。式とパラメータの数は同じである必要はありません。パラメータより式の数が少ない場合、残りのパラメータは nil に設定されます。したがって、呼び出しの最後に1つ以上のパラメータをオプションにすることができ、関数はそれらがnilでないかどうかをチェックすることによって指定されているかどうかをチェックできます。これを行う一般的な方法は OR 演算です。


function f(p1, p2) -- p2 is optional
     p2 = p2 or 0 -- if p2 is nil, set to a default of 0
     . . .
end

<!--NeedCopy-->

パラメータよりも多くのエクスプレッションがある場合、残りのエクスプレッション値は無視されます。

前述のとおり、関数は複数の値を返すことができます。これらの戻り値は、複数の代入ステートメントで使用できます。例:


local my_array = {1, 2, 3, 4}
local my_sum, my_ave = sum_and_average(my_array)

<!--NeedCopy-->

イテレータ関数とジェネリック for ループ

関数を導入したので、ジェネリックな for ループについて話すことができます。ジェネリック for ループ (変数が 1 つ) の構文は次のとおりです。


for variable in iterator(parameter1, parameter2, and so on) do
     statements in the for loop body
end

<!--NeedCopy-->

iterator () は、ループ本体の各反復で変数の値を提供する 0 個以上のパラメーターを持つ関数です。イテレータ関数は、クロージャと呼ばれる手法を使用して、反復のどこにあるかを追跡します。ここで心配する必要はありません。nil を返すことで、反復の終了を知らせます。イテレータ関数は、複数代入で使用するために、複数の値を返すことができます。

イテレータ関数の記述はこのホワイトペーパーの範囲を超えていますが、この概念を説明する便利なビルトインイテレータはほとんどありません。1 つは pairs () イテレータで、テーブル内のエントリを反復処理し、次のエントリのキーと値の 2 つの値を返します。

例:


local t = {k1 = "v1", k2 = "v2", k3 = "v3"}
local a = {} -- array to accumulate key-value pairs
local n = 0 -- number of key-value pairs
for key, value in pairs(t) do
     n = n + 1
     a[n] = key.. " = ".. Value -- add key-value pair to the array
end
local s = table.concat(a, ";") -- concatenate all key-value pairs into one string

<!--NeedCopy-->

もう 1 つの便利なイテレータは、 string.gmatch()COMBINE_HEADERS() 次の例で使用される関数です。

関数