2008.11.01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

MHI 5.0

この「にっき」には暴力シーンやグロテスクな表現が含まれています。

(2008.11.01)

$ [Python][Perl] Python の暗黒面以前に、正規表現のoオプションがなくて絶望した!

ブクマにも書いたんですが、普通に考えたら変数の評価を2回目以降しないようにするから速くなるわけで、当然の話のような…。期待のような動きをするなら o オプションなんていうオプションはそもそも要らないのではないでしょうか。

(追記)
その批判的なブクマに★をくれた筆者のid:hakobe932氏は男前だと思った

Perl の動きを Python でエミュレートしてみましょう。

import re

_pattern_cache = None
def match(pattern,text):
    global _pattern_cache
    if _pattern_cache is None:
        # print "(comment) compliled!"
        _pattern_cache = re.compile("^%s$" % pattern )
    return _pattern_cache.search(text)

for text in "vim","vim","vim","vim","vim":
    if match("vim",text):
        print "match: vim"
    else:
        print "not match: vim"

for text in "emacs","emacs","emacs","emacs","emacs":
    if match("emacs",text):
        print "match: emacs"
    else:
        print "not match: emacs"

これは

match: vim
match: vim
match: vim
match: vim
match: vim
not match: emacs
not match: emacs
not match: emacs
not match: emacs
not match: emacs

こうなります。本当はこう動いて欲しいという結果である:

match: vim
match: vim
match: vim
match: vim
match: vim
match: emacs
match: emacs
match: emacs
match: emacs
match: emacs

を得たいのであれば、match関数の部分を

_pattern_cache = (None,None)
def match(pattern,text):
    global _pattern_cache
    if _pattern_cache[0] != pattern:
        # print "(comment) compliled!"
        _pattern_cache = (pattern,re.compile("^%s$" % pattern ) )
    return _pattern_cache[1].search(text)

と修正する必要があります。 要は「初回であればコンパイルする」というコードを 「前回と異なっていたらコンパイルする」と改めるわけです。

でも、それは 「oオプションを使うと,その正規表現のコンパイルが1回しか行われなくなります」 という仕様と明らかに異なります。さすがに、これを

Perlの闇は深すぎて,油断するとすぐに真っ黒に染められてしまうので, 全力で取り扱い注意ということですね

というのは言い過ぎではないでしょうか?

.net(3) C++(3) Cygwin(12) GAME(3) Groovy(1) Linux(2) Lua(39) Mercurial(13) NYAOS(92) OS/2(7) Oracle(3) Perl(4) Python(22) SKK(4) Windows8(1) album(68) ckw(10) coLinux(1) vim(6) wifky(27) 書評(21) (9)

zetamattaのたいじゅー