From: Robert Klemme Date: 2010-10-28T19:36:35+09:00 Subject: Re: ctype functionality without a gem? On Thu, Oct 28, 2010 at 12:02 PM, Anton Bangratz wrote: > On 10/28/2010 11:16 AM, Ammar Ali wrote: >> On Thu, Oct 28, 2010 at 11:47 AM, Robert Klemme >> wrote: >>> On Thu, Oct 28, 2010 at 9:50 AM, Ammar Ali wrote: >>>> Is there a built-in method for identifying character types a la >>>> ctype() in C? I would like to avoid requiring a gem dependency. >> >>> What do you need that for?  Why not directly use a regexp to match a >>> string?  Often you can use capturing groups in a single regexp, e.g. >>> >>> irb(main):009:0> %w{foo bar 123}.each do |s| >>> irb(main):010:1* if /(\d+)|(\w+)/ =~ s >>> irb(main):011:2> puts "number" if $1 >>> irb(main):012:2> puts "chars" if $2 >>> irb(main):013:2> end >>> irb(main):014:1> end >>> chars >>> chars >>> number >>> => ["foo", "bar", "123"] >> >> That's very cool. I'll have to remember that one. > > It is a bit brittle, though. Watch: > >  %w{foo bar 123 345bar}.each do |s| >   if /(\d+)|(\w+)/ =~ s >     puts "number" if $1 >     puts "chars" if $2 >   end >  end > #=> > chars > chars > number > number Yes, of course. The regexp was a quick hack only to demonstrate the mechanism. You can easily fix that by proper anchoring the regexp. >> I do actually need to test if a character is of a certain type, all by >> itself, as part of a parser I'm working on. I came up with this quick >> solution for now, http://gist.github.com/650968 > > This is similarily fragile. If you are only testing for one character, > it seems good, if you are going to test for strings, it will not be > enough. > > Also, the whole solution is not necessarily fast - I do love regular > expressions, but I would search on for other methods to meet your > requirements. It really depends on what your goal is. If it is about > bit streams, you might want to look into bit-struct or similar > approaches that use Array#pack and String#unpack. If I have to implement a parser manually I would typically use regexp for scanning. You can even make this fairly readable by using /x. input.scan %r{ # white space (\s+) # integer ([-+]?\d+) # keyword: if (if) # etc }x do |m| ... end Of course, if the number of tokens is large this will become very awkward. Better use a proper parser generator then. Cheers robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/