Prev: extending a core class cleanly
Next: [ANN] RubyInstaller: 1.8.7-p299, 1.9.1-p429 and 1.9.2-rc1 installersand packages released
From: Intransition on 5 Jul 2010 19:29 I have a registry (array) of CLI classes. Each class has a class method cli() that returns an array of strings or regular expressions to match against ARGV to see if it is the chosen cli. Eg. class FooList << CLIBase def self.cli ; ['foo', 'list'] ; end ... end So if someone puts on the command line: $ foo list Then the above class would match for it. I wrote the algorithm to handle this, but I think it's Ugh-ly. Wondering if the smart folk here might play a game of golf on it. def command(argv) lookup = registry.map{ |cc| [cc, cc.cli] }.sort{ |a,b| b[1].size <=> a[1].size } x = lookup.find do |cc, cli| t = true cli.each_with_index do |r, i| t = t && (r === argv[i]) end t end cmdc = x[0] argv = argv[x[1].size..-1] return cmdc, argv end
From: Joel VanderWerf on 6 Jul 2010 00:46 Intransition wrote: > def command(argv) > lookup = registry.map{ |cc| [cc, cc.cli] }.sort{ |a,b| b[1].size > <=> a[1].size } > x = lookup.find do |cc, cli| > t = true > cli.each_with_index do |r, i| > t = t && (r === argv[i]) > end > t > end > cmdc = x[0] > argv = argv[x[1].size..-1] > return cmdc, argv > end Untested: def command(argv) lookup = registry.sort_by {|cc| cc.cli.size} cmdc = lookup.find do |cc| cc.cli.zip(argv).all? do |r,arg| r === arg end end return cmdc, argv[cmdc.cli.size..-1] end The following (assuming it works!) would be more compact still: class Symbol alias old_to_proc to_proc def to_proc case self when :=== # etc. proc {|x,y| x === y} else old_to_proc end end end def command(argv) lookup = registry.sort_by {|cc| cc.cli.size} cmdc = lookup.find do |cc| cc.cli.zip(argv).all?(&:===) end return cmdc, argv[cmdc.cli.size..-1] end
From: Martin DeMello on 6 Jul 2010 07:24 On Tue, Jul 6, 2010 at 4:59 AM, Intransition <transfire(a)gmail.com> wrote: > > def command(argv) > lookup = registry.map{ |cc| [cc, cc.cli] }.sort{ |a,b| b[1].size > <=> a[1].size } at the least this should be registry.map {|cc| [cc, cc.cli]}.sort_by {|a| -a[1].size} also, you're never using cc, so why carry it around? lookup = registry.map {|cc| cc.cli}.sort_by {|cli| -cli.size} and using the ever-handy symbol.to_proc lookup = registry.map(&:cli).sort_by(&:size).reverse > x = lookup.find do |cc, cli| > t = true > cli.each_with_index do |r, i| > t = t && (r === argv[i]) > end > t > end # untested lookup.find do |cli| cli.zip(argv).inject(true) {|e, (i, j)| e && (i === j)} end > cmdc = x[0] > argv = argv[x[1].size..-1] > return cmdc, argv > end martin
From: Intransition on 12 Jul 2010 20:49 Thanks Joel and Martin. Amazingly concise answers -- it's amazes me sometimes how small a piece of code can get in Ruby :-) I haven't gotten back to the particular code I need this for yet which is why I haven't responded until now, but should be back to it soon and I'll let you know how it worked out.
From: w_a_x_man on 12 Jul 2010 23:20
On Jul 6, 6:24 am, Martin DeMello <martindeme...(a)gmail.com> wrote: > On Tue, Jul 6, 2010 at 4:59 AM, Intransition <transf...(a)gmail.com> wrote: > > > def command(argv) > > lookup = registry.map{ |cc| [cc, cc.cli] }.sort{ |a,b| b[1].size > > <=> a[1].size } > > at the least this should be registry.map {|cc| [cc, cc.cli]}.sort_by > {|a| -a[1].size} > > also, you're never using cc, so why carry it around? > > lookup = registry.map {|cc| cc.cli}.sort_by {|cli| -cli.size} > > and using the ever-handy symbol.to_proc > > lookup = registry.map(&:cli).sort_by(&:size).reverse > > > x = lookup.find do |cc, cli| > > t = true > > cli.each_with_index do |r, i| > > t = t && (r === argv[i]) > > end > > t > > end > > # untested > lookup.find do |cli| > cli.zip(argv).inject(true) {|e, (i, j)| e && (i === j)} > end lookup.find{|cli| cli == argv[0,cli.size] } > > > cmdc = x[0] > > argv = argv[x[1].size..-1] > > return cmdc, argv > > end > > martin |