Calling method by name.
Jonathan M Davis
jmdavisProg at gmx.com
Thu Feb 3 20:32:21 PST 2011
On Thursday 03 February 2011 20:23:25 Andrew Wiley wrote:
> On Thu, Feb 3, 2011 at 10:07 PM, Jonathan M Davis <jmdavisProg at gmx.com>wrote:
> > On Thursday 03 February 2011 19:29:15 Robert Jacques wrote:
> > > On Thu, 03 Feb 2011 08:49:54 -0500, Jacob Carlborg <doob at me.com> wrote:
> > > > On 2011-02-03 05:52, Robert Jacques wrote:
> > > >> On Wed, 02 Feb 2011 12:55:37 -0500, %u <fghf at jhgjhb.com> wrote:
> > > >>> I know is possible to create an object from its name. It's possible
> >
> > to
> >
> > > >>> call a method from that object if the name is only known at
> > > >>> runtime?
> > > >>>
> > > >>> Would something like the following be possible?
> > > >>>
> > > >>> string classname, methodname;
> > > >>> // Ask the user for class and method.
> > > >>> auto obj = Object.factory(classname);
> > > >>> invoke(methodname, obj, param1, param2);
> > > >>>
> > > >>> Thanks
> > > >>
> > > >> I've been working on an update to std.variant, which includes a
> > > >> compile-time reflection to runtime-reflection system. (See
> > > >> https://jshare.johnshopkins.edu/rjacque2/public_html/) From the
> > > >> docs:
> > > >>
> > > >> Manually registers a class with Variant's runtime-reflection system.
> > > >> Note that Variant automatically registers any types it is exposed.
> >
> > Note
> >
> > > >> how in the example below, only Student is manually registered; Grade
> >
> > is
> >
> > > >> automatically registered by Variant via compile-time reflection of
> > > >> Student.
> > > >>
> > > >> module example;
> > > >> class Grade { real mark; }
> > > >> class Student { Grade grade; }
> > > >> void main(string[] args) {
> > > >> Variant.__register!Student;
> > > >> Variant grade = Object.factory("example.Grade");
> > > >> grade.mark(96.6);
> > > >> assert(grade.mark == 96.6);
> > > >> }
> > > >>
> > > >> And dynamic method/field calls are handled via the __reflect(string
> > > >> name, Variant[] args...) method like so:
> > > >>
> > > >> grade.__reflect("mark",Variant(96.6));
> > > >> assert(grade.__reflect("mark") == 96.6);
> > > >
> > > > Why would you need to pass in Variants in __reflect? Why not just
> > > > make it a variadic method and automatically convert to Variant?
> > >
> > > Well, opDispatch does exactly that. __reflect, on the other hand, was
> > > designed as a quasi-backend function primarily for a) internal use
> > > (hence the double underscore), b) scripting language
> > > interfacing/implementing
> >
> > and
> >
> > > c) user-extension. So efficiency was of key importance. And the
> >
> > reflection
> >
> > > system is extensible, as Variant knows to call __reflect on user
> > > defined types. This makes things like prototype style objects
> > > possible. (There's even a beta implementation of a prototype object in
> > > the library) But this requires that the use __reflect methods not be
> > > templated.
> > >
> > > I'm not well versed in dynamic reflection and its use cases, so when I
> > > considered the combination of a runtime method name and compile-time
> > > argument type information, I classed it as 'rare in practice'. But if
> > > that's not the case, I'd like to know and would greatly appreciate a
> > > use case/unit test.
> >
> > Most of the good examples of runtime reflection that I'm aware of require
> > user-
> > defined attributes. But there are libraries in Java (and presumably C#)
> > that do
> > stuff like allow you to mark your classes with certain attributes
> > indicating what
> > type of XML elements that they should be, and then another library which
> > knows
> > _nothing_ about your classes is able to serialize them to and from XML.
> > Another
> > example would be Hibernate, which does the same sort of stuff only it
> > deals with
> > talking to databases. Full-on runtime reflection combined with
> > user-defined attributes can do some powerful stuff. However, I do think
> > that runtime reflection
> > without user-defined attributes doesn't tend to be anywhere near as
> > useful. To
> > really get that sort of stuff working, we'd need D to properly support
> > both user-
> > defined attributes and runtime reflection. Both are future possibilities
> > but
> > obviously aren't happening any time soon.
>
> I would argue that if user-defined attributes could be implemented and tied
> into the existing compile time reflection system, we could reap similar
> benefits. One popular pattern in the serialization libraries you describe
> is that, for performance reasons, runtime reflection can be abandoned in
> favor of runtime code generation, where the same reflection system is used
> once to dynamically write code that can be used repeatedly. D has the
> advantage that such code can be written at compile time.
> True, runtime reflection would make this sort of thing more clean and
> decoupled, but even using compile time reflection, quite a bit is feasible
> if user-defined attributes are defined.
I've never really sat down to try and figure out how well compile time reflection
would work for that sort of thing (particularly since D is the only language I
know of with any kind of compile time reflection), but since we don't have user-
defined attributes yet, we can't do it regardless. If we could pull it off with
compile time reflection, then maybe we wouldn't really need runtime reflection. I
don't know. But we'll need user-defined attributes before we can do anything like
that, and exactly what the limitations and possibilities are may not be
particularly clear before we can actually play around with user-defined
attributes and compile time reflection. You may be right though, and runtime
wouldn't be needed to do some of the cooler things that you can do with runtime
reflection in languages like Java. Regardless, I've found compile time reflection
to be far more helpful in my everday code than I've ever found runtime reflection
to be.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list