Complex type-checking

I have a number of methods that can take arguments in two different
forms. As an example:

method(tuple [, …])

where ‘tuple’ can be things like (Point, Point, Integer) or (Numeric,
Numeric, Numeric, Numeric, Integer) (so either a Point object
representing the coordinates, or the coordinates directly).

I realise that type-checking in Ruby is anathematic to some, but I want
to generate some intelligent error messages in some cases. So please
let’s leave the ‘why do you want to do that’ bit alone for now. :slight_smile:

One meta-thought I had was for the argument vetter to be passed the
arglist and an array of allowed patterns, like

[
%r/^(?:(?:Point\s*){2}\sInteger)+$/,
%r/^(?:(?:Numeric\s
){4}\s*Integer)+$/
]

and check each tuple by doing kind_of?() of each element against the
appropriate words in the pattern.

Which is actually turning out to be a right bugger to code, actually.

So I’m figuring maybe someone could suggest a better method to me?

Thanks!

2010/2/22 Ken C. [email protected]:

to generate some intelligent error messages in some cases. So please
let’s leave the ‘why do you want to do that’ bit alone for now. :slight_smile:

Sorry, I can’t. Why do you want to do that? :slight_smile:

Which is actually turning out to be a right bugger to code, actually.

Is it?

def pattern_check(args, pattern)
m = pattern.match(args.map{|x|x.class}.join(’ '))

if m
m.to_a.each_with_index do |m,i|
return i if i > 0 && m
end
end

raise ArgumentError, args.inspect
end

def m(*a)
case pattern_check(a, %r{\A(?:(String String)|(Fixnum))\z})
when 1
printf “Two strings: %p\n”, a
when 2
printf “A number: %p\n”, a
else
raise ArgumentError, a.inspect
end
end

Method m does look ugly though.

So I’m figuring maybe someone could suggest a better method to me?

Provide different methods for different arguments.

Kind regards

robert

Robert K. wrote:

So please
let’s leave the ‘why do you want to do that’ bit alone for now. :slight_smile:

Sorry, I can’t. Why do you want to do that? :slight_smile:

:slight_smile:

Which is actually turning out to be a right bugger to code, actually.

Is it?

Well, it seems to be…

The thing is, the Point class match works all right – but when
specified as individual coordinates, they can be integers (potentially
bignums) or floats – so checking the actual coordinates is not as
simple as matching the class. I could do a (Fixnum|Float|…)
alternation, I suppose, but that doesn’t extend to cases in which
someone might be using a custom class extending one of those. Which is
actually probably a bit unlikely, so maybe I’ll just rule that
possibility out. :slight_smile:

def pattern_check(args, pattern)
m = pattern.match(args.map{|x|x.class}.join(’ '))

if m
m.to_a.each_with_index do |m,i|
return i if i > 0 && m
end
end

raise ArgumentError, args.inspect
end

def m(*a)
case pattern_check(a, %r{\A(?:(String String)|(Fixnum))\z})
when 1
printf “Two strings: %p\n”, a
when 2
printf “A number: %p\n”, a
else
raise ArgumentError, a.inspect
end
end

Method m does look ugly though.

Consider also that the argument list may include more than one tuple…

This has given me some ideas, though. Thanks!

#ken B-)}

Thomas S. wrote:

Let the error happen then wrap the call in a begin/rescue clause and
give more intelligent error messages based on the return error.

… which would require lots of extra code to account for all
possibilities. Better to vet the arguments to begin with rather than to
try to recover when they fail somewhere farther down the code, IMHO.

On Feb 21, 10:43 pm, Ken C. [email protected]
wrote:

to generate some intelligent error messages in some cases. So please
let’s leave the ‘why do you want to do that’ bit alone for now. :slight_smile:

Let the error happen then wrap the call in a begin/rescue clause and
give more intelligent error messages based on the return error.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs