On 1/6/11 11:52 AM, Robert Jacques wrote:
And Variant still only holds an object of some preexisting type. What
you are seeing is simply syntactic sugar for a Variant of type
Variant[string]. The above lowers down into:

Variant v;
Variant[string] __temp;
v = __temp;
v["a"] = 10;
assert(v["a"] == 10);
v["a"] = { writefln("hello, world"); };
v["a"].call();
v["a"] = delegate void(string a, int x) { foreach(i;0..x) writeln(i+1,"
",a); };
v["a"].call("potatoes", 3);

The only morph happens because actually making the Variant default type
be Variant[string], has some issues (GC interaction, hasValue,
Variant[string].init isn't usable, etc). So I decided that if and only
if you used an uninitialized Variant as a Variant[string], it would
'morph' to a Variant[string].

I think Variant should default to holding "void".

As for the v.a -> v["a"] syntactic sugar, I have found it very useful in
the parsing/use of dynamically structured structs, including JSON.

That's great, but (a) that's again outside what Variant is supposed to do, and (b) for JSON we're dealing with a closed hierarchy which suggests a different design.

* Algebraic holds any of a closed set of types. It should define
method calls like a.fun(args) if and only if all of its possible types
support the call with compatible arguments and return types.

I have considered this, but while this concept looks good on paper, in
practice it cripples Algebraic. The issue is that the intersections of
types tend to have no methods/operators in common. For example,
Algebraic!(int,string) would have no methods nor operators defined.

Algebraic with the fundamental JSON types is a great example because they all may share certain methods. Generally Algebraic with closed hierarchies (e.g. Visitor) are good candidates for the feature. Of course, if that feature affects other functionality we should avoid it. It's just "nice to have".

* Variant holds any of an unbounded set of types. Reflection may allow
us to define v.fun(args) to look up the method name dynamically and
issue a runtime error if it doesn't exist (sort of what happens now
with operators).

It's not 'may' anymore. Reflection _does_ allow me to define v.fun(args)
to look up the method name dynamically and issue a runtime error if it
doesn't exist. eg:

class Foo { real x = 5; }
auto foo = new Foo;
Variant a = foo;
assert(a.x == 5); // perform runtime reflection on 'a' implicitly
a.__reflect("x",Variant(10)); // or explicitly
assert(a.__reflect("x") == 10);

* Dynamic is a malleable type that you get to add state and methods
to, just like in Javascript.

And I have stubbed out a Prototype object for just this reason.

Great. Why not call it "Dynamic"?


Andrei

Reply via email to