Complex type-checking

Discussion in 'Ruby' started by Ken Coar, Feb 22, 2010.

  1. Ken Coar

    Ken Coar Guest

    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. :)

    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}\s*Integer)+$/,
    %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!
    --
    Posted via http://www.ruby-forum.com/.
    Ken Coar, Feb 22, 2010
    #1
    1. Advertising

  2. 2010/2/22 Ken Coar <>:
    > I have a number of methods that can take arguments in two different
    > forms. =A0As 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. =A0So please
    > let's leave the 'why do you want to do that' bit alone for now. :)


    Sorry, I can't. Why do you want to do that? :)

    > One meta-thought I had was for the argument vetter to be passed the
    > arglist and an array of allowed patterns, like
    >
    > [
    > =A0%r/^(?:(?:point\s*){2}\s*Integer)+$/,
    > =A0%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.


    Is it?

    def pattern_check(args, pattern)
    m =3D 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


    --=20
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
    Robert Klemme, Feb 22, 2010
    #2
    1. Advertising

  3. Ken Coar

    Ken Coar Guest

    Robert Klemme wrote:
    >
    >> So please
    >> let's leave the 'why do you want to do that' bit alone for now. :)

    >
    > Sorry, I can't. Why do you want to do that? :)


    :)

    >> 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. :)

    > 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-)}
    --
    Posted via http://www.ruby-forum.com/.
    Ken Coar, Feb 22, 2010
    #3
  4. Ken Coar

    Intransition Guest

    On Feb 21, 10:43=A0pm, Ken Coar <>
    wrote:
    > I have a number of methods that can take arguments in two different
    > forms. =A0As 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. =A0So please
    > let's leave the 'why do you want to do that' bit alone for now. :)


    Let the error happen then wrap the call in a begin/rescue clause and
    give more intelligent error messages based on the return error.
    Intransition, Feb 22, 2010
    #4
  5. Ken Coar

    Ken Coar Guest

    Thomas Sawyer 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.
    --
    Posted via http://www.ruby-forum.com/.
    Ken Coar, Feb 22, 2010
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. news.amnet.net.au
    Replies:
    1
    Views:
    569
    =?UTF-8?b?TMSByrtpZSBUZWNoaWU=?=
    Apr 13, 2004
  2. Ulf Heyder
    Replies:
    1
    Views:
    489
    Patrick TJ McPhee
    Oct 28, 2003
  3. Chishun Kwong
    Replies:
    0
    Views:
    415
    Chishun Kwong
    Mar 3, 2005
  4. Stanimir Stamenkov
    Replies:
    2
    Views:
    739
    Stanimir Stamenkov
    Oct 25, 2005
  5. Robert Mark Bram
    Replies:
    0
    Views:
    678
    Robert Mark Bram
    Feb 4, 2007
Loading...

Share This Page