Dynamic method call

Hi --

···

On Thu, 2 Aug 2007, Todd Burch wrote:

This may be slightly different, but I am calling a method dynamically
this way:

case tool
when "drill" then
  @operation = self.method(:drill) ;
when "cut" then
  @operation = self.method(:cut) ;
when "bend" then
  @operation = self.method(:bend) ;
end

@operation.call ; # call whatever method was set.

Unless I'm missing a subtlety, you could also do that as the somewhat
more concise:

   send(tool) if tool

David

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

and

do_something(..) if condition

doesn't require anything. I'm still missing what value this
if_is_true stuff is adding.

···

On 8/2/07, James Edward Gray II <james@grayproductions.net> wrote:

On Aug 2, 2007, at 2:27 AM, Andrea Maschio wrote:

> Ok, Gregory, now i understand that i didn't explain very well. The
> only part
> in wich the user (let's say a VERY junior programmer) is the scripting
> interface i provide for him, so he will write
> if_is_true(a_condition, "do_something(arg1,arg2)")
>
> tha internal implementation is my matter, but if you think eval is
> bad (i
> probably understand why), the solution with
>
> send(:method,arg1,arg2)
>
> is probably good, but how can i allow a user to input the method
> name with
> his arguments? Anyway, i'm going to try.

Have you considered:

   if_is_true(condition) { do_something(...) }

?

That doesn't require eval() or send().

To put in my 2 cents, this offends my senses. Whats wrong with:

if 1 < 2
p "gagme"
else
puts "perdue"
end

or even
1 < 2 ? p "gagme" : puts "perdue"

Calling a method with a hash argument just to perform a condition
makes me cringe, performance wise. Plus it just seems so overly
clever.

···

On Aug 5, 4:47 pm, "Gregory Brown" <gregory.t.br...@gmail.com> wrote:

On 8/4/07, Bas van Gils <b...@van-gils.org> wrote:

> On Thu, Aug 02, 2007 at 04:48:30AM +0900, dohzya wrote:

> > Do you want something like this :
> > ---
> > def sendif( args, &bloc )
> > if args[:if]
> > send args[:then].shift, *args[:then], &bloc
> > else
> > send args[:else].shift, *args[:else], &bloc if args[:else]
> > end
> > end

> > sendif :if => 1 < 2, :then => [:p, "gagne"], :else => [:puts, "perdu"]
> > ---
> > ?

> Damn, that's elegant!

I dig it too, though I like better:

sendif 1 < 2, :then => [:p, "gagne"], :else => [:puts, "perdue"]

just because it kills the redundant if.

in ruby 1.9 :

···

Le lundi 06 août 2007 à 08:47 +0900, Gregory Brown a écrit :

On 8/4/07, Bas van Gils <bas@van-gils.org> wrote:
> On Thu, Aug 02, 2007 at 04:48:30AM +0900, dohzya wrote:
> >
> > Do you want something like this :
> > ---
> > def sendif( args, &bloc )
> > if args[:if]
> > send args[:then].shift, *args[:then], &bloc
> > else
> > send args[:else].shift, *args[:else], &bloc if args[:else]
> > end
> > end
> >
> > sendif :if => 1 < 2, :then => [:p, "gagne"], :else => [:puts, "perdu"]
> > ---
> > ?
>
> Damn, that's elegant!

I dig it too, though I like better:

sendif 1 < 2, :then => [:p, "gagne"], :else => [:puts, "perdue"]

just because it kills the redundant if.

---
sendif 1 < 2, then: [:p, "gagne"], else: [:puts, "perdue"]
---
as elegant as Objective-C !

if I am very evil :
---
def then &b ; Proc.new &b ; end
def else &b ; Proc.new &b ; end
def sendif test, then, else
  test ? then.call : else.call
end
sendif 1 < 2, then {p "gagne"}, else {puts "perdue"}
---
but it's too expensive for a simple function...

--
Etienne Vallette d'Osia

unknown wrote:

Unless I'm missing a subtlety, you could also do that as the somewhat
more concise:

   send(tool) if tool

David

Thanks for the shortcuts - I didn't know either of these techniques
could be done. In my example, I do other things inside each WHEN
statement to set up the call, but I condensed my example to post.

Thanks! Todd

···

--
Posted via http://www.ruby-forum.com/\.

I would (personally) take it a step farther:

send( tool ) if tool && respond_to? tool

or something similar.

···

On Aug 02, 2007, at 09:16 , dblack@rubypal.com wrote:

  send(tool) if tool

--
Wayne E. Seguin
Sr. Systems Architect & Systems Admin
wayneseguin@gmail.com

# do_something(..) if condition

···

From: Gregory Brown [mailto:gregory.t.brown@gmail.com]
#
# doesn't require anything. I'm still missing what value this
# if_is_true stuff is adding.

i think he's asking for boolean obj so he can chain conditions. soemthing like,

   cond.if_true(foo).bar.blah.if_true.baz.light

which is
   
   if cond
      if x = foo.bar.blah
         x.baz.light
      end
   end

kind regards -botp

Full ack, though if you look through some of the mess we have seen in
this thread, this looks good by comparison. The issue is that the OP
is building a DSL for non-english speakers and needs to have an if
construct that matches the language. So the send_if bit is part of
the implementation details for that.

That having been said, the only benefit of the above is that it lends
nicely to dynamic buildup of calls, but I'd prefer passing around
lambdas, all else considered equal. It just seems like the OP wants
to avoid blocks in general.

···

On 8/5/07, evanwebb@gmail.com <evanwebb@gmail.com> wrote:

On Aug 5, 4:47 pm, "Gregory Brown" <gregory.t.br...@gmail.com> wrote:
> On 8/4/07, Bas van Gils <b...@van-gils.org> wrote:
>
>
>
> > On Thu, Aug 02, 2007 at 04:48:30AM +0900, dohzya wrote:
>
> > > Do you want something like this :
> > > ---
> > > def sendif( args, &bloc )
> > > if args[:if]
> > > send args[:then].shift, *args[:then], &bloc
> > > else
> > > send args[:else].shift, *args[:else], &bloc if args[:else]
> > > end
> > > end
>
> > > sendif :if => 1 < 2, :then => [:p, "gagne"], :else => [:puts, "perdu"]
> > > ---
> > > ?
>
> > Damn, that's elegant!
>
> I dig it too, though I like better:
>
> sendif 1 < 2, :then => [:p, "gagne"], :else => [:puts, "perdue"]
>
> just because it kills the redundant if.

To put in my 2 cents, this offends my senses. Whats wrong with:

if 1 < 2
p "gagme"
else
puts "perdue"
end

or even
1 < 2 ? p "gagme" : puts "perdue"

Calling a method with a hash argument just to perform a condition
makes me cringe, performance wise. Plus it just seems so overly
clever.

let us make it cheaper then

def then &b; b.call end
def else &b; b.call end
sendif 1 < 2, then { p "gagnee"}, else { puts "perdu"}

My wife made me change the output :wink:

Cheers
Robert

···

On 8/6/07, dohzya <dohzya@gmail.com> wrote:

Le lundi 06 août 2007 à 08:47 +0900, Gregory Brown a écrit :
> On 8/4/07, Bas van Gils <bas@van-gils.org> wrote:
> > On Thu, Aug 02, 2007 at 04:48:30AM +0900, dohzya wrote:
> > >
> > > Do you want something like this :
> > > ---
> > > def sendif( args, &bloc )
> > > if args[:if]
> > > send args[:then].shift, *args[:then], &bloc
> > > else
> > > send args[:else].shift, *args[:else], &bloc if args[:else]
> > > end
> > > end
> > >
> > > sendif :if => 1 < 2, :then => [:p, "gagne"], :else => [:puts, "perdu"]
> > > ---
> > > ?
> >
> > Damn, that's elegant!
>
> I dig it too, though I like better:
>
> sendif 1 < 2, :then => [:p, "gagne"], :else => [:puts, "perdue"]
>
> just because it kills the redundant if.
>

in ruby 1.9 :
---
sendif 1 < 2, then: [:p, "gagne"], else: [:puts, "perdue"]
---
as elegant as Objective-C !

if I am very evil :
---
def then &b ; Proc.new &b ; end
def else &b ; Proc.new &b ; end
def sendif test, then, else
  test ? then.call : else.call
end
sendif 1 < 2, then {p "gagne"}, else {puts "perdue"}
---
but it's too expensive for a simple function...

--
[...] as simple as possible, but no simpler.
-- Attributed to Albert Einstein

Sure, that could be helpful, but I'm not sure how you came up with
that based on what was asked.

For what you've shown there, I've often longed for a Null object

something like

class Null < BasicObject
  def self.method_missing(id,*args,&block)
     self
  end
end

module Kernel
  def if_true(condition)
     condition ? self : Null
  end
end

Note that I didn't even remotely test the above (though I have
implemented this before for fun), but that hopefully the idea is
preserved.

···

On 8/2/07, Peña, Botp <botp@delmonte-phil.com> wrote:

From: Gregory Brown [mailto:gregory.t.brown@gmail.com]
# do_something(..) if condition
#
# doesn't require anything. I'm still missing what value this
# if_is_true stuff is adding.

i think he's asking for boolean obj so he can chain conditions. soemthing like,

   cond.if_true(foo).bar.blah.if_true.baz.light

which is

   if cond
      if x = foo.bar.blah
         x.baz.light
      end
   end

You could still get the same benefit by setting up a hash of name-value
papers, e.g.,

actions = {
  "drill" => :do_the_drill_thang,
  "cut" => :slice_and_dice,
  ...
}

send(actions[tool]) if tool

An alternative, maybe better, idea would be to define method aliases, e.g.,

method_alias :drill, :do_the_drill_thang
...

send(tool) if tool

dean

···

On 8/2/07, Todd Burch <promos@burchwoodusa.com> wrote:

unknown wrote:
>
> Unless I'm missing a subtlety, you could also do that as the somewhat
> more concise:
>
> send(tool) if tool
>
>
> David

Thanks for the shortcuts - I didn't know either of these techniques
could be done. In my example, I do other things inside each WHEN
statement to set up the call, but I condensed my example to post.

Thanks! Todd

--
Dean Wampler
http://www.objectmentor.com
http://www.aspectprogramming.com
http://www.contract4j.org

output: "gagneeperdu" (or "perdugagnee")
result: nil

the 2 arguments are valued BEFORE calling the function...
you can't do that without macro or lazy-function

···

Le lundi 06 août 2007 à 19:44 +0900, Robert Dober a écrit :

def then &b; b.call end
def else &b; b.call end
sendif 1 < 2, then { p "gagnee"}, else { puts "perdu"}

--
Etienne Vallette d'Osia