Dynamic message dispatch?

Suppose I have methods foo and bar. How can I read a string from ARGV
or input and turn it directly into the message dispatch? I’m trying
to avoid explicit if/else or switch based dispatching, so that the
logic wouldn’t change if someone (me) later adds new methods directly,
by sub-classing, or using mix-ins.

Suppose I have methods foo and bar. How can I read a string
from ARGV or input and turn it directly into the message
dispatch?

Sorry, I meant to say “How can I read ‘foo’ or ‘bar’ as a string
from…”. I’m not asking how to do the input, I can’t figure out how
to convert a string into a method invocation on the fly.

Hi,

···

In message “Re: Dynamic message dispatch?” on 02/11/04, Paul J. Sanchez paul@argelfraster.org writes:

Suppose I have methods foo and bar. How can I read a string
from ARGV or input and turn it directly into the message
dispatch?

Sorry, I meant to say “How can I read ‘foo’ or ‘bar’ as a string
from…”. I’m not asking how to do the input, I can’t figure out how
to convert a string into a method invocation on the fly.

send?

self.send(“print”, “foo\n”)

						matz.

It seems to me that methods such as #send and
#define_method offer safer/saner alternatives
to eval.

In that vein: Suppose I had a config file
with lines of the form:
var_name = string_or_number

It is tempting simply to read each line and
do an eval in order to grab this information
(or perhaps even do a require).

But this is not really safe if we assume someone
could accidentally/purposely put something ugly
in the file.

Is there a better way to handle lines of the
form country=“United States” and size=256
without building a parser?

And BTW, are you still in North America??? :slight_smile:
How did it all go?

Hal

···

----- Original Message -----
From: “Yukihiro Matsumoto” matz@ruby-lang.org
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Sunday, November 03, 2002 4:39 PM
Subject: Re: Dynamic message dispatch?

Hi,

In message “Re: Dynamic message dispatch?” > on 02/11/04, Paul J. Sanchez paul@argelfraster.org writes:

Suppose I have methods foo and bar. How can I read a string
from ARGV or input and turn it directly into the message
dispatch?

Sorry, I meant to say “How can I read ‘foo’ or ‘bar’ as a string
from…”. I’m not asking how to do the input, I can’t figure out how
to convert a string into a method invocation on the fly.

send?

self.send(“print”, “foo\n”)

Hi, In message “Re: Dynamic message dispatch?” on 02/11/04,
Paul J. Sanchez paul@argelfraster.org writes:

> > > Suppose I have methods foo and bar.  How can I read a
> string | me> from ARGV or input and turn it directly into
> the message | me> dispatch?
> >
> >Sorry, I meant to say "How can I read 'foo' or 'bar' as a
> string |from...".  I'm not asking how to do the input, I
> can't figure out how |to convert a string into a method
> invocation on the fly.

> send?

>   self.send("print", "foo\n")

That worked beautifully. Thanks!

–paul

If just using a parser is an option, here’s what record.rb does:

DATA_CONF =<<EOF
device = /dev/hda
speed = 15 Mb/s

comments wont = fool my regexp :wink:

brand = acme
EOF

class TestConf < Test::Unit::TestCase
def set_up
@r = Record.new(Record::PRESET_KEYVALUE, ’ =')
@r << DATA_CONF
end

def test_output_matches_original
  without_blanks_and_comments = DATA_CONF.gsub("\n\n", "\n").gsub(/^\s*#.+?\n/m, '')
  
  assert_equal without_blanks_and_comments, @r.to_s
end

def test_get_values 
  assert_equal '/dev/hda', @r['device']
  assert_equal '15 Mb/s', @r['speed']
  assert_equal 'acme', @r['brand']
end

end

I’m using it for files whose entries are in the form
(such as var_name = string_or_number' but also key: value’, like email headers), and also lets you write
specific parsers and formatters for fields whose name matches a given
stringo or whose content matches a given regexp. From the inline doc:

DATA =<<EOF
Name: sherlock
Surname: holmes
Address: baker st, 12
City: london
Defeats:
Description: detective
solves first case in a Spielberg movie…
Friends: Sir Doyle, Dr. Watson
EOF

@r = Record.new
@r.read(‘Address’) do |text|
text =~ /(.+?),\s*(\d+)/
{“Street” => $1, “Nr.” => $2.to_i}
end

@r.read(/,/) do |text|
text.split(/,\s*/)
end

@r << DATA
@r[‘Street’] → {“Street” => “baker st”, “Nr.” => 12}
@r[‘Friends’] → [“Sir Doyle”, “Dr. Watson”]

record.rb is under archive/ in the rpkg install. It’s just ~400 lines
with tests and docs and it’s the base for the manipulation of rpkg
metadata and for a mbox handler.

OTOH, if the file format is not decided already, YAML is something
to consider.

(BTW, anybody remembers the correct Holmes’ house street number?)

Massimiliano

···

On Mon, Nov 04, 2002 at 07:50:20AM +0900, Hal E. Fulton wrote:

In that vein: Suppose I had a config file
with lines of the form:
var_name = string_or_number

It is tempting simply to read each line and
do an eval in order to grab this information
(or perhaps even do a require).

But this is not really safe if we assume someone
could accidentally/purposely put something ugly
in the file.

Is there a better way to handle lines of the
form country=“United States” and size=256
without building a parser?

(BTW, anybody remembers the correct Holmes’ house street
number?)

221b if I recall correctly.