Calling a Function From a String With the Function's Name in Ruby












141















How can I do what they are talking about here, but in Ruby?



How would you do the function on an object? and how would you do a global function (see jetxee's answer on the post mentioned)?



EXAMPLE CODE:



event_name = "load"

def load()
puts "load() function was executed."
end

def row_changed()
puts "row_changed() function was executed."
end

#something here to see that event_name = "load" and run load()


UPDATE:
How do you get to the global methods? or my global functions?



I tried this additional line



puts methods


and load and row_change where not listed.










share|improve this question





























    141















    How can I do what they are talking about here, but in Ruby?



    How would you do the function on an object? and how would you do a global function (see jetxee's answer on the post mentioned)?



    EXAMPLE CODE:



    event_name = "load"

    def load()
    puts "load() function was executed."
    end

    def row_changed()
    puts "row_changed() function was executed."
    end

    #something here to see that event_name = "load" and run load()


    UPDATE:
    How do you get to the global methods? or my global functions?



    I tried this additional line



    puts methods


    and load and row_change where not listed.










    share|improve this question



























      141












      141








      141


      21






      How can I do what they are talking about here, but in Ruby?



      How would you do the function on an object? and how would you do a global function (see jetxee's answer on the post mentioned)?



      EXAMPLE CODE:



      event_name = "load"

      def load()
      puts "load() function was executed."
      end

      def row_changed()
      puts "row_changed() function was executed."
      end

      #something here to see that event_name = "load" and run load()


      UPDATE:
      How do you get to the global methods? or my global functions?



      I tried this additional line



      puts methods


      and load and row_change where not listed.










      share|improve this question
















      How can I do what they are talking about here, but in Ruby?



      How would you do the function on an object? and how would you do a global function (see jetxee's answer on the post mentioned)?



      EXAMPLE CODE:



      event_name = "load"

      def load()
      puts "load() function was executed."
      end

      def row_changed()
      puts "row_changed() function was executed."
      end

      #something here to see that event_name = "load" and run load()


      UPDATE:
      How do you get to the global methods? or my global functions?



      I tried this additional line



      puts methods


      and load and row_change where not listed.







      ruby function metaprogramming






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited May 23 '17 at 12:03









      Community

      11




      11










      asked Sep 10 '09 at 20:10









      BuddyJoeBuddyJoe

      28.6k91263437




      28.6k91263437
























          4 Answers
          4






          active

          oldest

          votes


















          206














          To call functions directly on an object



          a = [2, 2, 3]
          a.send("length")
          # or
          a.public_send("length")


          which returns 3 as expected



          or for a module function



          FileUtils.send('pwd')
          # or
          FileUtils.public_send(:pwd)


          and a locally defined method



          def load()
          puts "load() function was executed."
          end

          send('load')
          # or
          public_send('load')


          Documentation:




          • Object#public_send

          • Object#send






          share|improve this answer





















          • 3





            +1 That works. This may be a dumb follow up ... but how come I can't find the word send in the Ruby source at - C:rubylibruby1.8fileutils.rb? Thought I would find the send function in there.

            – BuddyJoe
            Sep 10 '09 at 21:15






          • 1





            I was curious to what it was doing under the hood.

            – BuddyJoe
            Sep 10 '09 at 21:15











          • It's defined on object - ruby-doc.org/core/classes/Object.html#M000332 I picked a random function for interest value.

            – Colin Gravill
            Sep 10 '09 at 21:44






          • 1





            Interesting because before I read your answer twice, and fully grok'd it I ran the FileUtils.send("load") and it ran my function. so if I understand this correctly by creating functions in "global" am I adding the methods onto the root object? or not?

            – BuddyJoe
            Sep 10 '09 at 21:50






          • 9





            Good on you for looking stuff up in the source! :)

            – Colin Gravill
            Sep 10 '09 at 21:50



















          31














          Use this:



          > a = "my_string"
          > meth = a.method("size")
          > meth.call() # call the size method
          => 9


          Simple, right?



          As for the global, I think the Ruby way would be to search it using the methods method.






          share|improve this answer



















          • 1





            +1. like this. Ruby has such great syntax. Love it.

            – BuddyJoe
            Sep 10 '09 at 20:40











          • meth = a.method? isn't this call the function already? what if the method returns something?

            – user1735921
            Nov 16 '15 at 7:07











          • FYI for when the method doesn't exist: "my_string".method('blah') #=> NameError: undefined method blah' for class String'

            – Joshua Pinter
            Dec 30 '17 at 22:31



















          31














          Three Ways: send / call / eval - and their Benchmarks



          Typical invocation (for reference):



          s= "hi man"
          s.length #=> 6


          Using send



          s.send(:length) #=> 6


          Using call



          method_object = s.method(:length) 
          p method_object.call #=> 6


          Using eval



          eval "s.length" #=> 6


           



          Benchmarks



          require "benchmark" 
          test = "hi man"
          m = test.method(:length)
          n = 100000
          Benchmark.bmbm {|x|
          x.report("call") { n.times { m.call } }
          x.report("send") { n.times { test.send(:length) } }
          x.report("eval") { n.times { eval "test.length" } }
          }



          ...as you can see, instantiating a method object is the fastest dynamic way in calling a method, also notice how slow using eval is.




          #######################################
          ##### The results
          #######################################
          #Rehearsal ----------------------------------------
          #call 0.050000 0.020000 0.070000 ( 0.077915)
          #send 0.080000 0.000000 0.080000 ( 0.086071)
          #eval 0.360000 0.040000 0.400000 ( 0.405647)
          #------------------------------- total: 0.550000sec

          # user system total real
          #call 0.050000 0.020000 0.070000 ( 0.072041)
          #send 0.070000 0.000000 0.070000 ( 0.077674)
          #eval 0.370000 0.020000 0.390000 ( 0.399442)


          Credit goes to this blog post which elaborates a bit more on the three methods and also shows how to check if the methods exist.






          share|improve this answer
























          • I was just finding this, and I noticed something that wasn't covered. What would I do if I wanted to do Class.send("classVariable") = 5? That throws an error. Is there any way around that? The same thing is true for using Class.method("classVariable").call() = 5

            – thesecretmaster
            Nov 20 '15 at 22:14













          • if you want to send some argument with send call use something like this ClassName.send("method_name", arg1, arg2)

            – Aleem
            Aug 30 '17 at 10:07













          • Shouldn't your benchmark for call include instantiating the method object (m.test.method(:length)) to accurately represent it's true time? When using call you're likely going to instantiate the method object every time.

            – Joshua Pinter
            Dec 30 '17 at 22:29











          • Blog post link is dead, btw.

            – Joshua Pinter
            Dec 30 '17 at 22:30



















          3














          Personally I would setup a hash to function references and then use the string as an index to the hash. You then call the function reference with it's parameters. This has the advantage of not allowing the wrong string to call something you don't want to call. The other way is to basically eval the string. Do not do this.



          PS don't be lazy and actually type out your whole question, instead of linking to something.






          share|improve this answer
























          • Sorry. I'll copy some of the wording and translate to make it Ruby specific. +1

            – BuddyJoe
            Sep 10 '09 at 20:37











          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%2f1407451%2fcalling-a-function-from-a-string-with-the-functions-name-in-ruby%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          4 Answers
          4






          active

          oldest

          votes








          4 Answers
          4






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          206














          To call functions directly on an object



          a = [2, 2, 3]
          a.send("length")
          # or
          a.public_send("length")


          which returns 3 as expected



          or for a module function



          FileUtils.send('pwd')
          # or
          FileUtils.public_send(:pwd)


          and a locally defined method



          def load()
          puts "load() function was executed."
          end

          send('load')
          # or
          public_send('load')


          Documentation:




          • Object#public_send

          • Object#send






          share|improve this answer





















          • 3





            +1 That works. This may be a dumb follow up ... but how come I can't find the word send in the Ruby source at - C:rubylibruby1.8fileutils.rb? Thought I would find the send function in there.

            – BuddyJoe
            Sep 10 '09 at 21:15






          • 1





            I was curious to what it was doing under the hood.

            – BuddyJoe
            Sep 10 '09 at 21:15











          • It's defined on object - ruby-doc.org/core/classes/Object.html#M000332 I picked a random function for interest value.

            – Colin Gravill
            Sep 10 '09 at 21:44






          • 1





            Interesting because before I read your answer twice, and fully grok'd it I ran the FileUtils.send("load") and it ran my function. so if I understand this correctly by creating functions in "global" am I adding the methods onto the root object? or not?

            – BuddyJoe
            Sep 10 '09 at 21:50






          • 9





            Good on you for looking stuff up in the source! :)

            – Colin Gravill
            Sep 10 '09 at 21:50
















          206














          To call functions directly on an object



          a = [2, 2, 3]
          a.send("length")
          # or
          a.public_send("length")


          which returns 3 as expected



          or for a module function



          FileUtils.send('pwd')
          # or
          FileUtils.public_send(:pwd)


          and a locally defined method



          def load()
          puts "load() function was executed."
          end

          send('load')
          # or
          public_send('load')


          Documentation:




          • Object#public_send

          • Object#send






          share|improve this answer





















          • 3





            +1 That works. This may be a dumb follow up ... but how come I can't find the word send in the Ruby source at - C:rubylibruby1.8fileutils.rb? Thought I would find the send function in there.

            – BuddyJoe
            Sep 10 '09 at 21:15






          • 1





            I was curious to what it was doing under the hood.

            – BuddyJoe
            Sep 10 '09 at 21:15











          • It's defined on object - ruby-doc.org/core/classes/Object.html#M000332 I picked a random function for interest value.

            – Colin Gravill
            Sep 10 '09 at 21:44






          • 1





            Interesting because before I read your answer twice, and fully grok'd it I ran the FileUtils.send("load") and it ran my function. so if I understand this correctly by creating functions in "global" am I adding the methods onto the root object? or not?

            – BuddyJoe
            Sep 10 '09 at 21:50






          • 9





            Good on you for looking stuff up in the source! :)

            – Colin Gravill
            Sep 10 '09 at 21:50














          206












          206








          206







          To call functions directly on an object



          a = [2, 2, 3]
          a.send("length")
          # or
          a.public_send("length")


          which returns 3 as expected



          or for a module function



          FileUtils.send('pwd')
          # or
          FileUtils.public_send(:pwd)


          and a locally defined method



          def load()
          puts "load() function was executed."
          end

          send('load')
          # or
          public_send('load')


          Documentation:




          • Object#public_send

          • Object#send






          share|improve this answer















          To call functions directly on an object



          a = [2, 2, 3]
          a.send("length")
          # or
          a.public_send("length")


          which returns 3 as expected



          or for a module function



          FileUtils.send('pwd')
          # or
          FileUtils.public_send(:pwd)


          and a locally defined method



          def load()
          puts "load() function was executed."
          end

          send('load')
          # or
          public_send('load')


          Documentation:




          • Object#public_send

          • Object#send







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 21 '18 at 21:35









          mu is too short

          352k58692667




          352k58692667










          answered Sep 10 '09 at 20:17









          Colin GravillColin Gravill

          3,50311715




          3,50311715








          • 3





            +1 That works. This may be a dumb follow up ... but how come I can't find the word send in the Ruby source at - C:rubylibruby1.8fileutils.rb? Thought I would find the send function in there.

            – BuddyJoe
            Sep 10 '09 at 21:15






          • 1





            I was curious to what it was doing under the hood.

            – BuddyJoe
            Sep 10 '09 at 21:15











          • It's defined on object - ruby-doc.org/core/classes/Object.html#M000332 I picked a random function for interest value.

            – Colin Gravill
            Sep 10 '09 at 21:44






          • 1





            Interesting because before I read your answer twice, and fully grok'd it I ran the FileUtils.send("load") and it ran my function. so if I understand this correctly by creating functions in "global" am I adding the methods onto the root object? or not?

            – BuddyJoe
            Sep 10 '09 at 21:50






          • 9





            Good on you for looking stuff up in the source! :)

            – Colin Gravill
            Sep 10 '09 at 21:50














          • 3





            +1 That works. This may be a dumb follow up ... but how come I can't find the word send in the Ruby source at - C:rubylibruby1.8fileutils.rb? Thought I would find the send function in there.

            – BuddyJoe
            Sep 10 '09 at 21:15






          • 1





            I was curious to what it was doing under the hood.

            – BuddyJoe
            Sep 10 '09 at 21:15











          • It's defined on object - ruby-doc.org/core/classes/Object.html#M000332 I picked a random function for interest value.

            – Colin Gravill
            Sep 10 '09 at 21:44






          • 1





            Interesting because before I read your answer twice, and fully grok'd it I ran the FileUtils.send("load") and it ran my function. so if I understand this correctly by creating functions in "global" am I adding the methods onto the root object? or not?

            – BuddyJoe
            Sep 10 '09 at 21:50






          • 9





            Good on you for looking stuff up in the source! :)

            – Colin Gravill
            Sep 10 '09 at 21:50








          3




          3





          +1 That works. This may be a dumb follow up ... but how come I can't find the word send in the Ruby source at - C:rubylibruby1.8fileutils.rb? Thought I would find the send function in there.

          – BuddyJoe
          Sep 10 '09 at 21:15





          +1 That works. This may be a dumb follow up ... but how come I can't find the word send in the Ruby source at - C:rubylibruby1.8fileutils.rb? Thought I would find the send function in there.

          – BuddyJoe
          Sep 10 '09 at 21:15




          1




          1





          I was curious to what it was doing under the hood.

          – BuddyJoe
          Sep 10 '09 at 21:15





          I was curious to what it was doing under the hood.

          – BuddyJoe
          Sep 10 '09 at 21:15













          It's defined on object - ruby-doc.org/core/classes/Object.html#M000332 I picked a random function for interest value.

          – Colin Gravill
          Sep 10 '09 at 21:44





          It's defined on object - ruby-doc.org/core/classes/Object.html#M000332 I picked a random function for interest value.

          – Colin Gravill
          Sep 10 '09 at 21:44




          1




          1





          Interesting because before I read your answer twice, and fully grok'd it I ran the FileUtils.send("load") and it ran my function. so if I understand this correctly by creating functions in "global" am I adding the methods onto the root object? or not?

          – BuddyJoe
          Sep 10 '09 at 21:50





          Interesting because before I read your answer twice, and fully grok'd it I ran the FileUtils.send("load") and it ran my function. so if I understand this correctly by creating functions in "global" am I adding the methods onto the root object? or not?

          – BuddyJoe
          Sep 10 '09 at 21:50




          9




          9





          Good on you for looking stuff up in the source! :)

          – Colin Gravill
          Sep 10 '09 at 21:50





          Good on you for looking stuff up in the source! :)

          – Colin Gravill
          Sep 10 '09 at 21:50













          31














          Use this:



          > a = "my_string"
          > meth = a.method("size")
          > meth.call() # call the size method
          => 9


          Simple, right?



          As for the global, I think the Ruby way would be to search it using the methods method.






          share|improve this answer



















          • 1





            +1. like this. Ruby has such great syntax. Love it.

            – BuddyJoe
            Sep 10 '09 at 20:40











          • meth = a.method? isn't this call the function already? what if the method returns something?

            – user1735921
            Nov 16 '15 at 7:07











          • FYI for when the method doesn't exist: "my_string".method('blah') #=> NameError: undefined method blah' for class String'

            – Joshua Pinter
            Dec 30 '17 at 22:31
















          31














          Use this:



          > a = "my_string"
          > meth = a.method("size")
          > meth.call() # call the size method
          => 9


          Simple, right?



          As for the global, I think the Ruby way would be to search it using the methods method.






          share|improve this answer



















          • 1





            +1. like this. Ruby has such great syntax. Love it.

            – BuddyJoe
            Sep 10 '09 at 20:40











          • meth = a.method? isn't this call the function already? what if the method returns something?

            – user1735921
            Nov 16 '15 at 7:07











          • FYI for when the method doesn't exist: "my_string".method('blah') #=> NameError: undefined method blah' for class String'

            – Joshua Pinter
            Dec 30 '17 at 22:31














          31












          31








          31







          Use this:



          > a = "my_string"
          > meth = a.method("size")
          > meth.call() # call the size method
          => 9


          Simple, right?



          As for the global, I think the Ruby way would be to search it using the methods method.






          share|improve this answer













          Use this:



          > a = "my_string"
          > meth = a.method("size")
          > meth.call() # call the size method
          => 9


          Simple, right?



          As for the global, I think the Ruby way would be to search it using the methods method.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Sep 10 '09 at 20:18









          GeoGeo

          46.2k91289467




          46.2k91289467








          • 1





            +1. like this. Ruby has such great syntax. Love it.

            – BuddyJoe
            Sep 10 '09 at 20:40











          • meth = a.method? isn't this call the function already? what if the method returns something?

            – user1735921
            Nov 16 '15 at 7:07











          • FYI for when the method doesn't exist: "my_string".method('blah') #=> NameError: undefined method blah' for class String'

            – Joshua Pinter
            Dec 30 '17 at 22:31














          • 1





            +1. like this. Ruby has such great syntax. Love it.

            – BuddyJoe
            Sep 10 '09 at 20:40











          • meth = a.method? isn't this call the function already? what if the method returns something?

            – user1735921
            Nov 16 '15 at 7:07











          • FYI for when the method doesn't exist: "my_string".method('blah') #=> NameError: undefined method blah' for class String'

            – Joshua Pinter
            Dec 30 '17 at 22:31








          1




          1





          +1. like this. Ruby has such great syntax. Love it.

          – BuddyJoe
          Sep 10 '09 at 20:40





          +1. like this. Ruby has such great syntax. Love it.

          – BuddyJoe
          Sep 10 '09 at 20:40













          meth = a.method? isn't this call the function already? what if the method returns something?

          – user1735921
          Nov 16 '15 at 7:07





          meth = a.method? isn't this call the function already? what if the method returns something?

          – user1735921
          Nov 16 '15 at 7:07













          FYI for when the method doesn't exist: "my_string".method('blah') #=> NameError: undefined method blah' for class String'

          – Joshua Pinter
          Dec 30 '17 at 22:31





          FYI for when the method doesn't exist: "my_string".method('blah') #=> NameError: undefined method blah' for class String'

          – Joshua Pinter
          Dec 30 '17 at 22:31











          31














          Three Ways: send / call / eval - and their Benchmarks



          Typical invocation (for reference):



          s= "hi man"
          s.length #=> 6


          Using send



          s.send(:length) #=> 6


          Using call



          method_object = s.method(:length) 
          p method_object.call #=> 6


          Using eval



          eval "s.length" #=> 6


           



          Benchmarks



          require "benchmark" 
          test = "hi man"
          m = test.method(:length)
          n = 100000
          Benchmark.bmbm {|x|
          x.report("call") { n.times { m.call } }
          x.report("send") { n.times { test.send(:length) } }
          x.report("eval") { n.times { eval "test.length" } }
          }



          ...as you can see, instantiating a method object is the fastest dynamic way in calling a method, also notice how slow using eval is.




          #######################################
          ##### The results
          #######################################
          #Rehearsal ----------------------------------------
          #call 0.050000 0.020000 0.070000 ( 0.077915)
          #send 0.080000 0.000000 0.080000 ( 0.086071)
          #eval 0.360000 0.040000 0.400000 ( 0.405647)
          #------------------------------- total: 0.550000sec

          # user system total real
          #call 0.050000 0.020000 0.070000 ( 0.072041)
          #send 0.070000 0.000000 0.070000 ( 0.077674)
          #eval 0.370000 0.020000 0.390000 ( 0.399442)


          Credit goes to this blog post which elaborates a bit more on the three methods and also shows how to check if the methods exist.






          share|improve this answer
























          • I was just finding this, and I noticed something that wasn't covered. What would I do if I wanted to do Class.send("classVariable") = 5? That throws an error. Is there any way around that? The same thing is true for using Class.method("classVariable").call() = 5

            – thesecretmaster
            Nov 20 '15 at 22:14













          • if you want to send some argument with send call use something like this ClassName.send("method_name", arg1, arg2)

            – Aleem
            Aug 30 '17 at 10:07













          • Shouldn't your benchmark for call include instantiating the method object (m.test.method(:length)) to accurately represent it's true time? When using call you're likely going to instantiate the method object every time.

            – Joshua Pinter
            Dec 30 '17 at 22:29











          • Blog post link is dead, btw.

            – Joshua Pinter
            Dec 30 '17 at 22:30
















          31














          Three Ways: send / call / eval - and their Benchmarks



          Typical invocation (for reference):



          s= "hi man"
          s.length #=> 6


          Using send



          s.send(:length) #=> 6


          Using call



          method_object = s.method(:length) 
          p method_object.call #=> 6


          Using eval



          eval "s.length" #=> 6


           



          Benchmarks



          require "benchmark" 
          test = "hi man"
          m = test.method(:length)
          n = 100000
          Benchmark.bmbm {|x|
          x.report("call") { n.times { m.call } }
          x.report("send") { n.times { test.send(:length) } }
          x.report("eval") { n.times { eval "test.length" } }
          }



          ...as you can see, instantiating a method object is the fastest dynamic way in calling a method, also notice how slow using eval is.




          #######################################
          ##### The results
          #######################################
          #Rehearsal ----------------------------------------
          #call 0.050000 0.020000 0.070000 ( 0.077915)
          #send 0.080000 0.000000 0.080000 ( 0.086071)
          #eval 0.360000 0.040000 0.400000 ( 0.405647)
          #------------------------------- total: 0.550000sec

          # user system total real
          #call 0.050000 0.020000 0.070000 ( 0.072041)
          #send 0.070000 0.000000 0.070000 ( 0.077674)
          #eval 0.370000 0.020000 0.390000 ( 0.399442)


          Credit goes to this blog post which elaborates a bit more on the three methods and also shows how to check if the methods exist.






          share|improve this answer
























          • I was just finding this, and I noticed something that wasn't covered. What would I do if I wanted to do Class.send("classVariable") = 5? That throws an error. Is there any way around that? The same thing is true for using Class.method("classVariable").call() = 5

            – thesecretmaster
            Nov 20 '15 at 22:14













          • if you want to send some argument with send call use something like this ClassName.send("method_name", arg1, arg2)

            – Aleem
            Aug 30 '17 at 10:07













          • Shouldn't your benchmark for call include instantiating the method object (m.test.method(:length)) to accurately represent it's true time? When using call you're likely going to instantiate the method object every time.

            – Joshua Pinter
            Dec 30 '17 at 22:29











          • Blog post link is dead, btw.

            – Joshua Pinter
            Dec 30 '17 at 22:30














          31












          31








          31







          Three Ways: send / call / eval - and their Benchmarks



          Typical invocation (for reference):



          s= "hi man"
          s.length #=> 6


          Using send



          s.send(:length) #=> 6


          Using call



          method_object = s.method(:length) 
          p method_object.call #=> 6


          Using eval



          eval "s.length" #=> 6


           



          Benchmarks



          require "benchmark" 
          test = "hi man"
          m = test.method(:length)
          n = 100000
          Benchmark.bmbm {|x|
          x.report("call") { n.times { m.call } }
          x.report("send") { n.times { test.send(:length) } }
          x.report("eval") { n.times { eval "test.length" } }
          }



          ...as you can see, instantiating a method object is the fastest dynamic way in calling a method, also notice how slow using eval is.




          #######################################
          ##### The results
          #######################################
          #Rehearsal ----------------------------------------
          #call 0.050000 0.020000 0.070000 ( 0.077915)
          #send 0.080000 0.000000 0.080000 ( 0.086071)
          #eval 0.360000 0.040000 0.400000 ( 0.405647)
          #------------------------------- total: 0.550000sec

          # user system total real
          #call 0.050000 0.020000 0.070000 ( 0.072041)
          #send 0.070000 0.000000 0.070000 ( 0.077674)
          #eval 0.370000 0.020000 0.390000 ( 0.399442)


          Credit goes to this blog post which elaborates a bit more on the three methods and also shows how to check if the methods exist.






          share|improve this answer













          Three Ways: send / call / eval - and their Benchmarks



          Typical invocation (for reference):



          s= "hi man"
          s.length #=> 6


          Using send



          s.send(:length) #=> 6


          Using call



          method_object = s.method(:length) 
          p method_object.call #=> 6


          Using eval



          eval "s.length" #=> 6


           



          Benchmarks



          require "benchmark" 
          test = "hi man"
          m = test.method(:length)
          n = 100000
          Benchmark.bmbm {|x|
          x.report("call") { n.times { m.call } }
          x.report("send") { n.times { test.send(:length) } }
          x.report("eval") { n.times { eval "test.length" } }
          }



          ...as you can see, instantiating a method object is the fastest dynamic way in calling a method, also notice how slow using eval is.




          #######################################
          ##### The results
          #######################################
          #Rehearsal ----------------------------------------
          #call 0.050000 0.020000 0.070000 ( 0.077915)
          #send 0.080000 0.000000 0.080000 ( 0.086071)
          #eval 0.360000 0.040000 0.400000 ( 0.405647)
          #------------------------------- total: 0.550000sec

          # user system total real
          #call 0.050000 0.020000 0.070000 ( 0.072041)
          #send 0.070000 0.000000 0.070000 ( 0.077674)
          #eval 0.370000 0.020000 0.390000 ( 0.399442)


          Credit goes to this blog post which elaborates a bit more on the three methods and also shows how to check if the methods exist.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Aug 8 '15 at 13:09









          cwdcwd

          27.5k43141184




          27.5k43141184













          • I was just finding this, and I noticed something that wasn't covered. What would I do if I wanted to do Class.send("classVariable") = 5? That throws an error. Is there any way around that? The same thing is true for using Class.method("classVariable").call() = 5

            – thesecretmaster
            Nov 20 '15 at 22:14













          • if you want to send some argument with send call use something like this ClassName.send("method_name", arg1, arg2)

            – Aleem
            Aug 30 '17 at 10:07













          • Shouldn't your benchmark for call include instantiating the method object (m.test.method(:length)) to accurately represent it's true time? When using call you're likely going to instantiate the method object every time.

            – Joshua Pinter
            Dec 30 '17 at 22:29











          • Blog post link is dead, btw.

            – Joshua Pinter
            Dec 30 '17 at 22:30



















          • I was just finding this, and I noticed something that wasn't covered. What would I do if I wanted to do Class.send("classVariable") = 5? That throws an error. Is there any way around that? The same thing is true for using Class.method("classVariable").call() = 5

            – thesecretmaster
            Nov 20 '15 at 22:14













          • if you want to send some argument with send call use something like this ClassName.send("method_name", arg1, arg2)

            – Aleem
            Aug 30 '17 at 10:07













          • Shouldn't your benchmark for call include instantiating the method object (m.test.method(:length)) to accurately represent it's true time? When using call you're likely going to instantiate the method object every time.

            – Joshua Pinter
            Dec 30 '17 at 22:29











          • Blog post link is dead, btw.

            – Joshua Pinter
            Dec 30 '17 at 22:30

















          I was just finding this, and I noticed something that wasn't covered. What would I do if I wanted to do Class.send("classVariable") = 5? That throws an error. Is there any way around that? The same thing is true for using Class.method("classVariable").call() = 5

          – thesecretmaster
          Nov 20 '15 at 22:14







          I was just finding this, and I noticed something that wasn't covered. What would I do if I wanted to do Class.send("classVariable") = 5? That throws an error. Is there any way around that? The same thing is true for using Class.method("classVariable").call() = 5

          – thesecretmaster
          Nov 20 '15 at 22:14















          if you want to send some argument with send call use something like this ClassName.send("method_name", arg1, arg2)

          – Aleem
          Aug 30 '17 at 10:07







          if you want to send some argument with send call use something like this ClassName.send("method_name", arg1, arg2)

          – Aleem
          Aug 30 '17 at 10:07















          Shouldn't your benchmark for call include instantiating the method object (m.test.method(:length)) to accurately represent it's true time? When using call you're likely going to instantiate the method object every time.

          – Joshua Pinter
          Dec 30 '17 at 22:29





          Shouldn't your benchmark for call include instantiating the method object (m.test.method(:length)) to accurately represent it's true time? When using call you're likely going to instantiate the method object every time.

          – Joshua Pinter
          Dec 30 '17 at 22:29













          Blog post link is dead, btw.

          – Joshua Pinter
          Dec 30 '17 at 22:30





          Blog post link is dead, btw.

          – Joshua Pinter
          Dec 30 '17 at 22:30











          3














          Personally I would setup a hash to function references and then use the string as an index to the hash. You then call the function reference with it's parameters. This has the advantage of not allowing the wrong string to call something you don't want to call. The other way is to basically eval the string. Do not do this.



          PS don't be lazy and actually type out your whole question, instead of linking to something.






          share|improve this answer
























          • Sorry. I'll copy some of the wording and translate to make it Ruby specific. +1

            – BuddyJoe
            Sep 10 '09 at 20:37
















          3














          Personally I would setup a hash to function references and then use the string as an index to the hash. You then call the function reference with it's parameters. This has the advantage of not allowing the wrong string to call something you don't want to call. The other way is to basically eval the string. Do not do this.



          PS don't be lazy and actually type out your whole question, instead of linking to something.






          share|improve this answer
























          • Sorry. I'll copy some of the wording and translate to make it Ruby specific. +1

            – BuddyJoe
            Sep 10 '09 at 20:37














          3












          3








          3







          Personally I would setup a hash to function references and then use the string as an index to the hash. You then call the function reference with it's parameters. This has the advantage of not allowing the wrong string to call something you don't want to call. The other way is to basically eval the string. Do not do this.



          PS don't be lazy and actually type out your whole question, instead of linking to something.






          share|improve this answer













          Personally I would setup a hash to function references and then use the string as an index to the hash. You then call the function reference with it's parameters. This has the advantage of not allowing the wrong string to call something you don't want to call. The other way is to basically eval the string. Do not do this.



          PS don't be lazy and actually type out your whole question, instead of linking to something.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Sep 10 '09 at 20:16









          dlamblindlamblin

          27.1k1875109




          27.1k1875109













          • Sorry. I'll copy some of the wording and translate to make it Ruby specific. +1

            – BuddyJoe
            Sep 10 '09 at 20:37



















          • Sorry. I'll copy some of the wording and translate to make it Ruby specific. +1

            – BuddyJoe
            Sep 10 '09 at 20:37

















          Sorry. I'll copy some of the wording and translate to make it Ruby specific. +1

          – BuddyJoe
          Sep 10 '09 at 20:37





          Sorry. I'll copy some of the wording and translate to make it Ruby specific. +1

          – BuddyJoe
          Sep 10 '09 at 20:37


















          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%2f1407451%2fcalling-a-function-from-a-string-with-the-functions-name-in-ruby%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

          MongoDB - Not Authorized To Execute Command

          How to fix TextFormField cause rebuild widget in Flutter

          Npm cannot find a required file even through it is in the searched directory