如何在 Javascript 中制作相互递归的结构



我想知道在Javascript中是否有可能拥有相互递归的对象,如果是,如何?

目标:

我想有三个对象:

  1. 一个表示具有两个值Boolean TrueFalse
  2. 的类型
  3. 表示Boolean类型的True对象
  4. 表示Boolean类型的False对象

诀窍是我想询问True对象的类型,我应该返回Boolean对象,我想向Boolean对象询问其值,我应该返回 2 个对象:True对象和False对象。

但它应该是完全相互递归的,因为我得到了这样的东西(尽管它不一定完全像这样):

True 
// {name : "True", type : [Object object]}
False
// {name : "False", type : [Object object]}
Boolean 
// {name : "Boolean", values : [Object object]}
Boolean.values  
// {True: [Object object], False: [Object object]}
True.type
// {name : "Boolean", values : [Object object]}
False.type
// {name : "Boolean", values : [Object object]}
Boolean.values.True 
// {name : "True", type: [Object object]}
Boolean.values.True.type 
// {name : "Boolean", values : [Object object]}
Boolean.values.True.type.values 
// {True : [Object object], False: [Object object]}

等等...

如果有帮助,它们应满足以下属性:

Boolean === Boolean.values.True.type 
Boolean === Boolean.values.True.type.values.True.type
True === Boolean.values.True
True === True.type.values.True.type.values.True.type.values.True
False === Boolean.values.False
False === True.type.values.False

这样做的能力应该是无限的

注意

这些可以是函数而不是对象。而且呼叫不必完全像这样。

你来了:

//Define the top level objects but avoid recursion
var True = {};
var False = {};
var Boolean = {
    values: {
        True: True,
        False: False
    }
};
//Create the recursion
True.type = Boolean;
False.type = Boolean;

这很简单:

var Boolean = {
    name: "Boolean",
    values: {
        True: {
            name: "True"
        },
        False: {
            name: "False"
        }
    }
};
var True = Boolean.values.True;
var False = Boolean.values.False;
True.type = Boolean;
False.type = Boolean;

您是否正在尝试创建代数数据类型?


编辑:这就是我创建代数数据类型的方式:

function data(constructors) {
    var factory = function (constructor) {
        this.constructor = constructor || this;
    };
    var type = factory.prototype = {};
    for (var name in constructors) {
        var fields = constructors[name];
        if (fields) {
            var body = ["    var data = new " + name + "(arguments.callee);"];
            var length = fields.length;
            var params = [];
            for (var i = 0; i < length; i++) {
                var param = "arg" + i;
                body.push("    data." + fields[i] + " = " + param + ";");
                params.push(param);
            }
            body.unshift("return function (" + params.join(", ") + ") {");
            body.push("    return data;", "};");
            type[name] = Function(name, body.join("n"))(factory);
        } else type[name] = new factory;
    }
    return type;
}

使用数据函数,我们可以定义代数数据类型,如下所示:

var Boolean = data({
    True: null,
    False: null
});
var True = Boolean.True;
var False = Boolean.False;
var List = data({
    Nil: null,
    Cons: ["head", "tail"]
});
var Nil = List.Nil;
var Cons = List.Cons;

它具有以下不变量:

Object.getPrototypeOf(True) === Boolean;
Object.getPrototypeOf(False) === Boolean;
Object.getPrototypeOf(Nil) === List;
Object.getPrototypeOf(Cons(0, Nil)) === List;
True.constructor === True;
False.constructor === False;
Nil.constructor === Nil;
Cons(0, Nil).constructor === Cons;

使用它,您可以创建纯函数,如下所示:

List.map = function (f) {
    switch (this.constructor) {
    case Nil: return Nil;
    case Cons:
        var x = this.head;
        var xs = this.tail;
        return Cons(f(x), xs.map(f));
    }
};
function map(f, a) {
    return a.map(f);
}

您可以按如下方式使用它:

function toList(a) {
    var list = Nil;
    for (var i = a.length - 1; i >= 0; i--) list = Cons(a[i], list);
    return list;
}
var xs = toList([1,2,3]);
var ys = map(function (a) {
    return a * 2;
}, xs);

希望有帮助。

最新更新