Lutger Blijdestijn wrote: > The restriction with calling zero-args functions is unfortunate, > could this be solved by turning it into a class and dynamically > checking whether the type is a function and then invoke it if it is?
Maybe, but I think it'd still break the property get, which breaks setting complex types. This, and your other concern about implicit declarations are actually caused by the same root problem: the imperfect compiler implementation of properties combined with variadic opDispatch templates. (Like I said in that other thread, each of those features works quite well on its own, but the combination reveals some minor bugs.) To set a complex type, you do the: dyn.property() = some fancy thing; Which returns a property by reference, then does its opAssign template, which is much more capable of fanciness than the runtime variadic function you get without the parenthesis. Why do that? Because overloading on property and non-property doesn't work right now. Through trial and error, I found the compiler doesn't add a property assignment's type to the template argument list, but does pass it as a func argument. (Quite possibly a (minor) compiler bug itself - I may be depending on one bug to work around another!) So, if you try to do a template, it will complain about wrong number of arguments to the function. A variadic function gets that error to go away and I can handle it at runtime. This comes with trade-offs though: the big one being that it doesn't work with complex types. Like the code's comment says, I really need the compiler's help to make them work, and it isn't around by the time any of that code is actually run. The best situation would be: @property Dynamic opDispatch(string fieldName)() // getter Dynamic opDispatch(string fieldName, T...)(T t) // function call, // any num of args @property Dynamic opDispatch(string fieldName, T)(T t) // setter Then everything would Just Work, without the limitations of the runtime variadic and associated workarounds. But the first two are broken by @property not being recognized in overloads currently*, and the last is broke by the right-hand side of the property assignment not being passed as a template argument. * My preferred fix here would be to give @property one more point in overload resolution so it is slightly preferred over non-property in these situations, but otherwise do nothing. It's the most conservative solution here. I looked at dmd's code, but I don't know the compiler well enough to make it happen. I guess if @property was strengthened, I could work with that too, just by adding an opCall and leaving opDispatch to do nothing but get and set. The property assign not being passed to the template would have to be solved somehow there too though. Anyway, none of the fixes are in place today, so I had to make a choice - either setting requires a named function call or zero arg calling requires a named function. I went with the latter since I figured it is a bit prettier in usage. > I would also change implicit declarations into an error, I see > you have an throw statement for that but commented out. Yes, the main reason is so the ref returns don't do range violation when you are trying to do an assignment, due to the above situation. It would work with simple assignment: dynobj.name; // throws dynobj.name = 10; // works dynobj.name; // still works But complex assignment won't work there: dynobj.name = someDelegate; // this won't work right, probably // will segfault down the line if I don't throw at runtime over it So my compromise was: dynobj.name() = someDelegate; // uses the opAssign template // which works well But... if dynobj.name didn't already exist, the left hand side of that would throw a range violation, getting a property that doesn't exist. That's why the exception is commented. If I required a .set() method or something like that: dynobj.set("name", whatever you want); That would work, but it no longer looks like a dynamic language... When the compiler progresses a little more (or maybe someone will think of a nicer workaround), we can have the best of all worlds, but for now this is the best I can do while keeping a mostly dynamic language like appearance. (Now, a related question here is weak typing in general. I'm writing this to be very weakly typed - coercing all over the place. Dynamic languages can throw a runtime exception on type mismatch, but I want to basically mimic javascript here, which does not. Besides, D itself is strongly typed - if you want strong types, just use standard D types! Possibly including std.variant.)