January 17, 2014
On Friday, 17 January 2014 at 17:50:54 UTC, H. S. Teoh wrote:
> On Fri, Jan 17, 2014 at 05:29:14PM +0000, Gary Willoughby wrote:
>> On Friday, 17 January 2014 at 15:56:46 UTC, H. S. Teoh wrote:
>> >Couldn't you just return a Variant? I thought this is what Variants
>> >are made for.
>> >
>> >
>> >T
>> 
>> Yes but then i would need to coerce it to get it's underlying type.
>
> But isn't that what you'd have to do anyway? I mean, how else would the
> following code work?
>
> 	class DynClass {
> 		...
> 		auto opDispatch(string field)() {
> 			return dotDotDotMagic();
> 		}
> 	}
>
> 	void main(string[] args) {
> 		auto d = new DynClass();
> 		if (args[1] == "int")
> 			d.abc = 123; // d.abc = int
> 		else
> 			d.abc = "xyz"; // d.abc = string
>
> 		// Suppose this somehow works:
> 		auto x = d.abc;	// what's the type of x?
> 	}
>
> Since the type of x must be known at compile-time, but the type of d.abc
> can't be known until runtime, the above code can't possibly work unless
> d.abc returns a Variant. It's simply not possible for a
> runtime-determined type to be put into a variable of compile-time
> determined type without some kind of runtime check.
>
> Now I'm not sure if Variant allows assignment to a static type, but in
> theory this should be possible:
>
> 	// assume d.abc returns a Variant
> 	int x = d.abc; // will assert if d.abc doesn't hold an int at runtime
>
>
> T

In the example in my original post the types are known at compile time but they are different between properties. I wondered if there was a solution to storing and retrieving while preserving the original type via opDispatch.

I have a working solution but it only stores the base type. So i f i have an inheritance chain like this:

A -> B -> C

I can store properties of type A, B and C but when i retrieve them they all come back as A because of array covariance. I wonder if there is a way of casting them automagically to the correct type.
January 17, 2014
> I can store properties of type A, B and C but when i retrieve them they all come back as A because of array covariance. I wonder if there is a way of casting them automagically to the correct type.

So you basically want to declare a classmember for every name opDispatch is called with? That is not possible;

I thought about declaring it static in opDispatch itself, but than you can only have one instance. Next thought: Declare a static hashmap and store the values there, but then you could just use std.variant.
January 17, 2014
On Fri, Jan 17, 2014 at 06:49:25PM +0000, Gary Willoughby wrote: [...]
> In the example in my original post the types are known at compile time but they are different between properties. I wondered if there was a solution to storing and retrieving while preserving the original type via opDispatch.
> 
> I have a working solution but it only stores the base type. So i f i have an inheritance chain like this:
> 
> A -> B -> C
> 
> I can store properties of type A, B and C but when i retrieve them they all come back as A because of array covariance. I wonder if there is a way of casting them automagically to the correct type.

Is it possible, at compile-time, to determine the type just from the property name alone? If not (i.e., different class instances may have a property named "abc" map to int or string, respectively), then this is not possible, because the return type of opDispatch can only depend on its compile-time parameter, that is, the property name.

If there's a compile-time procedure for determining the type of a property solely from its name, then yes, this is possible. What you do is to first determine the return type from the property name (at compile-time!), hash the .mangleof of this type, and store an AA of AA's of property values, with the outer AA keyed by the hash value. Something like this:

	class MyClass {
		Variant[string][size_t] props;

		auto opDispatch(string ident)() {
			alias returnType = ... /* determine type from ident */;
			enum id = hashOf(T.mangleof); // unique ID for T

			return cast(returnType)props[id][ident];
		}
	}

The success of this depends on whether it's possible to determine the return type from the property name (at compile-time), though. If that's not possible, then this doesn't work.


T

-- 
Acid falls with the rain; with love comes the pain.
January 17, 2014
On Fri, Jan 17, 2014 at 07:08:54PM +0000, Tobias Pankrath wrote:
> >I can store properties of type A, B and C but when i retrieve them they all come back as A because of array covariance. I wonder if there is a way of casting them automagically to the correct type.
> 
> So you basically want to declare a classmember for every name opDispatch is called with? That is not possible;
> 
> I thought about declaring it static in opDispatch itself, but than you can only have one instance. Next thought: Declare a static hashmap and store the values there, but then you could just use std.variant.

One of the reasons this breaks down is because of situations like this:

	class MyClass {
		...
		auto opDispatch(string op)() {
			return ... /* assume we magically return the right type here */;
		}
	}

	// Which of these assignments to 'abc' should determine its
	// type? What if the function that gets called is determined at
	// runtime only? What if they are in two separately-compiled
	// modules?

	void fun(MyClass o) {
		o.abc = 123;
	}

	void gun(MyClass o) {
		o.abc = "xyz";
	}

	auto x = o.abc; // what's the type of x?

Another problematic case:

	auto o = new MyClass;
	auto p = new MyClass;

	o.abc = 123;
	p.abc = "xyz";

	// Problem: now the return type of opDispatch cannot be
	// determined at compile-time.

Now, if you decide beforehand that "abc" is always an int, and "def" is always a string, then this problem is avoided:

	o.abc = 123; // OK
	p.abc = 123; // OK
	o.abc = "xyz"; // compile error
	p.abc = "xyz"; // compile error
	o.def = "xyz"; // OK
	p.def = "xyz"; // OK
	o.def = 123; // compile error
	p.def = 123; // compile error


T

-- 
Freedom of speech: the whole world has no right *not* to hear my spouting off!
January 17, 2014
On 2014-01-17 18:49, H. S. Teoh wrote:

> Now I'm not sure if Variant allows assignment to a static type, but in
> theory this should be possible:
>
> 	// assume d.abc returns a Variant
> 	int x = d.abc; // will assert if d.abc doesn't hold an int at runtime

It doesn't work. Variant doesn't retain the static type, which is needed in this case.

-- 
/Jacob Carlborg
January 17, 2014
On Fri, Jan 17, 2014 at 09:08:50PM +0100, Jacob Carlborg wrote:
> On 2014-01-17 18:49, H. S. Teoh wrote:
> 
> >Now I'm not sure if Variant allows assignment to a static type, but in theory this should be possible:
> >
> >	// assume d.abc returns a Variant
> >	int x = d.abc; // will assert if d.abc doesn't hold an int at runtime
> 
> It doesn't work. Variant doesn't retain the static type, which is needed in this case.
[...]

Is that because D doesn't have implicit casting via opCast? -- because, conceivably, if

	x = d.abc;

gets lowered to

	x = d.opCast!(typeof(x))(d.abc);

then the above can be made to work.


T

-- 
If you look at a thing nine hundred and ninety-nine times, you are perfectly safe; if you look at it the thousandth time, you are in frightful danger of seeing it for the first time. -- G. K. Chesterton
January 17, 2014
On 2014-01-17 22:14, H. S. Teoh wrote:

> Is that because D doesn't have implicit casting via opCast? -- because,
> conceivably, if
>
> 	x = d.abc;
> 	
> gets lowered to
>
> 	x = d.opCast!(typeof(x))(d.abc);
> 	
> then the above can be made to work.

I don't know, maybe.

-- 
/Jacob Carlborg
1 2
Next ›   Last »