デリゲート

提供: AliceScript Wiki
2022年1月12日 (水) 04:01時点におけるMaster (トーク | 投稿記録)による版 (式形式のラムダ)
ナビゲーションに移動 検索に移動

デリゲートは、AliceScriptにおける”匿名関数”のメカニズムです。デリゲートは匿名関数として、その場ですぐに実行したり、変数に代入したり、関数に引数として渡すことができます。

例えば、蔵書検索アプリケーションを作成することを考えてみましょう。この検索にはAND検索、OR検索、完全一致検索が用意されています。 いずれの場合も、Seartch()関数が行うことは基本的に同じです。つまり、なんらかの条件に基づいて一連の蔵書から項目を検索します。しかし、条件に基づいて検索するコードはそれぞれの条件によって異なります。

ソフトウェアには、この種の手法が半世紀にわたって使用されてきました。AliceScriptのデリゲートは、さらに思い通りのプログラミングを実現します。

デリゲートには次の特徴があります。

  • デリゲートを使用すると、関数を引数として渡すことができます。
  • デリゲートは、コールバック関数の仕組みを実現するのに使用できます。
  • デリゲートは連結でき、たとえば、複数の関数を1つのイベントで呼び出すことができます。

この記事ではdelegateキーワードまたはラムダ式とそれによってサポートされる機能、delegate型に実装される機能を説明します。

delegate
名前空間 Alice
アセンブリ ローカル
サポート AliceScript1
属性 言語構造

基本

デリゲート型は、delegateキーワードと、そのデリゲートの実行に必要な引数を指定して宣言されます。

引数はかっこで囲み、各引数をコンマで区切ります。括弧内を空にすると、デリゲートは引数が不要なことを意味します。

デリゲートを同期的に呼び出すには関数のように丸括弧を使用して呼び出すか、Invokeメソッド使用し、非同期的に呼び出すにはBeginInvokeメソッドを使用します。 また基本的には、引数の指定方法や戻り値に関する詳細は関数と同じです。詳しく知るには関数の記事も参照してください。

次の例にはデリゲートを生成し、それをSayHelloとして定義します。SayHelloが呼び出されたとき、標準出力にHello,World!を書き込みます。

var SayHello = delegate()
 {
   print("Hello,World!");
 }
SayHello();//出力例:Hello,World!

ラムダ式

ラムダ式を用いてデリゲートを生成することもできます。ラムダ演算子=>は、引数指定部と式本体を分割する役割を持ちます。

ラムダ式には、次の2つの形式があります。

式形式のラムダ

式形式のラムダは、次の形です。

(input-parameters) => expression

式形式のラムダは、呼び出された時にその式の値を返します。次の例では、xを二乗した値を返すデリゲートをpowという名前で宣言します。

var pow = (x) => x * x;
print(pow(2));//出力例:4

ステートメント形式のラムダ

(input-parameters) => { <sequence-of-statements> }

関数からの暗黙的な変換

ほとんどのネイティブ関数とユーザー定義関数は、デリゲート型の変数へと暗黙的に変換できます。ユーザー定義関数を丸括弧なしで呼び出すと、それはその関数をデリゲート型に変換されたオペランドと認識されます。次に例を示します。

function SayHello()
 {
    print(“Hello,World”);
 }
var hello=SayHello;//helloは、DELEGATE型を表します
hello();//出力:Hello,World

ただし、以下の属性を持っている関数を暗黙的に変換することはできません。

  • 言語構造
  • 関数の区切り文字の空白をサポート
  • 単一の引数のみ関数の区切り文字の空白をサポート

また、FunctionBase型を継承しない関数も、この機能をサポートしません。

関数の属性について詳しく知るには、関数の記事を参照してください。

デリゲートの組み合わせ

デリゲート型は、複数のデリゲートを一つに結合することができます。組み合わされたデリゲートの各ステートメントは、順番に実行され、foreach文を使用して一つずつに分解することも可能です。上記の例ですでにSayHelloを定義しましたから、もう一つ、SayBonjurデリゲートを定義し、それらを結合して実行する例を示します。

var SayBonjur = delegate()
 {
    print(“Bonjur”);
 }
var Say = SayHello+SayBonjur;
Say();
//出力例:Hello,World!
//     :Bonjur

イベント駆動型プログラム

イベント駆動型プログラムは例えば「キーボードが押下された」とか、「マウスが移動した」などの受動的なイベントの発生によってコードが実行されるプログラムです。AliceScriptでは、デリゲート型とその組み合わせによって実現できます。ここでは簡単なサンプルとして、1秒おきにHello,Worldを表示し続け、それをeキーが押下されたときに停止するプログラムを作成します。このコードでは非同期的に1秒前にHello,Worldを表示し続け、同時に同期的にキーの押下を待機し続け、なんらかのキーが押下されたときにOnkeyDownにキーの情報を渡して呼び出します。

var OnKeyDown;
(()=>{
  //非同期に実行されるコード
  while(true)
   {
      OnKeyDown(Console_ReadKey());
   }
}).BeginInvoke();

//OnKeyDownに次のコードをイベントハンドラとして登録します
OnKeyDown+=(key)=>
 {
    if(key==“e”)
     {
         exit;
     }
 }
 while(true)
  {
     print(“Hello,World”);
     delay(1000);
  }

実際に実行すると次のように動作します。

Hello,World
Hello,World
Hello,World
Hello,World
eキーを押下すると終了します

Invoke

variable delegate.Invoke(params args);

現在のデリゲートに指定された引数を渡して実行し、その戻り値を返します。

BeginInvoke

void delegate.BeginInvoke(params args);

現在のデリゲートをすべて非同期で実行します。

Length/Count

number delegate.Length;
number delegate.Count;

現在のデリゲートに含まれる要素の数を返します。