Dynamic Methods

Hi all,

I wonder if anyone has any suggestions on how to create a method that
matches its name based on a regular expression. For instance:

class Foo
def /bar*/
puts "Wow!"
end
end

Then I could do something like:

foo = Foo.new
foo.barchart
foo.barstweward

The regexp method name throws the interpreter off of course.

I looked at the method_missing feature to implement this. It gets part of
the problem solved, but I then don’t know what the regular expression for
the method name is.

Anyone have any ideas or pointers on where I could look?

TIA, John.

“John” nojgoalbyspam@hotmail.com writes:

I wonder if anyone has any suggestions on how to create a method that
matches its name based on a regular expression. For instance:

How about something like this:

 class Dave

   # This part implements the 'alias_regexp' thingie

   @@_method_matches = {}

   def self.alias_regexp(regexp, name)
     @@_method_matches[regexp] = name
   end

   def method_missing(name, *args)
     name = name.to_s
     @@_method_matches.each do |regexp, target|
       if regexp =~ name.to_s
         return send(target, *args)
       end
     end
     super
   end


   # and this demonstrates it in action

   def do_it
     puts "do it"
   end

   def dont
     puts "dont"
   end

   alias_regexp /no.*/, :dont
   alias_regexp /nyet.*/, :dont
   alias_regexp /yes.*/, :do_it
 end

 d = Dave.new
 d.no_way
 d.nyet_way
 d.yes_please

Cheers

Dave

Hi all,

I wonder if anyone has any suggestions on how to create a method that
matches its name based on a regular expression. For instance:

[snip]

I looked at the method_missing feature to implement this. It gets part of
the problem solved, but I then don’t know what the regular expression for
the method name is.

Anyone have any ideas or pointers on where I could look?

Not sure exactly what you want… the method name gets passed
in, right? As a symbol?

Untested code follows – doing this from memory.

def method_missing(name,args)
if name ~ /^bar.
/
puts “I’m #{name.to_s}, one of the bar family.”
else
puts “I’m not a bar at all.”
end
end

Hal Fulton

···

----- Original Message -----
From: “John” nojgoalbyspam@hotmail.com
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Friday, July 12, 2002 1:58 PM
Subject: Dynamic Methods

somthing like:

def method_missing(name, args)
meths = instance_methods +
private_instance_methods +
protected_instance_methods
re = Regexp.new("(#{name}.
)[;]")
md = re.match(meths.join(‘;’))
send(md[1], *args) if md
end

essentially it looks at all the methods available and finds a match then
uses send to call it.

this is not tested, but should work along these lines. could also be
made a little more concise.

~transami

···

On Fri, 2002-07-12 at 12:58, John wrote:

Hi all,

I wonder if anyone has any suggestions on how to create a method that
matches its name based on a regular expression. For instance:

class Foo
def /bar*/
puts “Wow!”
end
end

Then I could do something like:

foo = Foo.new
foo.barchart
foo.barstweward

The regexp method name throws the interpreter off of course.

I looked at the method_missing feature to implement this. It gets part of
the problem solved, but I then don’t know what the regular expression for
the method name is.

Anyone have any ideas or pointers on where I could look?

TIA, John.


~transami

__("< berk! berk!
__/
^^

instersting. with something like this, if the method_missing routine was
sophisticated enough you could have “sloppy” programming. imagine your
program still working even if you misspelled a method call. a strange
notion.

~transami

···

On Fri, 2002-07-12 at 12:58, John wrote:

Hi all,

I wonder if anyone has any suggestions on how to create a method that
matches its name based on a regular expression. For instance:

class Foo
def /bar*/
puts “Wow!”
end
end

Then I could do something like:

foo = Foo.new
foo.barchart
foo.barstweward

The regexp method name throws the interpreter off of course.

I looked at the method_missing feature to implement this. It gets part of
the problem solved, but I then don’t know what the regular expression for
the method name is.

Anyone have any ideas or pointers on where I could look?

TIA, John.


~transami

__("< berk! berk!
__/
^^

Tom Sawyer transami@transami.net writes:

instersting. with something like this, if the method_missing routine
was sophisticated enough you could have “sloppy”
programming. imagine your program still working even if you
misspelled a method call. a strange notion.

This reminds me of a bash feature which lets you mistype a directory
name by 1 character and still have the cd work:

$> pwd
/home/huber
$> ls -ld tmp
drwx------ 3 huber huber 4096 Jul 12 15:40 tmp
$> cd tmpf
tmp
$> pwd
/home/huber/tmp

I like this, but I’m pretty sure I wouldn’t want that same feature in
say…rm. :slight_smile: Or ruby for that matter!

···


Josh Huber

Wow! Thanks Dave!

I assume then that its not possible with Ruby out of the box? I have been
amazed at how flexible Ruby is.

Do people think that this is such an esoteric feature that it would not be
worth adding to the language?

John.

“Dave Thomas” Dave@PragmaticProgrammer.com wrote in message
news:m2ptxsvjv1.fsf@zip.local.thomases.com

···

“John” nojgoalbyspam@hotmail.com writes:

I wonder if anyone has any suggestions on how to create a method that
matches its name based on a regular expression. For instance:

How about something like this:

 class Dave

   # This part implements the 'alias_regexp' thingie

   @@_method_matches = {}

   def self.alias_regexp(regexp, name)
     @@_method_matches[regexp] = name
   end

   def method_missing(name, *args)
     name = name.to_s
     @@_method_matches.each do |regexp, target|
       if regexp =~ name.to_s
         return send(target, *args)
       end
     end
     super
   end


   # and this demonstrates it in action

   def do_it
     puts "do it"
   end

   def dont
     puts "dont"
   end

   alias_regexp /no.*/, :dont
   alias_regexp /nyet.*/, :dont
   alias_regexp /yes.*/, :do_it
 end

 d = Dave.new
 d.no_way
 d.nyet_way
 d.yes_please

Cheers

Dave

I like this, but I’m pretty sure I wouldn’t want that same feature in
say…rm. :slight_smile: Or ruby for that matter!

LOL

My thought was that you could have aliases for methods as well as having
shorter versions:

[ls|dir|directory]

So rather than specify each to call the other, define a very dynamic regexp
to do the work for you.

John.

“Josh Huber” huber@alum.wpi.edu wrote in message
news:87ele8psuy.fsf@alum.wpi.edu…

···

Tom Sawyer transami@transami.net writes:

instersting. with something like this, if the method_missing routine
was sophisticated enough you could have “sloppy”
programming. imagine your program still working even if you
misspelled a method call. a strange notion.

This reminds me of a bash feature which lets you mistype a directory
name by 1 character and still have the cd work:

$> pwd
/home/huber
$> ls -ld tmp
drwx------ 3 huber huber 4096 Jul 12 15:40 tmp
$> cd tmpf
tmp
$> pwd
/home/huber/tmp

I like this, but I’m pretty sure I wouldn’t want that same feature in
say…rm. :slight_smile: Or ruby for that matter!


Josh Huber

Hi –

···

On Sat, 13 Jul 2002, John wrote:

Wow! Thanks Dave!

I assume then that its not possible with Ruby out of the box? I have been
amazed at how flexible Ruby is.

Well, Dave wrote it using Ruby out of the box :slight_smile: It all depends how
one defines the box…

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

I can’t say I’ve ever needed anything like this. It seems mightily
esoteric to me, yes.

(What do you propose if more than one possibility matches, by the
way?)

···

— John nojgoalbyspam@hotmail.com wrote:

Wow! Thanks Dave!

I assume then that its not possible with Ruby out of the box? I
have been
amazed at how flexible Ruby is.

Do people think that this is such an esoteric feature that it would
not be
worth adding to the language?

=====

Use your computer to help find a cure for cancer: http://members.ud.com/projects/cancer/

Yahoo IM: michael_s_campbell


Do You Yahoo!?
Sign up for SBC Yahoo! Dial - First Month Free

David Alan Black dblack@candle.superlink.net writes:

Well, Dave wrote it using Ruby out of the box :slight_smile: It all depends how
one defines the box…

With Ruby (to misquote some movie or other) there is no box.

:slight_smile:

(What do you propose if more than one possibility matches, by the
way?)

Maybe to call ALL of the methods? :wink:

Must admit to not having thought of that yet. Obviously calling all of them
is pretty weird, due to what order are they called in.

Would it be possible to see if a regular expression intersects with another
regular expression, and if so not add the one that overlaps?

John.

“Michael Campbell” michael_s_campbell@yahoo.com wrote in message
news:20020712230645.80655.qmail@web12407.mail.yahoo.com

Wow! Thanks Dave!

I assume then that its not possible with Ruby out of the box? I
have been
amazed at how flexible Ruby is.

Do people think that this is such an esoteric feature that it would
not be
worth adding to the language?

I can’t say I’ve ever needed anything like this. It seems mightily
esoteric to me, yes.

(What do you propose if more than one possibility matches, by the
way?)

=====

Use your computer to help find a cure for cancer:
http://members.ud.com/projects/cancer/

···

— John nojgoalbyspam@hotmail.com wrote:

Yahoo IM: michael_s_campbell


Do You Yahoo!?
Sign up for SBC Yahoo! Dial - First Month Free
http://sbc.yahoo.com

Pass input handling like this over to libreadline. You’ll have
almost what you want at the expense of pressing a key (tab),
in a way that users are probably much more used to, and
ambiguities will be taken care of automatically. Plus you’ll
have command history, which surely does not hurt. :slight_smile:

If you are interested in providing command line interfaces
for your applications, have a look at my cliff' module and ecalc’ example program in the rpkg repository
(http://www.allruby.com/rpkg). If you don’t want to install
rpkg, just tell me and I’ll make a .tar.gz for cliff.

Massimiliano

···

On Sat, Jul 13, 2002 at 06:58:50AM +0900, John wrote:

My thought was that you could have aliases for methods as well as having
shorter versions:

[ls|dir|directory]

Would it be possible to see if a regular expression intersects with another
regular expression, and if so not add the one that overlaps?

it might be possible, but damned difficult.

It’s been too long since my CS days, but something about that makes me think
it’s … not, at least not with any sort of reasonable time. But I have doubts
of my doubt, too, so…

In any case, what did you need this for? In 15 years of professional
programming (granted, not all of it OOP), I can’t think of a case where I would
have even considered this to be a solution to a problem. But I haven’t seen all
the problems there are yet, so I’m sure I’m missing a few. =)

Hi –

(What do you propose if more than one possibility matches, by the
way?)

Maybe to call ALL of the methods? :wink:

Or raise TooManyMethodsError :slight_smile:

Must admit to not having thought of that yet. Obviously calling all of them
is pretty weird, due to what order are they called in.

Would it be possible to see if a regular expression intersects with another
regular expression, and if so not add the one that overlaps?

I agree with Michael that it sounds (literally, scientifically)
impossible, though living as I do under a CS glass ceiling I don’t
know how the proof would go (if there is one) and would defer to more
learned opinion if said opinion were different. But still, impossible
or not, imagine being presented with:

/(^|blah)[^\Wc-gi-z]{2,3}/

and

/^...?([hi])\1/

and having to determine whether or not a string existed that matched
them both. “Impossible” is close enough for me :slight_smile:

I wonder whether you could get by with a very simplified wildcard
scheme (instead of regexes) – that might be easier to do this kind of
testing with.

David

···

On Sat, 13 Jul 2002, John wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

“Massimiliano Mirra” list@chromatic-harp.com wrote in message
news:20020716231901.D216@sphere.libero.it…

···

On Sat, Jul 13, 2002 at 06:58:50AM +0900, John wrote:

My thought was that you could have aliases for methods as well as having
shorter versions:

[ls|dir|directory]

Pass input handling like this over to libreadline. You’ll have
almost what you want at the expense of pressing a key (tab),
in a way that users are probably much more used to, and
ambiguities will be taken care of automatically. Plus you’ll
have command history, which surely does not hurt. :slight_smile:

If you are interested in providing command line interfaces
for your applications, have a look at my cliff' module and ecalc’ example program in the rpkg repository
(http://www.allruby.com/rpkg). If you don’t want to install
rpkg, just tell me and I’ll make a .tar.gz for cliff.

Massimiliano

I have never heard of libreadline before. I did a quick search and was
inundated with hits. Where is the place to get libreadline for Ruby? I saw
something related to debian, but I have Windoze.

I will also take a look at your cliff module.

Thanks

John.

Basically I thought it was nigh impossible too. But you never know in this
crazy world. I see things quite often that I didn’t know where possible.
Ruby has a few of those!!!

Raising the too many methods error is a good solution. You can even add the
methods that it matched to the exception to let the caller decide which one
they would like from that list.

John.

“David Alan Black” dblack@candle.superlink.net wrote in message
news:Pine.LNX.4.30.0207131030500.8431-100000@candle.superlink.net

Hi –

(What do you propose if more than one possibility matches, by the
way?)

Maybe to call ALL of the methods? :wink:

Or raise TooManyMethodsError :slight_smile:

Must admit to not having thought of that yet. Obviously calling all of
them
is pretty weird, due to what order are they called in.

Would it be possible to see if a regular expression intersects with
another

···

On Sat, 13 Jul 2002, John wrote:

regular expression, and if so not add the one that overlaps?

I agree with Michael that it sounds (literally, scientifically)
impossible, though living as I do under a CS glass ceiling I don’t
know how the proof would go (if there is one) and would defer to more
learned opinion if said opinion were different. But still, impossible
or not, imagine being presented with:

/(^|blah)[^\Wc-gi-z]{2,3}/

and

/^...?([hi])\1/

and having to determine whether or not a string existed that matched
them both. “Impossible” is close enough for me :slight_smile:

I wonder whether you could get by with a very simplified wildcard
scheme (instead of regexes) – that might be easier to do this kind of
testing with.

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

In any case, what did you need this for?

I assume you mean having the class respond to methods that match a regexp?

So you can have a user input commands without having to type the whole
command. Also for having aliases for commands without having to write each
method to call the main method.

class foo
def /[ls|dir|directory]/
end
def /desc.*/
end
end

foo.ls
foo.dir
foo.directory

foo.desc
foo.describe

Personally I think its kinda neat. I love the power of regular expressions.
Not to mention that the regexp is data and so can be read at runtime from a
database/file. I know that due to this layer of indirection that it will
make execution slower, but thats what faster machines are for :wink:

John.

“Mike Campbell” michael_s_campbell@yahoo.com wrote in message
news:NFBBKBEMGLGCIPPFGHOLMEIICJAA.michael_s_campbell@yahoo.com

Would it be possible to see if a regular expression intersects with
another
regular expression, and if so not add the one that overlaps?

it might be possible, but damned difficult.

It’s been too long since my CS days, but something about that makes me
think
it’s … not, at least not with any sort of reasonable time. But I have
doubts
of my doubt, too, so…

In any case, what did you need this for? In 15 years of professional
programming (granted, not all of it OOP), I can’t think of a case where I
would
have even considered this to be a solution to a problem. But I haven’t
seen all

···

the problems there are yet, so I’m sure I’m missing a few. =)

I have never heard of libreadline before. I did a quick search and was
inundated with hits. Where is the place to get libreadline for Ruby? I saw
something related to debian, but I have Windoze.

Ah! I see. Yes, in Debian it’s just a matter of getting the libreadline-ruby
package. For Windows, you’ll have to find the libreadline DLL first (which I
guess you’ll find precompiled) and then get the ruby bindings (which I guess
you’ll have to compile). Can’t help you further as I’m not a Windows guy.

I will also take a look at your cliff module.

cliff depends on libreadline. If after getting libreadline you run into
troubles with cliff, feel free to contact me offlist, I’m all for making it
platform independent if it is not already.

Massimiliano

···

On Wed, Jul 17, 2002 at 02:27:22PM +0900, John wrote:

So, implement #method_missing that delegates to the actual method name
using regex as the mapper?

– Dossy

···

On 2002.07.14, John nojgoalbyspam@hotmail.com wrote:

In any case, what did you need this for?

I assume you mean having the class respond to methods that match a regexp?

So you can have a user input commands without having to type the whole
command. Also for having aliases for commands without having to write each
method to call the main method.

class foo
def /[ls|dir|directory]/
end
def /desc.*/
end
end

foo.ls
foo.dir
foo.directory

foo.desc
foo.describe

Personally I think its kinda neat. I love the power of regular expressions.


Dossy Shiobara mail: dossy@panoptic.com
Panoptic Computer Network web: http://www.panoptic.com/
“He realized the fastest way to change is to laugh at your own
folly – then you can let go and quickly move on.” (p. 70)