Ruby方法名简写的trick……(外加方法名缩写的trick)

刚才跟NS老兄聊的时候他给我看了段代码:
night_stalker 写道
看到一个方法简写 trick
irb(main):004:0> "Hello World".spl
=> ["Hello", "World"]
irb(main):005:0> "Hi there Daniel".sp
=> ["Hi", "there", "Daniel"]
irb(main):006:0> "Hi there Daniel".s
=> "Ambigous abbreviation s ->  select, slice, sub!, squeeze, send, split,
size, strip, succ!, squeeze!, sub, slice!, scan, sort, swapcase, swapcase!,
sum, singleton_methods, succ, sort_by, strip!"


我正无聊,回答说这实现起来不难,就模仿那段代码的行为估摸了一个出来。不过这么简单的东西我一开始居然写错了,郁闷 T T
class Object
  def method_missing(name, *args, &block)
    candidates = methods.grep /^#{name}/
    raise "undefined method `#{name}' for #{self}:#{self.class}" if candidates.empty?
    raise "Ambigous abbreviation #{name} -> #{candidates.join ', '}" unless candidates.one?
    method(candidates.first).call *args
  end
end

一开始忘写method,直接拿candidates.first[*args]就调用了……找起错来还挺麻烦的 T T

另外,还可以尝试匹配下划线分隔的名字中的缩写,像是把end_with?缩写成ew。在Ruby 1.9上可以这样写:
class Object
  def method_missing(name, *args, &block)
    candidates = methods.grep /^#{name}/
    if candidates.empty?
      downcase_name = name.to_s.downcase
      candidates = methods.map{|m| m.downcase}.reject{|m| m[0] != name[0]}.select do |m|
        downcase_name == m.to_s.sub(/[?!=]$/, '').split(/_/).map{|p| p[0]}.join
      end
    end
    raise "undefined method `#{name}' for #{self}:#{self.class}" if candidates.empty?
    raise "Ambigous abbreviation #{name} -> #{candidates.join ', '}" unless candidates.one?
    method(candidates.first).call *args
  end
end

主要是Ruby 1.9之前String#[]返回的是字节的值,是个Fixnum,要转成字符还得用Fixnum#chr,比较烦……要在Ruby 1.8上运行这代码的话,要在[0]后面都加上.chr。

E:\build_area\ruby191\bin>irb
irb(main):001:0> class Object
irb(main):002:1>   def method_missing(name, *args, &block)
irb(main):003:2>     candidates = methods.grep /^#{name}/
irb(main):004:2>     if candidates.empty?
irb(main):005:3>       candidates = methods.select do |m|
irb(main):006:4*         name.to_s.downcase == m.to_s.sub(/[?!=]$/, '').split(/_/).map {|p| p[0]}.join.downcase
irb(main):007:4>       end
irb(main):008:3>     end
irb(main):009:2>     raise "undefined method `#{name}' for #{self}:#{self.class}" if candidates.empty?
irb(main):010:2>     raise "Ambigous abbreviation #{name} -> #{candidates.join ', '}" unless candidates.one?
irb(main):011:2>     method(candidates.first).call *args
irb(main):012:2>   end
irb(main):013:1> end
=> nil
irb(main):014:0> 'alpha'.ew 'a'
=> true
irb(main):015:0> 'alpha'.end_with? 'a'
=> true


结束语:人不能太无聊了 XDD

你可能感兴趣的:(编程,windows,Ruby)