method_missing crazyness

L

leon breedt

Hi,

Any reason why syntax like this:

def prefix_/(a-zA-Z0-9_)/(suffix, *args)
do something with suffix
end

Would be worse than doing manual dispatching in method_missing?

Seems like it could be a nifty hack at first glance, makes dynamic
methods slightly more explicit (and a bit more intellisense friendly).
#respond_to? could be automatically taught this as well, no?

Leon
 
A

Austin Ziegler

Any reason why syntax like this:
def prefix_/(a-zA-Z0-9_)/(suffix, *args)
do something with suffix
end
Would be worse than doing manual dispatching in method_missing?
=20
Seems like it could be a nifty hack at first glance, makes dynamic
methods slightly more explicit (and a bit more intellisense
friendly). #respond_to? could be automatically taught this as
well, no?

Well, it's a neat idea, but from my perspective:

1. It's uglier than sin. Strictly speaking, you would want something
like:

def %r{prefix_([A-Za-z0-9_]+)}(method_match, *args)
...
end

2. This would have very limited utility. #method_missing can be used
to perform automatic delegation, e.g.:

def method_missing(meth, *args)
@my_array.__send__(meth, *args)
end

This would be useful only in the case where there are known sets
of responses that are similar.

-austin
--=20
Austin Ziegler * (e-mail address removed)
* Alternate: (e-mail address removed)
 
G

gabriele renzi

leon breedt ha scritto:
Hi,

Any reason why syntax like this:

def prefix_/(a-zA-Z0-9_)/(suffix, *args)
do something with suffix
end

Would be worse than doing manual dispatching in method_missing?

Seems like it could be a nifty hack at first glance, makes dynamic
methods slightly more explicit (and a bit more intellisense friendly).
#respond_to? could be automatically taught this as well, no?

IMO, it would be cool to have multiple dispatch based on ===, so that
you could write

def m(s)
:default
end

def m(/:alpha:/ s)
:alphabetic
end

it would be nice even because all methods such as
def m(x)
conditional branch
other branch
other branch
end

could be splitted in many different cases.
Just think of what ActiveRecord::Base#find does to get why this would be
nice ;)
 
J

Jeffrey Moss

Multimethods with optional typed argument lists would be totally awesome. It
wouldn't break backward compatibility either. Wasn't that the most popular
requested feature for ruby 2?

As for the method_missing trick, I think it is too much of a special case,
because what if you want to use a custom prefix instead? It would have to
work out like this instead:

def prefix_/(a-zA-Z0-9_)/(*args)
do something with $1
end

This is one of those eye candy things that doesn't expand usability much. I
would continue using method_missing, personally, because I feel like its
more organized.

-Jeff

----- Original Message -----
From: "gabriele renzi" <[email protected]>
Newsgroups: comp.lang.ruby
To: "ruby-talk ML" <[email protected]>
Sent: Thursday, July 28, 2005 9:51 AM
Subject: Re: method_missing crazyness
 
D

Dave Fayram

Multimethods with optional typed argument lists would be totally awesome.= It
wouldn't break backward compatibility either. Wasn't that the most popula= r
requested feature for ruby 2?

Aren't these against the spirit of duck typing, though? I thought that
Ruby was moving away from needing type-checking dispatch rather than
towards needing it.

The only time I've ever needed it is when I was doing some heavy math
code. When your set of types is small and well known, it is much more
elegant than loading up on the to_somethings or making a kind_of? if
statement clause.
=20
As for the method_missing trick, I think it is too much of a special case= ,
because what if you want to use a custom prefix instead?

I would venture to say special prefixes or suffixes are actually the
common case.

--=20
--=20
Dave Fayram (II)
(e-mail address removed)
 
A

Austin Ziegler

I would venture to say special prefixes or suffixes are actually the
common case.

Not in my experience. I've worked with a lot of stuff, but I mostly
use #method_missing for delegation. If I'm using special prefixes and
suffixes, it's usually a plugin method.

-austin
--=20
Austin Ziegler * (e-mail address removed)
* Alternate: (e-mail address removed)
 
J

Jeffrey Moss

I think optional type checking, key word being optional, would actually
compliment the duck typing, the method with no type(s) in the argument list
would become the default. Adding a type would only make it more specific, a
shortcutted form of "return custom_string_method if param.is_a?(String)".
It would come in handy more in the complex class structures than the simple
"method_missing" case. In the case of the complex class structure, instead
of being a substitute for the switch or conditional statement in
method_missing, it would be a substitute for this:

def custom_string_method(obj)
# do custom stuff on a string
end

def custom_method(obj)
next_method_name = "custom_#{obj.class.to_s.downcase}_method"
if self.respond_to?(next_method_name)
return self.send(next_method_name, obj)
end
# do default custom stuff
end

Which would allow you to override methods for certain objects without
overriding custom_method and adding new conditionals. If you weren't using
method overrides, it would only be syntactical sugar, but in this case it
actually cleans up the app a bit to say:

def custom_method(String obj)
# do custom stuff on a string
end

def custom_method(obj)
# do default custom stuff
end

-Jeff

----- Original Message -----
From: "Dave Fayram" <[email protected]>
To: "ruby-talk ML" <[email protected]>
Sent: Thursday, July 28, 2005 12:16 PM
Subject: Re: method_missing crazyness


Multimethods with optional typed argument lists would be totally awesome.
It
wouldn't break backward compatibility either. Wasn't that the most popular
requested feature for ruby 2?

Aren't these against the spirit of duck typing, though? I thought that
Ruby was moving away from needing type-checking dispatch rather than
towards needing it.

The only time I've ever needed it is when I was doing some heavy math
code. When your set of types is small and well known, it is much more
elegant than loading up on the to_somethings or making a kind_of? if
statement clause.
As for the method_missing trick, I think it is too much of a special case,
because what if you want to use a custom prefix instead?

I would venture to say special prefixes or suffixes are actually the
common case.
 
G

gabriele renzi

Dave Fayram ha scritto:

# Beware: just mumbling aloud, I understand that probably there is a
# huge number of corner cases to consider wrt multimethods
Aren't these against the spirit of duck typing, though? I thought that
Ruby was moving away from needing type-checking dispatch rather than
towards needing it.

I don't really think duck typing and multiple dispatch are in the same pot.
What I think (but notice I am usually dumb) is that the former is about
doing something relying on property of a parameter (i.e. it responds to
#meth and takes 4 arguments).
The latter is just a better way, imho, to organize code and avoid things
such as #coerce, the visitor pattern or things like:

def find(*args)
options = extract_options_from_args!(args)

case args.first
when :first
find:)all, options.merge(options[:include] ? { } : { :limit
=> 1 })).first
when :all
options[:include] ? find_with_associations(options) :
find_by_sql(construct_finder_sql(options))
else
return args.first if args.first.kind_of?(Array) &&
args.first.empty?
expects_array = args.first.kind_of?(Array)

conditions = " AND #{sanitize_sql(options[:conditions])}"
if options[:conditions]

ids = args.flatten.compact.uniq
case ids.size
when 0
raise RecordNotFound, "Couldn't find #{name} without an
ID#{conditions}"
when 1
if result = find:)first, options.merge({ :conditions =>
"#{table_name}.#{primary_key} = #{sanitize(ids.first)}#{conditions}" }))
return expects_array ? [ result ] : result
else
raise RecordNotFound, "Couldn't find #{name} with
ID=#{ids.first}#{conditions}"
end
else
# Find multiple ids
ids_list = ids.map { |id| sanitize(id) }.join(',')
result = find:)all, options.merge({ :conditions =>
"#{table_name}.#{primary_key} IN (#{ids_list})#{conditions}"}))
if result.size == ids.size
return result
else
raise RecordNotFound, "Couldn't find all
#{name.pluralize} with IDs (#{ids_list})#{conditions}"
end
end
end
end


Say, how do you add a :last option?
you could subclass, or alias/redefine/call-redefined-method.

If we had multiple dispatch (say, based on ===) you could just write

def find:)last l)
bla bla
end

I understand that there is some overlap with type cheking, but it is not
the only thing.
Probably, if you just add a rule such as "in absence of a specific
method, call the first that was defined", you would get back duck typing
just as it is now (i.e. it could fail or work)



The only time I've ever needed it is when I was doing some heavy math
code. When your set of types is small and well known, it is much more
elegant than loading up on the to_somethings or making a kind_of? if
statement clause.

I often found I could have used it, but maybe I'm just short sighted.
OTOH I wonder if we don't generally feel the need for this *because* we
don't have it, I never realized how much useful an anonymous function
could have been before I learned ruby.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,792
Messages
2,569,639
Members
45,353
Latest member
RogerDoger

Latest Threads

Top