2011-08-04 10 views
8

私は、(私はのソートは、スキームにそれを理解する)とD 2.0でそれを実装Yコンビネータよりよく学ぶことをしようとしていると私はかなり惨めに失敗しています:DのY-コンビネータ?

auto fact = delegate(uint delegate(uint) recurse) 
{ 
    return delegate(uint n) 
    { 
     return n > 1 ? n * recurse(n - 1) : 1; 
    }; 
}; 

fact(fact)(5); 

これにはありません私はfactfactに渡すことができないという明白な理由のために働いています(そのタイプは何でしょうか?)。そして、私はまだfactの名前を自分に渡す必要があるので、とにかくうまくいかないでしょうか?

しかし、私はどのようにDにY-コンビネータを実装するのですか?

+0

デリゲートはすでに参照型です。あなたは '&'を削除できます。 – BCS

+0

@BCS:良い点は、もともとの方法であり、私はそれを取り除くことを忘れてしまった。修正されます。 :) – Mehrdad

答えて

7

詳細な説明hereを参照してください。

+0

重要な機能Dの欠如(C#と比較して)は、署名自体の中で代理エイリアスの名前を使用する能力であると思われます... – Mehrdad

+0

RosettaCodeのサンプルコードが動作するので、Dが重要でない特徴? – gmfawcett

+1

RosettaCodeのサンプルコードは、醜い問題を回避するために型キャストを使用しています。構造体は構造体の中にデリゲートをラップすることができます。なぜなら、構造体はその型が再帰的に構造体型に依存するメンバを持つことができるからです。しかし、Mehrdadには、コンパイラがエイリアス再帰のほとんどの形式を許可しないため、エイリアス宣言が必要以上に制限されているという点があります。 (例:struct Foo(T){Bar * qux;}エイリアスFoo!int Bar; //コンパイルエラー struct Foo(T){。Foo!int * qux;} // works) – tgehr

3

私はDを知りませんが、ほとんどの言語では、非再帰を実装しようとすると関数の型に問題が発生します(まだコードにY-Combinatorはありません)。型を複数の部分に分割し、このようにして型への再帰を取得することで、通常の方法を実現できます。他の言語から

いくつかの例:Cの一

  • 通常の関数ポインタを含む構造体を書き込みます。この構造体は、引数として使用できます。

  • OCamlでは、関数型をラップするバリアント型を追加します。この場合も、型の分離が可能になり、型の再帰が可能になります。

他の言語の例が必要な場合は、this pageをご覧ください。

4

型付きの自己参照を扱う関数は宣言することができない(最後に私がチェックした)ことはD(およびC/C++)の既知の制限です。

意味的またはアーキテクチャ的な意味ではなく、構文の制限(関数のプロトタイプの長さは無限)または命名規則(同じ問題ですが名前のマングリング)になります。

+0

+1ちょっとばかげて、機能を自分自身に渡す方法を頭に入れようとすると、本当に混乱していました。彼らはこれを修正する予定ですか? (例えば 'void foo(typeof(foo)){}'は 'forward reference'エラーを返します) – Mehrdad

+0

@Mahrdad:私が知っているわけではありません。 OTOHでは、項目の周りの小さなラッパーが問題を修正しています。 – BCS

+0

ところで、ハスケルはまた、「無限の長さの型を宣言することはできません」というようなことをしません – vines

3

Dでの私の一般的なYコンビネータ:

import std.stdio, std.algorithm, std.range; 
auto Y(R,T...)(R delegate(T) delegate (R delegate(T)) f){ 
    struct F{R delegate(F,T) f;}; 
    return (R delegate(T)delegate(F) a){return a(F((F b,T i){return f(a(b))(i);})); 
    }((F b){return (T n){return b.f(b,n);};}); 
} 
void main(){ 
    auto factorial=Y((long delegate(long) self){return (long i){return i?self(i-1)*i:1;};}); 
    auto fibonacci=Y((int delegate(int) self){return (int i){return i<2?i:self(i-1)+self(i-2);};}); 
    auto ackermann=Y((long delegate(long,long) self){return (long n,long m){return n?m?self(n-1,self(n,m-1)):self(n-1,1):m+1;};}); 
    writeln(map!factorial(iota(0,20))); 
    writeln(map!fibonacci(iota(0,20))); 
    writeln(map!((a){return ackermann(a%4,a/4);})(iota(0,20))); 
} 

私は階乗関数の自明な再帰的定義から始まり、私のコードは次のように見えたまでそれを修正。無限型の問題は型ラッパー(構造体F)で回避されています。

関連する問題