Operátory nejsou (vždy) funkce

Začalo to zcela nenápadnou poznámkou pod čarou v Real world Haskell, že OR operátor (||) je v Haskellu definován jako běžná funkce a zároveň zkratuje (short circuit - první nalezený true ukončí vyhodnocování). Proč někdo považuje za důležité tak běžný fakt explicitně rozebírat mi začalo vrtat hlavou a na konci vedlo k odhalení jedné fundamentální neznalosti.

Nejdřív k tomu, proč mi to připadalo naprosto samozřejmé:

  1. Vždycky jsem si myslel, že operátory jsou de-facto pouze divné funkce. Mohou mít sice infixovou notaci, speciální asociativitu a jiné blbosti, ale v principu je vždy možné sestrojit a použít místo nich běžné funkce. Pro tuhle redundantnost jsem se nikdy moc nezabýval podrobnostmi jejich implementace v jazycích, které to dovolují a proto jsem tak dlouho nezaregistroval svůj omyl.

  2. Zkratování logických operátorů je výchozí chování ve všech jazycích, které znám, protože je výhodnější hned z několika důvodů a proto nemá smysl to dělat opačně.

Po chvilce přemýšlení jsem si ale uvědomil, že syntéza těchto dvou předpokladů je překvapivě netriviální. Z principu modelu vyhodnocení “call-by-value” totiž vyplývá, že před voláním funkce dojde k vyhodnocení všech výrazů, které produkují hodnoty vstupující do funkce a funkcí proto není možné simulovat zkratové chování operátoru!

Samozřejmě to lze simulovat funkcemi vyšších řádů, ale to už je spíše inženýrské řešení. Hlavní zjištění je, že operátory v jazyce mají daleko užší vztah se samotným modelem vyhodnocování daného jazyka (v případě lambda kalkulu konkrétně se specifiky provádění redukčních operací) a proto je informace, která upoutala mojí pozornost na začátku, jednak nesamozřejmá a jednak má zpětně dalekosáhlý význam pro pochopení jazyka jako takového.