0xDEADBEEF

[RSS]
««« »»»

Java, Scala a regulární výrazy

26. 11. 2017

Po­slední dobou zjiš­ťuji, že práce s re­gu­lár­ními výrazy v Javě a Scale je ne­u­spo­ko­jivá, ma­toucí a API nikdy ne­na­bízí přesně to, co bych chtěl.

Scala má krásně vy­pa­da­jící metodu Regex#replaceAllIn(String, Match => String). Na první pohled je všechno jasné: Každý výskyt re­gu­lár­ního výrazu v prvním ar­gu­mentu je předán funkci Match => String. Objekt typu Match re­pre­zen­tuje výskyt vzoru. Funkce ho vezme jako ar­gu­ment a vy­pro­du­kuje string, který ho na­hradí. Co by na tom mohlo být kom­pli­ko­va­ného, žeano?

Jed­no­du­ché volání, které na první pohled vypadá jako iden­tita, není bez­pečné:

regex.replaceAllIn(str, (m: Match) => m.group(0))

m.group(0) před­sta­vuje celou shodu (ostatní indexy jsou uzá­vor­ko­vané výrazy v regexu, m.group(1) jsou první zá­vorky, m.group("named") jsou zá­vorky po­jme­no­vané named) .

V čem je pro­blém?

V tom, že vý­sle­dek funkce se ne­po­u­žije ver­ba­tim pro na­hra­zení, ale je in­ter­pre­to­ván. Každý výskyt ře­tězců $0$9 je in­ter­pre­to­ván jako pod­vý­raz a \$ zna­mená li­te­rál $. Když vstupní data ob­sa­hují dolar ná­sle­do­vaný číslem, skončí to při­nej­lep­ším vý­jim­kou, při­nej­hor­ším to udělá něco ne­če­ka­ného. A to není to, co by člověk čekal nebo chtěl. V do­ku­men­taci je toto cho­vání dobře po­psané, ale ne­pů­sobí to, že by to tak mělo být.

Ko­rektní verze by měla vy­pa­dat takhle:

regex.replaceAllIn(str, (m: Match) => Regex.quoteReplacement(m.group(0)))

In­ter­pre­tace stringu je pře­ži­tek star­ších API, které ne­na­bí­zely na­hra­zení přes fukci:

regex.replaceAllIn(str, replace: String)

V tomto pří­padě nemůžu spe­ci­fi­ko­vat logiku, která vy­po­čítá na­hra­zo­vací string a proto jsou po­u­žity zpětné re­fe­rence jako $0$9. Ty po­sky­tují aspoň ně­ja­kou ru­di­men­tární fle­xi­bi­litu.

Pro­blém je v tom, že vý­sledný string musí být es­ca­po­ván a hned potom je in­ter­pre­to­ván (pro $\$), což je zby­tečná práce, která stojí zby­tečný čas.1

Ocenil bych jasné API s me­to­dami jako

které jasně říkají, co dělají a uži­va­tel si může vybrat přesně to cho­vání, které po­tře­buje.


  1. Do­da­tek: I když má quoteReplacement mě­ři­tel­nou režii, je téměř za­ne­dba­telná. Im­ple­men­tace počítá s tím, že v na­prosté vět­šině pří­padů nebude třeba nic es­ca­po­vat.
píše k47 (@kaja47, k47)