On Fri, 19 Jan 2007 22:45:05 +0900, Ruby Quiz wrote:
> The three rules of Ruby Quiz:
>
> 1. Please do not post any solutions or spoiler discussion for this quiz until
> 48 hours have passed from the time on this message.
>
> 2. Support Ruby Quiz by submitting ideas as often as you can:
>
> http://www.rubyquiz.com/
>
> 3. Enjoy!
>
> Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone
> on Ruby Talk follow the discussion. Please reply to the original quiz message,
> if you can.
>
> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>
> by Robert Dober
>
> Command Line Interfaces very often support command abbreviations The purpose of
> this quiz is to automatically dispatch to methods on unambiguous abbreviations,
> ask the user for clarification in case of ambiguous abbreviations and raise a
> NoMethodError in case of an abbreviation that cannot be matched to any command.
>
> Behavior of other methods defined in a class shall not be altered.
>
> Be creative about the interface and about behavior. I have OTOH defined a small
> test suite that makes assumptions about the interface and behavior. But the test
> suite is only there for your convenience.
>
> What is said below applies to the test suite and shall in no way inhibit any
> alternative ideas.
>
> class Mine
> abbrev :step, :next, :stop
> abbrev :exit
> end
>
> Mine.new.e # should resolve to exit
> Mine.new.st # should prompt the user
> Mine.new.a # should still raise a NoMethodError
>
> Abbreviation targets themselves are not expanded.
>
> class Nine
> abbrev :hash
> abbrev :has
> end
>
> Nine.new.ha # => [:hash, :has]
> Nine.new.has # => NoMethodError
>
> class Nine
> def has; 42; end
> end
> Nine.new.has # => 42
>
> In order to allow for automated testing the test code shall not prompt the user
> in case of an ambiguous abbreviation but return an array containing all (and
> only all) possible completions as symbols. Note that the test suite sets the
> global variable $TESTING to a true value for your convenience.
>
> http://rubyquiz.com/test-abbrev.rb
Returning an array when the answer is ambiguous is a very bad way to do
this. Instead, I throw an exception (you can get the candidates from the
#candidates attribute of the exception).
I also saw no reason to specifically name the methods that get abbreviated
-- rather, abbreviation works on all methods in the object and its super
classes.
require 'abbrev'
class AmbiguousExpansionError < StandardError
attr_accessor :candidates
def initialize(name,possible_methods)
super("Ambiguous abbreviaton: #{name}\n"+
"Candidates: #{possible_methods.join(", ")}")
@candidates=possible_methods
end
end
module Abbreviator
def method_missing name,*args
abbrevs=methods.abbrev
return send(abbrevs[name.to_s],*args) if abbrevs[name.to_s]
meths=abbrevs.reject{|key,value| key!~/^#{name}/}.values.uniq
raise AmbiguousExpansionError.new(name, meths) if meths.length>1
return super(name,*args)
end
end
--
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/