【お知らせ】プログラミング記事の投稿はQiitaに移行しました。

無名関数

無名関数を実装しました。

当初は難易度が高いので後回しにしようと思っていたのですが、関数定義に関数ポインタの値を持たせれば式の中で扱えることに気付きました。そのためすぐに実装できました。

使用例

var f = function(a, b) { return a - b; };
printfln("f(5, 3) = %d", f(5, 3)); 

仮想関数

無名関数の応用で仮想関数を実現することができます。

struct Test1
{
  function ctor()
  {
    Virt();
  }

  var virt = function(this : Test1)
  {
    printfln("Test1.Virt");
  };
  
  function Virt()
  {
    virt(this);
  }
}

struct Test2 : Test1
{
  virt = function(this : Test2)
  {
    printfln("Test2.Virt");
  };
}

Test1 t1;
Test2 t2; 

このような書き方は周りくどいため、言語仕様で仮想関数をサポートする予定です。

なお、コンストラクタが呼び出される前にメンバへの代入が行われるため、ベースクラスのコンストラクタから派生クラスの仮想関数を呼び出すことが可能です。上記コードでは利用しています。これを実現するために混乱気味だったコンストラクタ周りの処理を見直しました。

問題点

このような簡単な実装では別の関数を通すとスタックフレームが失われてしまうため、クロージャとして使うことができません。具体的には次のような操作はできません。

function test1()
{
  var a = 1;
  test2(function() { return a; });
}

function test2(f)
{
  printfln("%d", f());
}

ローカル変数が使えなければ無名関数の使い勝手が大きく制限されるため、今後の検討課題とします。なお、仮想関数はthisポインタを明示的に渡すことで問題を回避しています。