From: Tim Hammerquist Date: 2002-05-20T08:48:44+09:00 Subject: Re: Ruby regex question Dossy graced us by uttering: > On 2002.05.19, Tim Hammerquist wrote: >> Basically, if the match fails, you don't have to check any values. > > Yikes. > > def foo(something) > something =~ /.../ > or_other = $1 > bar(or_other) > end > > def bar(or_other) > ... > end > > Are you saying that if you test the success or failure of the match in > foo(), that bar() doesn't need to test its inputs? No, I'm saying that foo() should check _its_ inputs, and bar() should check its inputs. Depending on foo() to check bar()'s input would be a violation of encapsulation, ne? And no. To clarify, I'm saying that if you check if the entire regex /(foo) (bar) (baz)/ matches against "foo bar bas", you don't have to check $1, $2, or $3. >> Most Perl code from gurus checks the match success immediately. >> >> Most Ruby idioms do the same. > > Really? In my experience, yes. > -r--r--r-- 1 root root 217854 Oct 5 2001 /usr/lib/perl5/5.6.1/CPAN.pm > > 3086 # read header > 3087 my($line_count,$last_updated); > 3088 while (@lines) { > 3089 my $shift = shift(@lines); > 3090 last if $shift =~ /^\s*$/; ^^^^^^^^^^^^^^^^^^^^^^^^^^ If $shift is all whitespace or empty, the entire loop is skipped. Success of the match is check directly _before_ acting upon it. > 3091 $shift =~ /^Line-Count:\s+(\d+)/ and $line_count = $1; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The binary operation 'and' checks the boolean status of the previous expression, in this case, a regex match. This is a variation of: if ($shift =~ /match/) { $line_count = $1; } Success of the match is checked before use of $1. > 3092 $shift =~ /^Last-Updated:\s+(.+)/ and $last_updated = $1; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Same here. Success of the match is checked before use of $1. > Maybe this portion of CPAN.pm wasn't written by a Perl guru. Andreas Koenig is a very capable Perl hacker, and a frequent poster to clpm. He also checks match success immediately in this excerpt. I fail to understand why you include it. > You are right though, that it is more common to find regex success > immediately with the regex evaluation. Perhaps it's because with > Perl, you can't know if $1 is valid (applies to the regex you just > evaluated) _unless_ you test if the regex succeeded, which _forces_ > you to test for the regex success. Ruby doesn't force you to do > this, so the only reason for it to be a Ruby idiom is because it's a > carry-over from Perl. (There are quite a few features of Ruby that were deliberately borrowed from Perl, but...) I only hope you don't place the success of the entire regex in the contents of $3 in the following match. "foo bar " =~ /(foo) (bar) (baz)?/ The result of the match is true (0, to be exact, but boolean true), but $3 is nil. (tested; 1.6.7) > In Ruby, which is more OO than Perl, I'd imagine that the idiom > would involve more decoupling between objects. The object receiving > the message should be responsible for determing the validity of its > inputs, not necessarily the sender. Granted. But _how_ you check the input has little to do with _where_ you check its input. > -- Dossy Tim Hammerquist -- "Sometimes these hairstyles are exaggerated beyond the laws of physics." -- Unknown narrator on Anime