haxe3: Dynamic falls back to 'resolve()' on existing variable. Why?

66 views
Skip to first unread message

Ma rk

unread,
Aug 14, 2014, 8:04:04 AM8/14/14
to haxe...@googlegroups.com
hi Guys,

Just started learning Haxe so I might made a childish mistake :) Thanks for all the help in advance!

Doc says if a variable was not found in a class which implements "Dynamic", logic falls back to call "resolve(field:String)" function (if implemented).

I wanted to test it and it seems "resolve(field:String)" is called even if variable exists, which means, I cannot retrieve/use the value I stored previously.

Please explain why or let me know if it's a bug so I can report it. Thank you in advance!


The code below is 95% of docs sample. I added my part at Foo.main(), also commented those lines
class Resolve implements Dynamic<String> {
 
public var present:Int;
 
public function new() {}
 
function resolve(field:String) {
   
return "Tried to resolve " + field;
 
}
}

class Foo {
 
static public function main() {
   
var c = new Resolve();
    c
.present = 2;
    c
.uncleFoo = "hehehe"; //OK as no error
    trace
(c.present);      //OK as result is fine
    trace
(c.uncleFoo);     //NOK! Falls back to call resolve - Why???
   
//c.uncleFoo = 103;    //OK as error: "Int should be String" == variable exists
  }
}

compile/run:
Call [path][\ | /]haxe.exe -main Foo --interp

result:

Foo.hx:14: 2
Foo.hx:15: Tried to resolve uncleFoo

line 14 is OK, but line 15 should be "hehehe", doesn't it?

If not, how am I supposed to use the string value I stored in object "c" (of class Resolve)?


Thank you again!


All the Best,
Mark

Simon Krajewski

unread,
Aug 14, 2014, 8:13:22 AM8/14/14
to haxe...@googlegroups.com
Class instance types don't work like structure types here: To the compiler the fields of Resolve are fixed and assigning new ones does not change the type itself. Thus it considers the field "uncleFoo" to not exist and tries to resolve it again.

I can kind of see where you are coming from because in this simple example it indeed looks like the compiler could figure it out. However, that's not really worth it because as soon as `c` leaves context, the type is the plain Resolve class again anyway. This would lead to seemingly inconsistent behavior, so the current one is preferable.

Simon

Mark

unread,
Aug 14, 2014, 8:33:33 AM8/14/14
to haxe...@googlegroups.com
Thank you for the answer and for coming back so fast.

Related to your feedback, a few questions if I may:

a) in this case, why don't I get a compile-time error trying to assign a value to "uncleFoo"? (which, I will never be able to retrieve, though)

b) why do I get an error trying to assign an Int value to it after I "set type" to String? (I understand "technically why". But as this is a write only, unable to ever use 'property'... it doesn't seem to matter what is assigned to it. Or it does?)

c) last but not least: the value I assigned is "stored", right? Otherwise I could not raise error in question "b".
Storing the value in memory (as long as I'm within context) looks a waste of processing time & stack ram. Isn't that a bad behaviour? (Even if it's my fault after all :).


Thank you again!
Mark




--
To post to this group haxe...@googlegroups.com
http://groups.google.com/group/haxelang?hl=en
---
You received this message because you are subscribed to a topic in the Google Groups "Haxe" group.
For more options, visit https://groups.google.com/d/optout.

Simon Krajewski

unread,
Aug 14, 2014, 8:41:02 AM8/14/14
to haxe...@googlegroups.com
Am 14.08.2014 14:33, schrieb Mark:
Thank you for the answer and for coming back so fast.

Related to your feedback, a few questions if I may:

a) in this case, why don't I get a compile-time error trying to assign a value to "uncleFoo"? (which, I will never be able to retrieve, though)

You should be able to retrieve it using `Reflect.field(c, "uncleFoo")` or by hiding the type of `c`, e.g. by doing `(c : Dynamic).uncleFoo`. In that case the compiler doesn't know what type `c` has and cannot resolve to its `resolve` method, defaulting to dynamic access.


b) why do I get an error trying to assign an Int value to it after I "set type" to String? (I understand "technically why". But as this is a write only, unable to ever use 'property'... it doesn't seem to matter what is assigned to it. Or it does?)

Because you used `implements Dynamic<String>`, which means all dynamically accessed types must be of String. You can use `implements Dynamic` if you want to get rid of that restriction.


c) last but not least: the value I assigned is "stored", right? Otherwise I could not raise error in question "b".
Storing the value in memory (as long as I'm within context) looks a waste of processing time & stack ram. Isn't that a bad behaviour? (Even if it's my fault after all :).

Yes, it is stored and can be retrieved by means mentioned in a).

Simon

You received this message because you are subscribed to the Google Groups "Haxe" group.

Mark

unread,
Aug 14, 2014, 8:51:26 AM8/14/14
to haxe...@googlegroups.com
HAHH! All clear now, thank you for the help!

(Tricky language. I love it already ;)


杨博

unread,
Aug 15, 2014, 1:37:52 PM8/15/14
to haxe...@googlegroups.com
I think reflective accessing and the resolve feature should implement different types. e.g. Dynamic<String> vs DynamicResolver<String>

在 2014年8月14日星期四UTC+8下午8时41分02秒,Simon Krajewski写道:
Reply all
Reply to author
Forward
0 new messages