Does D have reflection?












1















Does D have reflection or anything close to it, to be able to access objects at runtime ?



if not :



How exactly would I access or edit objects at runtime ?



for example :



bool myFunc(string status){
switch(status){
case "create":
Object my_obj = new createObject();
write("Object has been created or whatever");
break;

case "mutate":
//Don't want to have to make a global declaration
my_obj.attribute = "A meme";
write("Object has been mutated or whatever");
break;

case "delete":
//Don't want to have to make a global declaration
delete();
write("Object has been deleted or whatever");
break;

default:
//blah
break;
}


return true;
}



void main(){
while(true)
{String status = readln();myFunc(status);}



}


This is all I can think of at the moment, please let me know what I misunderstand about D in regards to this topic.



I've looked through the documentation on dlang.org and couldn't really find something to do with reflection, or at least not in the way that Java has.



ps, the above code is pseudo-code which I just made up on the spot, I'm sure for whatever reasons it would not actually compile, I'm just hoping to get through that I want access to objects in a specific way just so it convenient for me.










share|improve this question





























    1















    Does D have reflection or anything close to it, to be able to access objects at runtime ?



    if not :



    How exactly would I access or edit objects at runtime ?



    for example :



    bool myFunc(string status){
    switch(status){
    case "create":
    Object my_obj = new createObject();
    write("Object has been created or whatever");
    break;

    case "mutate":
    //Don't want to have to make a global declaration
    my_obj.attribute = "A meme";
    write("Object has been mutated or whatever");
    break;

    case "delete":
    //Don't want to have to make a global declaration
    delete();
    write("Object has been deleted or whatever");
    break;

    default:
    //blah
    break;
    }


    return true;
    }



    void main(){
    while(true)
    {String status = readln();myFunc(status);}



    }


    This is all I can think of at the moment, please let me know what I misunderstand about D in regards to this topic.



    I've looked through the documentation on dlang.org and couldn't really find something to do with reflection, or at least not in the way that Java has.



    ps, the above code is pseudo-code which I just made up on the spot, I'm sure for whatever reasons it would not actually compile, I'm just hoping to get through that I want access to objects in a specific way just so it convenient for me.










    share|improve this question



























      1












      1








      1








      Does D have reflection or anything close to it, to be able to access objects at runtime ?



      if not :



      How exactly would I access or edit objects at runtime ?



      for example :



      bool myFunc(string status){
      switch(status){
      case "create":
      Object my_obj = new createObject();
      write("Object has been created or whatever");
      break;

      case "mutate":
      //Don't want to have to make a global declaration
      my_obj.attribute = "A meme";
      write("Object has been mutated or whatever");
      break;

      case "delete":
      //Don't want to have to make a global declaration
      delete();
      write("Object has been deleted or whatever");
      break;

      default:
      //blah
      break;
      }


      return true;
      }



      void main(){
      while(true)
      {String status = readln();myFunc(status);}



      }


      This is all I can think of at the moment, please let me know what I misunderstand about D in regards to this topic.



      I've looked through the documentation on dlang.org and couldn't really find something to do with reflection, or at least not in the way that Java has.



      ps, the above code is pseudo-code which I just made up on the spot, I'm sure for whatever reasons it would not actually compile, I'm just hoping to get through that I want access to objects in a specific way just so it convenient for me.










      share|improve this question
















      Does D have reflection or anything close to it, to be able to access objects at runtime ?



      if not :



      How exactly would I access or edit objects at runtime ?



      for example :



      bool myFunc(string status){
      switch(status){
      case "create":
      Object my_obj = new createObject();
      write("Object has been created or whatever");
      break;

      case "mutate":
      //Don't want to have to make a global declaration
      my_obj.attribute = "A meme";
      write("Object has been mutated or whatever");
      break;

      case "delete":
      //Don't want to have to make a global declaration
      delete();
      write("Object has been deleted or whatever");
      break;

      default:
      //blah
      break;
      }


      return true;
      }



      void main(){
      while(true)
      {String status = readln();myFunc(status);}



      }


      This is all I can think of at the moment, please let me know what I misunderstand about D in regards to this topic.



      I've looked through the documentation on dlang.org and couldn't really find something to do with reflection, or at least not in the way that Java has.



      ps, the above code is pseudo-code which I just made up on the spot, I'm sure for whatever reasons it would not actually compile, I'm just hoping to get through that I want access to objects in a specific way just so it convenient for me.







      reflection d






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 25 '18 at 9:49







      timi95

















      asked Nov 24 '18 at 20:33









      timi95timi95

      9911




      9911
























          2 Answers
          2






          active

          oldest

          votes


















          1














          Yes, D has reflection, but no, it is not like Java.



          D's reflection comes in the form of compile time building blocks, rather than runtime methods. Of course, you can create the runtime methods yourself, but it won't just work out of the box with everything.



          I actually just wrote a thing today that reflection loops over a method to show its properties and let you edit it: https://twitter.com/adamdruppe/status/1066390612516179968 It is not done yet but I'll link so you can see some of it in action: https://github.com/adamdruppe/arsd/commit/5411dd9844869909466f2091391abe091b529bf8#diff-7a88942576365ca3d7f389b766344477R6587



          Anyway, the way I do it is to create methods out of simple loops using the reflection info. The language provides two facilities, __traits, and the is expression to do this:



          https://dlang.org/spec/traits.html



          https://dlang.org/spec/expression.html#IsExpression



          And the standard library wraps and extends with the std.traits module



          http://dpldocs.info/experimental-docs/std.traits.html



          (or if you prefer the official website of basically the same docs, just imo harder to read/navigate: https://dlang.org/phobos/std_traits.html )



          You can combine this with other code generation techniques like template mixins and traditional things like interfaces and constructors to create the runtime stuff.



          But for a simple case, try something like this:



          import std.stdio;
          import std.conv;
          import std.traits;

          class MyClass {
          void myMethod() {}
          int anotherMethod(int a) { return a; }

          // this is the runtime bridge function. The trick here is to do
          // a switch, just like your example, but the innards are auto-generated
          // from the compile time reflection.
          string call(string methodName, string args) {
          // it starts as a plain switch...
          method_switch: switch(methodName) {
          // but inside, we use a static foreach - a compile-time loop -
          // over the __traits(allMembers) magic, which gives a list of all member names
          static foreach(inspecting; __traits(allMembers, typeof(this))) {
          case inspecting: { // you can create switch cases inside these static loops
          // for this example, I only want to use callable methods, so this
          // static if - a compile time if statement - will filter out anything else.
          //
          // It is possible to do more, like plain data members, child classes, and more,
          // but that will add a lot more code. Same basic ideas with each of them though.
          static if(isCallable!(__traits(getMember, this, inspecting))) {
          // after we confirm it is callable, we can get a delegate of it
          // (same as normally doing `&member.method`) to call later.
          auto callable = &__traits(getMember, this, inspecting);

          // next is building the argument list. Parameters comes from the std.traits
          // module in the standard library and gives an object representing the function's
          // parameters. We can loop over these and set them!
          Parameters!callable arguments;
          foreach(i, ref arg; arguments) { // ref loop cuz we setting the arg members..
          // so for the runtime bridge here, I took everything as strings and
          // want to convert them to the actual method arguments. In many cases,
          // that automatic conversion will not be possible. The next bit of magic,
          // __traits(compiles), will take some code and return true if it successfully
          // compiles. Using the static if block, I can turn what would be compile time
          // errors into a runtime exception instead.
          static if(__traits(compiles, to!(typeof(arg))(args[i])))
          // note that to is from the stdlib again: std.conv. It converts
          // a thing from one type to another. Here, I ask it to convert our
          // string (args is the runtime array of strings the user passed) to
          // whatever the type is that the method expects.
          //
          // Note that this might throw an exception if the string is wrong.
          // For example, passing "lol" to a method expecting an int will throw
          // an exception saying cannot convert string "lol" to int.
          arg = to!(typeof(arg))(args[i]);
          else
          // or if the conversion didn't compile at all, it will always throw.
          throw new Exception("method " ~ methodName ~ " not callable with this reflection code because of incompatible argument type");
          }

          // now that we have the arguments, time to tackle the return value.
          // the main special case here is a void return - that is not a value
          // and thus cannot be converted. So we do it separately.

          // Otherwise, though, inside we just call our callable from above with
          // the arguments from above and return the value converted to string!

          static if(is(ReturnType!callable == void)) {
          // it returned void, so call it and return null
          // because the language won't let us return void
          // directly as a string nor convert it easily.
          callable(arguments);
          return null;
          } else {
          // it returned something else, just call the function
          // and convert it to a string
          return to!string(callable(arguments));
          }
          }
          } break method_switch;
          }
          default:
          throw new Exception("no such method " ~ methodName);
          }

          assert(0); // not reached
          }
          }

          // and let's call them with some strings. You could also get these strings from
          // the user (just btw remember to .strip them if they come from readln, otherwise
          // the trailing newline character will cause a method not found exception.)
          void main() {
          auto obj = new MyClass();
          writeln(obj.call("myMethod", ));
          writeln(obj.call("anotherMethod", ["5"]));
          }


          It might help to copy/paste that code out of the website and read the comments in your regular editor, since Stack Overflow will often make you scroll and that is hard. I show the basic ideas in the comments.



          Once you write that reflection bridge function once though and make it work somehow that you are happy with it... you can add as many methods as you want and it will work!



          In fact, you can even make the call method there part of an interface, and the definition of the body part of a mixin template (see https://dlang.org/spec/template-mixin.html ) and pop it into any of your classes.



          class MyNewClass : Reflectable {
          mixin CallImplementation;
          }

          // it will now work there!


          The interface lets you refer to it from base classes (same as Java, for the most part), and the mixin template lets you copy that reflection provider into each child class, so it gives all methods even on child classes. Java would do that for you automatically, but in D you do need to add that mixin line to each one. Not too much of a hassle, but something to consider. (It actually is possible for D to do it automatically too.. but it requires hacking the core runtime library, so it is a fairly advanced topic and only useful in special situations (since you must use that hacked library project-wide). So probably not useful to you, just hinting it is there.)



          With the interface btw, you can also add a static constructor to your classes to register them in some runtime associative array or switch or whatever of class names to factory functions, and create them from strings too. No particularly special code to realize that, it is the same kind of pattern you have probably seen before, but if you need new class objects from strings instead of just editing existing objects, that's how I'd get started.



          I'll leave those details for you to play with though, lemme know if anything here makes no sense.






          share|improve this answer



















          • 1





            BTW I also talked about this and more similar stuff in the reflection chapter of my book: packtpub.com/application-development/d-cookbook that used to be the free sample chapter, but it looks like they changed that... still, you might be able to get more out of that if this answer doesn't get you far enough for your needs.

            – Adam D. Ruppe
            Nov 24 '18 at 21:39











          • Hey this could be a silly question, but could you call the constructor and set stuff with it using your version of reflection ? Like : auto obj = new MyClass(); writeln(obj.call("MyClass", ["attribute1","attribute2","attribute3"]));

            – timi95
            Nov 25 '18 at 17:03






          • 1





            You could, but it won't automatically cover constructors like that. You'd have to add them to the switch yourself.

            – Adam D. Ruppe
            Nov 25 '18 at 20:49



















          1














          The D programming language has support for compile-time reflection, but it does not support run-time reflection (like Java for an example). For more details on the compile-time reflection see Adam's answer.



          10+ years ago Thomas Kühne wrote a brilliant package called FlectioneD ( http://dsource.org/projects/flectioned ) that is still a good reference on this topic...






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53462128%2fdoes-d-have-reflection%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            Yes, D has reflection, but no, it is not like Java.



            D's reflection comes in the form of compile time building blocks, rather than runtime methods. Of course, you can create the runtime methods yourself, but it won't just work out of the box with everything.



            I actually just wrote a thing today that reflection loops over a method to show its properties and let you edit it: https://twitter.com/adamdruppe/status/1066390612516179968 It is not done yet but I'll link so you can see some of it in action: https://github.com/adamdruppe/arsd/commit/5411dd9844869909466f2091391abe091b529bf8#diff-7a88942576365ca3d7f389b766344477R6587



            Anyway, the way I do it is to create methods out of simple loops using the reflection info. The language provides two facilities, __traits, and the is expression to do this:



            https://dlang.org/spec/traits.html



            https://dlang.org/spec/expression.html#IsExpression



            And the standard library wraps and extends with the std.traits module



            http://dpldocs.info/experimental-docs/std.traits.html



            (or if you prefer the official website of basically the same docs, just imo harder to read/navigate: https://dlang.org/phobos/std_traits.html )



            You can combine this with other code generation techniques like template mixins and traditional things like interfaces and constructors to create the runtime stuff.



            But for a simple case, try something like this:



            import std.stdio;
            import std.conv;
            import std.traits;

            class MyClass {
            void myMethod() {}
            int anotherMethod(int a) { return a; }

            // this is the runtime bridge function. The trick here is to do
            // a switch, just like your example, but the innards are auto-generated
            // from the compile time reflection.
            string call(string methodName, string args) {
            // it starts as a plain switch...
            method_switch: switch(methodName) {
            // but inside, we use a static foreach - a compile-time loop -
            // over the __traits(allMembers) magic, which gives a list of all member names
            static foreach(inspecting; __traits(allMembers, typeof(this))) {
            case inspecting: { // you can create switch cases inside these static loops
            // for this example, I only want to use callable methods, so this
            // static if - a compile time if statement - will filter out anything else.
            //
            // It is possible to do more, like plain data members, child classes, and more,
            // but that will add a lot more code. Same basic ideas with each of them though.
            static if(isCallable!(__traits(getMember, this, inspecting))) {
            // after we confirm it is callable, we can get a delegate of it
            // (same as normally doing `&member.method`) to call later.
            auto callable = &__traits(getMember, this, inspecting);

            // next is building the argument list. Parameters comes from the std.traits
            // module in the standard library and gives an object representing the function's
            // parameters. We can loop over these and set them!
            Parameters!callable arguments;
            foreach(i, ref arg; arguments) { // ref loop cuz we setting the arg members..
            // so for the runtime bridge here, I took everything as strings and
            // want to convert them to the actual method arguments. In many cases,
            // that automatic conversion will not be possible. The next bit of magic,
            // __traits(compiles), will take some code and return true if it successfully
            // compiles. Using the static if block, I can turn what would be compile time
            // errors into a runtime exception instead.
            static if(__traits(compiles, to!(typeof(arg))(args[i])))
            // note that to is from the stdlib again: std.conv. It converts
            // a thing from one type to another. Here, I ask it to convert our
            // string (args is the runtime array of strings the user passed) to
            // whatever the type is that the method expects.
            //
            // Note that this might throw an exception if the string is wrong.
            // For example, passing "lol" to a method expecting an int will throw
            // an exception saying cannot convert string "lol" to int.
            arg = to!(typeof(arg))(args[i]);
            else
            // or if the conversion didn't compile at all, it will always throw.
            throw new Exception("method " ~ methodName ~ " not callable with this reflection code because of incompatible argument type");
            }

            // now that we have the arguments, time to tackle the return value.
            // the main special case here is a void return - that is not a value
            // and thus cannot be converted. So we do it separately.

            // Otherwise, though, inside we just call our callable from above with
            // the arguments from above and return the value converted to string!

            static if(is(ReturnType!callable == void)) {
            // it returned void, so call it and return null
            // because the language won't let us return void
            // directly as a string nor convert it easily.
            callable(arguments);
            return null;
            } else {
            // it returned something else, just call the function
            // and convert it to a string
            return to!string(callable(arguments));
            }
            }
            } break method_switch;
            }
            default:
            throw new Exception("no such method " ~ methodName);
            }

            assert(0); // not reached
            }
            }

            // and let's call them with some strings. You could also get these strings from
            // the user (just btw remember to .strip them if they come from readln, otherwise
            // the trailing newline character will cause a method not found exception.)
            void main() {
            auto obj = new MyClass();
            writeln(obj.call("myMethod", ));
            writeln(obj.call("anotherMethod", ["5"]));
            }


            It might help to copy/paste that code out of the website and read the comments in your regular editor, since Stack Overflow will often make you scroll and that is hard. I show the basic ideas in the comments.



            Once you write that reflection bridge function once though and make it work somehow that you are happy with it... you can add as many methods as you want and it will work!



            In fact, you can even make the call method there part of an interface, and the definition of the body part of a mixin template (see https://dlang.org/spec/template-mixin.html ) and pop it into any of your classes.



            class MyNewClass : Reflectable {
            mixin CallImplementation;
            }

            // it will now work there!


            The interface lets you refer to it from base classes (same as Java, for the most part), and the mixin template lets you copy that reflection provider into each child class, so it gives all methods even on child classes. Java would do that for you automatically, but in D you do need to add that mixin line to each one. Not too much of a hassle, but something to consider. (It actually is possible for D to do it automatically too.. but it requires hacking the core runtime library, so it is a fairly advanced topic and only useful in special situations (since you must use that hacked library project-wide). So probably not useful to you, just hinting it is there.)



            With the interface btw, you can also add a static constructor to your classes to register them in some runtime associative array or switch or whatever of class names to factory functions, and create them from strings too. No particularly special code to realize that, it is the same kind of pattern you have probably seen before, but if you need new class objects from strings instead of just editing existing objects, that's how I'd get started.



            I'll leave those details for you to play with though, lemme know if anything here makes no sense.






            share|improve this answer



















            • 1





              BTW I also talked about this and more similar stuff in the reflection chapter of my book: packtpub.com/application-development/d-cookbook that used to be the free sample chapter, but it looks like they changed that... still, you might be able to get more out of that if this answer doesn't get you far enough for your needs.

              – Adam D. Ruppe
              Nov 24 '18 at 21:39











            • Hey this could be a silly question, but could you call the constructor and set stuff with it using your version of reflection ? Like : auto obj = new MyClass(); writeln(obj.call("MyClass", ["attribute1","attribute2","attribute3"]));

              – timi95
              Nov 25 '18 at 17:03






            • 1





              You could, but it won't automatically cover constructors like that. You'd have to add them to the switch yourself.

              – Adam D. Ruppe
              Nov 25 '18 at 20:49
















            1














            Yes, D has reflection, but no, it is not like Java.



            D's reflection comes in the form of compile time building blocks, rather than runtime methods. Of course, you can create the runtime methods yourself, but it won't just work out of the box with everything.



            I actually just wrote a thing today that reflection loops over a method to show its properties and let you edit it: https://twitter.com/adamdruppe/status/1066390612516179968 It is not done yet but I'll link so you can see some of it in action: https://github.com/adamdruppe/arsd/commit/5411dd9844869909466f2091391abe091b529bf8#diff-7a88942576365ca3d7f389b766344477R6587



            Anyway, the way I do it is to create methods out of simple loops using the reflection info. The language provides two facilities, __traits, and the is expression to do this:



            https://dlang.org/spec/traits.html



            https://dlang.org/spec/expression.html#IsExpression



            And the standard library wraps and extends with the std.traits module



            http://dpldocs.info/experimental-docs/std.traits.html



            (or if you prefer the official website of basically the same docs, just imo harder to read/navigate: https://dlang.org/phobos/std_traits.html )



            You can combine this with other code generation techniques like template mixins and traditional things like interfaces and constructors to create the runtime stuff.



            But for a simple case, try something like this:



            import std.stdio;
            import std.conv;
            import std.traits;

            class MyClass {
            void myMethod() {}
            int anotherMethod(int a) { return a; }

            // this is the runtime bridge function. The trick here is to do
            // a switch, just like your example, but the innards are auto-generated
            // from the compile time reflection.
            string call(string methodName, string args) {
            // it starts as a plain switch...
            method_switch: switch(methodName) {
            // but inside, we use a static foreach - a compile-time loop -
            // over the __traits(allMembers) magic, which gives a list of all member names
            static foreach(inspecting; __traits(allMembers, typeof(this))) {
            case inspecting: { // you can create switch cases inside these static loops
            // for this example, I only want to use callable methods, so this
            // static if - a compile time if statement - will filter out anything else.
            //
            // It is possible to do more, like plain data members, child classes, and more,
            // but that will add a lot more code. Same basic ideas with each of them though.
            static if(isCallable!(__traits(getMember, this, inspecting))) {
            // after we confirm it is callable, we can get a delegate of it
            // (same as normally doing `&member.method`) to call later.
            auto callable = &__traits(getMember, this, inspecting);

            // next is building the argument list. Parameters comes from the std.traits
            // module in the standard library and gives an object representing the function's
            // parameters. We can loop over these and set them!
            Parameters!callable arguments;
            foreach(i, ref arg; arguments) { // ref loop cuz we setting the arg members..
            // so for the runtime bridge here, I took everything as strings and
            // want to convert them to the actual method arguments. In many cases,
            // that automatic conversion will not be possible. The next bit of magic,
            // __traits(compiles), will take some code and return true if it successfully
            // compiles. Using the static if block, I can turn what would be compile time
            // errors into a runtime exception instead.
            static if(__traits(compiles, to!(typeof(arg))(args[i])))
            // note that to is from the stdlib again: std.conv. It converts
            // a thing from one type to another. Here, I ask it to convert our
            // string (args is the runtime array of strings the user passed) to
            // whatever the type is that the method expects.
            //
            // Note that this might throw an exception if the string is wrong.
            // For example, passing "lol" to a method expecting an int will throw
            // an exception saying cannot convert string "lol" to int.
            arg = to!(typeof(arg))(args[i]);
            else
            // or if the conversion didn't compile at all, it will always throw.
            throw new Exception("method " ~ methodName ~ " not callable with this reflection code because of incompatible argument type");
            }

            // now that we have the arguments, time to tackle the return value.
            // the main special case here is a void return - that is not a value
            // and thus cannot be converted. So we do it separately.

            // Otherwise, though, inside we just call our callable from above with
            // the arguments from above and return the value converted to string!

            static if(is(ReturnType!callable == void)) {
            // it returned void, so call it and return null
            // because the language won't let us return void
            // directly as a string nor convert it easily.
            callable(arguments);
            return null;
            } else {
            // it returned something else, just call the function
            // and convert it to a string
            return to!string(callable(arguments));
            }
            }
            } break method_switch;
            }
            default:
            throw new Exception("no such method " ~ methodName);
            }

            assert(0); // not reached
            }
            }

            // and let's call them with some strings. You could also get these strings from
            // the user (just btw remember to .strip them if they come from readln, otherwise
            // the trailing newline character will cause a method not found exception.)
            void main() {
            auto obj = new MyClass();
            writeln(obj.call("myMethod", ));
            writeln(obj.call("anotherMethod", ["5"]));
            }


            It might help to copy/paste that code out of the website and read the comments in your regular editor, since Stack Overflow will often make you scroll and that is hard. I show the basic ideas in the comments.



            Once you write that reflection bridge function once though and make it work somehow that you are happy with it... you can add as many methods as you want and it will work!



            In fact, you can even make the call method there part of an interface, and the definition of the body part of a mixin template (see https://dlang.org/spec/template-mixin.html ) and pop it into any of your classes.



            class MyNewClass : Reflectable {
            mixin CallImplementation;
            }

            // it will now work there!


            The interface lets you refer to it from base classes (same as Java, for the most part), and the mixin template lets you copy that reflection provider into each child class, so it gives all methods even on child classes. Java would do that for you automatically, but in D you do need to add that mixin line to each one. Not too much of a hassle, but something to consider. (It actually is possible for D to do it automatically too.. but it requires hacking the core runtime library, so it is a fairly advanced topic and only useful in special situations (since you must use that hacked library project-wide). So probably not useful to you, just hinting it is there.)



            With the interface btw, you can also add a static constructor to your classes to register them in some runtime associative array or switch or whatever of class names to factory functions, and create them from strings too. No particularly special code to realize that, it is the same kind of pattern you have probably seen before, but if you need new class objects from strings instead of just editing existing objects, that's how I'd get started.



            I'll leave those details for you to play with though, lemme know if anything here makes no sense.






            share|improve this answer



















            • 1





              BTW I also talked about this and more similar stuff in the reflection chapter of my book: packtpub.com/application-development/d-cookbook that used to be the free sample chapter, but it looks like they changed that... still, you might be able to get more out of that if this answer doesn't get you far enough for your needs.

              – Adam D. Ruppe
              Nov 24 '18 at 21:39











            • Hey this could be a silly question, but could you call the constructor and set stuff with it using your version of reflection ? Like : auto obj = new MyClass(); writeln(obj.call("MyClass", ["attribute1","attribute2","attribute3"]));

              – timi95
              Nov 25 '18 at 17:03






            • 1





              You could, but it won't automatically cover constructors like that. You'd have to add them to the switch yourself.

              – Adam D. Ruppe
              Nov 25 '18 at 20:49














            1












            1








            1







            Yes, D has reflection, but no, it is not like Java.



            D's reflection comes in the form of compile time building blocks, rather than runtime methods. Of course, you can create the runtime methods yourself, but it won't just work out of the box with everything.



            I actually just wrote a thing today that reflection loops over a method to show its properties and let you edit it: https://twitter.com/adamdruppe/status/1066390612516179968 It is not done yet but I'll link so you can see some of it in action: https://github.com/adamdruppe/arsd/commit/5411dd9844869909466f2091391abe091b529bf8#diff-7a88942576365ca3d7f389b766344477R6587



            Anyway, the way I do it is to create methods out of simple loops using the reflection info. The language provides two facilities, __traits, and the is expression to do this:



            https://dlang.org/spec/traits.html



            https://dlang.org/spec/expression.html#IsExpression



            And the standard library wraps and extends with the std.traits module



            http://dpldocs.info/experimental-docs/std.traits.html



            (or if you prefer the official website of basically the same docs, just imo harder to read/navigate: https://dlang.org/phobos/std_traits.html )



            You can combine this with other code generation techniques like template mixins and traditional things like interfaces and constructors to create the runtime stuff.



            But for a simple case, try something like this:



            import std.stdio;
            import std.conv;
            import std.traits;

            class MyClass {
            void myMethod() {}
            int anotherMethod(int a) { return a; }

            // this is the runtime bridge function. The trick here is to do
            // a switch, just like your example, but the innards are auto-generated
            // from the compile time reflection.
            string call(string methodName, string args) {
            // it starts as a plain switch...
            method_switch: switch(methodName) {
            // but inside, we use a static foreach - a compile-time loop -
            // over the __traits(allMembers) magic, which gives a list of all member names
            static foreach(inspecting; __traits(allMembers, typeof(this))) {
            case inspecting: { // you can create switch cases inside these static loops
            // for this example, I only want to use callable methods, so this
            // static if - a compile time if statement - will filter out anything else.
            //
            // It is possible to do more, like plain data members, child classes, and more,
            // but that will add a lot more code. Same basic ideas with each of them though.
            static if(isCallable!(__traits(getMember, this, inspecting))) {
            // after we confirm it is callable, we can get a delegate of it
            // (same as normally doing `&member.method`) to call later.
            auto callable = &__traits(getMember, this, inspecting);

            // next is building the argument list. Parameters comes from the std.traits
            // module in the standard library and gives an object representing the function's
            // parameters. We can loop over these and set them!
            Parameters!callable arguments;
            foreach(i, ref arg; arguments) { // ref loop cuz we setting the arg members..
            // so for the runtime bridge here, I took everything as strings and
            // want to convert them to the actual method arguments. In many cases,
            // that automatic conversion will not be possible. The next bit of magic,
            // __traits(compiles), will take some code and return true if it successfully
            // compiles. Using the static if block, I can turn what would be compile time
            // errors into a runtime exception instead.
            static if(__traits(compiles, to!(typeof(arg))(args[i])))
            // note that to is from the stdlib again: std.conv. It converts
            // a thing from one type to another. Here, I ask it to convert our
            // string (args is the runtime array of strings the user passed) to
            // whatever the type is that the method expects.
            //
            // Note that this might throw an exception if the string is wrong.
            // For example, passing "lol" to a method expecting an int will throw
            // an exception saying cannot convert string "lol" to int.
            arg = to!(typeof(arg))(args[i]);
            else
            // or if the conversion didn't compile at all, it will always throw.
            throw new Exception("method " ~ methodName ~ " not callable with this reflection code because of incompatible argument type");
            }

            // now that we have the arguments, time to tackle the return value.
            // the main special case here is a void return - that is not a value
            // and thus cannot be converted. So we do it separately.

            // Otherwise, though, inside we just call our callable from above with
            // the arguments from above and return the value converted to string!

            static if(is(ReturnType!callable == void)) {
            // it returned void, so call it and return null
            // because the language won't let us return void
            // directly as a string nor convert it easily.
            callable(arguments);
            return null;
            } else {
            // it returned something else, just call the function
            // and convert it to a string
            return to!string(callable(arguments));
            }
            }
            } break method_switch;
            }
            default:
            throw new Exception("no such method " ~ methodName);
            }

            assert(0); // not reached
            }
            }

            // and let's call them with some strings. You could also get these strings from
            // the user (just btw remember to .strip them if they come from readln, otherwise
            // the trailing newline character will cause a method not found exception.)
            void main() {
            auto obj = new MyClass();
            writeln(obj.call("myMethod", ));
            writeln(obj.call("anotherMethod", ["5"]));
            }


            It might help to copy/paste that code out of the website and read the comments in your regular editor, since Stack Overflow will often make you scroll and that is hard. I show the basic ideas in the comments.



            Once you write that reflection bridge function once though and make it work somehow that you are happy with it... you can add as many methods as you want and it will work!



            In fact, you can even make the call method there part of an interface, and the definition of the body part of a mixin template (see https://dlang.org/spec/template-mixin.html ) and pop it into any of your classes.



            class MyNewClass : Reflectable {
            mixin CallImplementation;
            }

            // it will now work there!


            The interface lets you refer to it from base classes (same as Java, for the most part), and the mixin template lets you copy that reflection provider into each child class, so it gives all methods even on child classes. Java would do that for you automatically, but in D you do need to add that mixin line to each one. Not too much of a hassle, but something to consider. (It actually is possible for D to do it automatically too.. but it requires hacking the core runtime library, so it is a fairly advanced topic and only useful in special situations (since you must use that hacked library project-wide). So probably not useful to you, just hinting it is there.)



            With the interface btw, you can also add a static constructor to your classes to register them in some runtime associative array or switch or whatever of class names to factory functions, and create them from strings too. No particularly special code to realize that, it is the same kind of pattern you have probably seen before, but if you need new class objects from strings instead of just editing existing objects, that's how I'd get started.



            I'll leave those details for you to play with though, lemme know if anything here makes no sense.






            share|improve this answer













            Yes, D has reflection, but no, it is not like Java.



            D's reflection comes in the form of compile time building blocks, rather than runtime methods. Of course, you can create the runtime methods yourself, but it won't just work out of the box with everything.



            I actually just wrote a thing today that reflection loops over a method to show its properties and let you edit it: https://twitter.com/adamdruppe/status/1066390612516179968 It is not done yet but I'll link so you can see some of it in action: https://github.com/adamdruppe/arsd/commit/5411dd9844869909466f2091391abe091b529bf8#diff-7a88942576365ca3d7f389b766344477R6587



            Anyway, the way I do it is to create methods out of simple loops using the reflection info. The language provides two facilities, __traits, and the is expression to do this:



            https://dlang.org/spec/traits.html



            https://dlang.org/spec/expression.html#IsExpression



            And the standard library wraps and extends with the std.traits module



            http://dpldocs.info/experimental-docs/std.traits.html



            (or if you prefer the official website of basically the same docs, just imo harder to read/navigate: https://dlang.org/phobos/std_traits.html )



            You can combine this with other code generation techniques like template mixins and traditional things like interfaces and constructors to create the runtime stuff.



            But for a simple case, try something like this:



            import std.stdio;
            import std.conv;
            import std.traits;

            class MyClass {
            void myMethod() {}
            int anotherMethod(int a) { return a; }

            // this is the runtime bridge function. The trick here is to do
            // a switch, just like your example, but the innards are auto-generated
            // from the compile time reflection.
            string call(string methodName, string args) {
            // it starts as a plain switch...
            method_switch: switch(methodName) {
            // but inside, we use a static foreach - a compile-time loop -
            // over the __traits(allMembers) magic, which gives a list of all member names
            static foreach(inspecting; __traits(allMembers, typeof(this))) {
            case inspecting: { // you can create switch cases inside these static loops
            // for this example, I only want to use callable methods, so this
            // static if - a compile time if statement - will filter out anything else.
            //
            // It is possible to do more, like plain data members, child classes, and more,
            // but that will add a lot more code. Same basic ideas with each of them though.
            static if(isCallable!(__traits(getMember, this, inspecting))) {
            // after we confirm it is callable, we can get a delegate of it
            // (same as normally doing `&member.method`) to call later.
            auto callable = &__traits(getMember, this, inspecting);

            // next is building the argument list. Parameters comes from the std.traits
            // module in the standard library and gives an object representing the function's
            // parameters. We can loop over these and set them!
            Parameters!callable arguments;
            foreach(i, ref arg; arguments) { // ref loop cuz we setting the arg members..
            // so for the runtime bridge here, I took everything as strings and
            // want to convert them to the actual method arguments. In many cases,
            // that automatic conversion will not be possible. The next bit of magic,
            // __traits(compiles), will take some code and return true if it successfully
            // compiles. Using the static if block, I can turn what would be compile time
            // errors into a runtime exception instead.
            static if(__traits(compiles, to!(typeof(arg))(args[i])))
            // note that to is from the stdlib again: std.conv. It converts
            // a thing from one type to another. Here, I ask it to convert our
            // string (args is the runtime array of strings the user passed) to
            // whatever the type is that the method expects.
            //
            // Note that this might throw an exception if the string is wrong.
            // For example, passing "lol" to a method expecting an int will throw
            // an exception saying cannot convert string "lol" to int.
            arg = to!(typeof(arg))(args[i]);
            else
            // or if the conversion didn't compile at all, it will always throw.
            throw new Exception("method " ~ methodName ~ " not callable with this reflection code because of incompatible argument type");
            }

            // now that we have the arguments, time to tackle the return value.
            // the main special case here is a void return - that is not a value
            // and thus cannot be converted. So we do it separately.

            // Otherwise, though, inside we just call our callable from above with
            // the arguments from above and return the value converted to string!

            static if(is(ReturnType!callable == void)) {
            // it returned void, so call it and return null
            // because the language won't let us return void
            // directly as a string nor convert it easily.
            callable(arguments);
            return null;
            } else {
            // it returned something else, just call the function
            // and convert it to a string
            return to!string(callable(arguments));
            }
            }
            } break method_switch;
            }
            default:
            throw new Exception("no such method " ~ methodName);
            }

            assert(0); // not reached
            }
            }

            // and let's call them with some strings. You could also get these strings from
            // the user (just btw remember to .strip them if they come from readln, otherwise
            // the trailing newline character will cause a method not found exception.)
            void main() {
            auto obj = new MyClass();
            writeln(obj.call("myMethod", ));
            writeln(obj.call("anotherMethod", ["5"]));
            }


            It might help to copy/paste that code out of the website and read the comments in your regular editor, since Stack Overflow will often make you scroll and that is hard. I show the basic ideas in the comments.



            Once you write that reflection bridge function once though and make it work somehow that you are happy with it... you can add as many methods as you want and it will work!



            In fact, you can even make the call method there part of an interface, and the definition of the body part of a mixin template (see https://dlang.org/spec/template-mixin.html ) and pop it into any of your classes.



            class MyNewClass : Reflectable {
            mixin CallImplementation;
            }

            // it will now work there!


            The interface lets you refer to it from base classes (same as Java, for the most part), and the mixin template lets you copy that reflection provider into each child class, so it gives all methods even on child classes. Java would do that for you automatically, but in D you do need to add that mixin line to each one. Not too much of a hassle, but something to consider. (It actually is possible for D to do it automatically too.. but it requires hacking the core runtime library, so it is a fairly advanced topic and only useful in special situations (since you must use that hacked library project-wide). So probably not useful to you, just hinting it is there.)



            With the interface btw, you can also add a static constructor to your classes to register them in some runtime associative array or switch or whatever of class names to factory functions, and create them from strings too. No particularly special code to realize that, it is the same kind of pattern you have probably seen before, but if you need new class objects from strings instead of just editing existing objects, that's how I'd get started.



            I'll leave those details for you to play with though, lemme know if anything here makes no sense.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 24 '18 at 21:38









            Adam D. RuppeAdam D. Ruppe

            22.7k43353




            22.7k43353








            • 1





              BTW I also talked about this and more similar stuff in the reflection chapter of my book: packtpub.com/application-development/d-cookbook that used to be the free sample chapter, but it looks like they changed that... still, you might be able to get more out of that if this answer doesn't get you far enough for your needs.

              – Adam D. Ruppe
              Nov 24 '18 at 21:39











            • Hey this could be a silly question, but could you call the constructor and set stuff with it using your version of reflection ? Like : auto obj = new MyClass(); writeln(obj.call("MyClass", ["attribute1","attribute2","attribute3"]));

              – timi95
              Nov 25 '18 at 17:03






            • 1





              You could, but it won't automatically cover constructors like that. You'd have to add them to the switch yourself.

              – Adam D. Ruppe
              Nov 25 '18 at 20:49














            • 1





              BTW I also talked about this and more similar stuff in the reflection chapter of my book: packtpub.com/application-development/d-cookbook that used to be the free sample chapter, but it looks like they changed that... still, you might be able to get more out of that if this answer doesn't get you far enough for your needs.

              – Adam D. Ruppe
              Nov 24 '18 at 21:39











            • Hey this could be a silly question, but could you call the constructor and set stuff with it using your version of reflection ? Like : auto obj = new MyClass(); writeln(obj.call("MyClass", ["attribute1","attribute2","attribute3"]));

              – timi95
              Nov 25 '18 at 17:03






            • 1





              You could, but it won't automatically cover constructors like that. You'd have to add them to the switch yourself.

              – Adam D. Ruppe
              Nov 25 '18 at 20:49








            1




            1





            BTW I also talked about this and more similar stuff in the reflection chapter of my book: packtpub.com/application-development/d-cookbook that used to be the free sample chapter, but it looks like they changed that... still, you might be able to get more out of that if this answer doesn't get you far enough for your needs.

            – Adam D. Ruppe
            Nov 24 '18 at 21:39





            BTW I also talked about this and more similar stuff in the reflection chapter of my book: packtpub.com/application-development/d-cookbook that used to be the free sample chapter, but it looks like they changed that... still, you might be able to get more out of that if this answer doesn't get you far enough for your needs.

            – Adam D. Ruppe
            Nov 24 '18 at 21:39













            Hey this could be a silly question, but could you call the constructor and set stuff with it using your version of reflection ? Like : auto obj = new MyClass(); writeln(obj.call("MyClass", ["attribute1","attribute2","attribute3"]));

            – timi95
            Nov 25 '18 at 17:03





            Hey this could be a silly question, but could you call the constructor and set stuff with it using your version of reflection ? Like : auto obj = new MyClass(); writeln(obj.call("MyClass", ["attribute1","attribute2","attribute3"]));

            – timi95
            Nov 25 '18 at 17:03




            1




            1





            You could, but it won't automatically cover constructors like that. You'd have to add them to the switch yourself.

            – Adam D. Ruppe
            Nov 25 '18 at 20:49





            You could, but it won't automatically cover constructors like that. You'd have to add them to the switch yourself.

            – Adam D. Ruppe
            Nov 25 '18 at 20:49













            1














            The D programming language has support for compile-time reflection, but it does not support run-time reflection (like Java for an example). For more details on the compile-time reflection see Adam's answer.



            10+ years ago Thomas Kühne wrote a brilliant package called FlectioneD ( http://dsource.org/projects/flectioned ) that is still a good reference on this topic...






            share|improve this answer




























              1














              The D programming language has support for compile-time reflection, but it does not support run-time reflection (like Java for an example). For more details on the compile-time reflection see Adam's answer.



              10+ years ago Thomas Kühne wrote a brilliant package called FlectioneD ( http://dsource.org/projects/flectioned ) that is still a good reference on this topic...






              share|improve this answer


























                1












                1








                1







                The D programming language has support for compile-time reflection, but it does not support run-time reflection (like Java for an example). For more details on the compile-time reflection see Adam's answer.



                10+ years ago Thomas Kühne wrote a brilliant package called FlectioneD ( http://dsource.org/projects/flectioned ) that is still a good reference on this topic...






                share|improve this answer













                The D programming language has support for compile-time reflection, but it does not support run-time reflection (like Java for an example). For more details on the compile-time reflection see Adam's answer.



                10+ years ago Thomas Kühne wrote a brilliant package called FlectioneD ( http://dsource.org/projects/flectioned ) that is still a good reference on this topic...







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 26 '18 at 14:54









                DejanLekicDejanLekic

                10.7k32957




                10.7k32957






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53462128%2fdoes-d-have-reflection%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

                    Calculate evaluation metrics using cross_val_predict sklearn

                    Insert data from modal to MySQL (multiple modal on website)