Otazník v identifikátorech?

14.08.09

To jsem zase na Twitteru něco napsal:

„Existuje nějaký rozumný důvod, proč většina (?) programovacích jazyků neumožňuje v identifikátorech funkcí/proměnných dávat otazník?“

~ Lukáš Havrlant, about 5 hours ago from TwitterFox

Výsledek? Mnoho strašně chaotických reakcí, na které už radši ani odkazovat nebudu, protože čert aby se v tom vyznal. Teď se trochu oklikou jdeme dostat k otazníkům v identifikátorech.

Kdo mě četl, ten už jazyk Scheme zná. Scheme je ve zkratce (ne čistě) funkcionální jazyk, která má docela zajímavé konvence pro identifikátory. Máte-li funkci, která vrací true/false, končí tento predikát otazníkem. Jako byste se ptali: platí tento výrok? Je toto číslo sudé? A tak ve Scheme naleznete predikáty jako even?, number? nebo list?. Je to těžce návykové a hezky čitelné. Kód pak čtete jako větu. (if (even? 5)). Krása, ne?

Scheme má i jiné hezké konvence jako vykřičník. Ten se dává na konec funkce v případě, kdy má funkce destruktivní účinky. Programujeme-li funkcionálně, píšeme obvykle programy jako matematické funkce, to jest zanořujeme do sebe funkce a výsledek jedné funkce je předán jako argument jiné funkci: f1(f2(f3(), f4())). To je dobrý systém, protože máte vše pod kontrolou a nestane se vám, že by nějaká funkce měnila něco někde úplně mimo prostředí funkce. Pro příklad: „funkcionální“ verze reverse (převrátí hodnoty v seznamu) by se chovala takto (použiji nějaký pseudojazyk):

Seznam = (1, 2, 3);
PrevracenySeznam = reverse(Seznam);

V Seznam by byl stále seznam (1, 2, 3) a v PrevracenySeznam by byl seznam (3, 2, 1). Destruktivní verze reverse by se chovala takhle:

Seznam = (1, 2, 3);
reverse(Seznam);

V Seznam by nyní bylo uloženo (3, 2, 1). Původní seznam jsme nenávratně ztratili. Rozdíl je jasný. No jo, ale jak teď rozlišit, kdy funkce pracuje destruktivně a kdy ne? Obvykle jde funkce naprogramovat oběma způsoby. Scheme má na to konvenci – pokud se funkce chová destruktivně, má na konci identifikátoru vykřičník. Stejně jako má predikát otazník. Takže funkcionální verze reverse by se jmenovala reverse, kdežto destruktivní reverse!. Rozdíl je opět vidět na první pohled. Pro příklad z jiných jazyků nemusíme chodit daleko. PHP asi skoro všichni čtenáři znají, takže co třeba tenhle případ:

$Array1 = array("red", "green", "blue", "yellow");
$Array2 = array("red", "green", "blue", "yellow");

array_splice($Array1, 2);
array_slice($Array2, 2);

var_dump($Array1);
var_dump($Array2);

Pro jistotu: Funkce array_splice odstraňuje vybrané prvky, array_slice extrahuje. array_splice tedy odstraní z pole vše od indexu 2 a dál, array_slice naopak zachová vše od indexu dva a dál. A teď otázka, především pro ty, kteří tyto funkce neznají podrobně. Co bude uloženo v proměnných $Array1 a $Array2? Změní některá funkce své předané argumenty? Pokud by zde existovala vykřičníková konvence jako ve Schemu, odpověď by byla jasná. Správná odpověď je, že funkce array_splice je destruktivní, zato array_slice ne. Dle Schemovské konvence by pak zápis funkce vypadal takto: array_splice!.

Poslední konvencí je konverze jednoho typu na druhý. To se neprovádí dvojkou, jako to člověk občas vidí jinde (html2pdf apod.), ale pomocí ->. Takže funkce na převod z desítkové do binární soustavy by se mohla jmenovat dec->bin.

Výborně, už známe konvence Scheme a zpět k mému twitu. Jak je vidět i na těchto příkladech, použité konvence se vztahují hlavně (jenom?) na názvy funkcí. Bohužel jsem nahoře napsal „v identifikátorech funkcí/proměnných“ a snad všichni reagující se chytili té proměnné, kterou jsem tam vlastně přidal do počtu (což nemohl nikdo vědět, že). Aneb když může být otazník ve funkci, proč ne třeba i v té proměnné. Prásk to za lomítko. A už to bylo v háji :-).

Takže abych to upřesnil. Nejde mi o otazníky v názvech proměnných, je pravda, že si nevzpomínám, jestli jsem je používal ve Scheme, asi spíš ne. Otázka měla znít, proč většina jazyků nedovoluje použít otazníky v názvech funkcí? V C# máme kupříkladu funkci TrueForAll, proč by se nemohla jmenovat TrueForAll?? Nebylo by to čitelnější?

Poznámka na konec: Nejde mi o naroubování této feature do současných jazyků, takže odpověď „není to možné kvůli kolizím s jinými prostředky jazyka“ není relevantní, pokud by se s tím počítalo od začátku (o což mi jde), nebyl by s tím problém. Navíc u funkcí by nejspíš kolize nenastala nikde.

Komentáře

  1. tiso · 14. srpen 2009, 17:12 · #

    Zaujímavé, to by sa hodilo… Vidno že niekto premýšľa nad tým, ako uľahčiť programátorom ži­vot.

    Miesto identifikator? sa bežne používa is_identifikator, has_identificator a podobne, čo je o pár znakov viac.

    Pri konverzii som skôr za 2-kové funkcie(dec2bin), aby sa to netĺklo s objektovým zápisom.

  2. Martin Malý · 14. srpen 2009, 20:11 · #

    To, co tu popisuješ, má třeba jazyk FORTH, kde otazník ve slově (ve FORTHu jsou všechno slova) znamená, že se jedná o nějakou „podmíněnou“ operaci. Ale ve FORTHu smí jméno slova (=defacto funkce) obsahovat opravdu cokoli kromě mezery. Takže v podstatě přesně to co píšeš. Ale zpět k otazníku: Je to dáno hlavně tím, že otazník je ve spoustě jazyků/prostředí „speciální znak“, takže jsou programátoři navyklí ho nepoužívat. V zásadě není nijaký důvod, proč by identifikátor např. v C nemohl obsahovat otazník – kromě toho zvyku a „pravidel“.

  3. Timy · 14. srpen 2009, 21:47 · #

    @Martin: OK, díky za objasnění.

    Ale ve FORTHu smí jméno slova (=defacto funkce) obsahovat opravdu cokoli kromě mezery.

    Scheme je na tomhle taky dobře, může toho obsahovat hodně: http://tinyurl.com/pgkj2h (a myslím, že ten výčet tam není přesný, můj kompilátor schroustal i trojtečku: …) Takže kód pak může vypadat třeba takhle :-) http://www.pastebin.cz/21804

  4. Vojtěch Šalbaba · 14. srpen 2009, 23:24 · #

    Myslim ze nejde o to ktery jazyk funkcionalitou oplyva nebo neoplyva, ale o to ze by oplyvat mely. Opravdu ocenuji kdyz kod jde cist jako basnicka, napriklad misto integer2string(22) psat 22.to_string, moci pouzivat ! dle libosti v nazvech funkci, moci pouzivat otazniky pro designaci funkcich vracejici (napriklad) pouze pravdivostni hodnoty, moci pretezovat funkce a tak dale, a tak dale.
    Uz jen takova drobnost jako opravdu se postarat o to aby se cely jazyk tvaril objektove, cili vyhnout se vecem jako length(„ahoj“) a misto nich pouzivat soustavne pouzivat „ahoj“.length dokazi opravdu hodne v pohodovosti psani.
    A neni to jen v designu jazyka, ale kdyz je jazyk dobre navrzeny, tak ze kod ktery dobre vypada zaroven nejspise i funguje, a uz jen z toho ze nekde neco na pohled nesedi svou prilisnou slozitosti jde videt ze tam se deje nejaka nekala cinost, programatori mene sahaji k hovadinam a vsichni muzou zit spokojenejsi zivot.

  5. pixy · 15. srpen 2009, 23:34 · #

    Není to prostě proto, že otazník je v mnoha jazycích operátorem? Nebudu nic nalhávat, já zas tak moc jazyků neznám, takže nevím, jak to chodí jinde – ale třeba v Javascriptu to neprojde prostě proto, že otazník za proměnnou je regulérní zápis (klasický ternární operátor), např. výraz x?0:1 A funkce/proměnné se tady moc nerozlišují…

  6. Timy · 16. srpen 2009, 11:03 · #

    Pixy, v poznámce na konec jsem psal, že mi nejde o okamžité naroubování této fíčury do současných jazyků. Spíš proč to někoho nenapadlo při návrhu těchto jazyků, pak by se daly takové kolize snadno vyřešit.

    Tu co zmiňuješ například nutností psát mezery kolem ternárního operátoru. Případně by musela probíhat složitější analýza konce proměnné. On ten příklad, který jsi napsal, je syntakticky jednoznačný, akorát parser se musí na tom otazníku zastavit a podívat se, jestli je dál dvojtečka nebo není. Nevím o kolik je to složitější na programování, psaní kompilátorů máme až za pár semestrů :-). Jednodušší by určitě bylo počítat s tím v návrhu jazyka a přidat například ty povinné mezery.

  7. tiso · 16. srpen 2009, 18:25 · #

    [6] tak to sa teším na tvoj parser *.phpi súborov do PHP (phpi = PHP Improved). V PHPI budeš používať takéto vylepšenia z iných jazykov, inak bude zhodné s PHP.

Pošli komentář

Komentáře jsou moderované. Každý komentář musí před publikováním autor Laboratoře schválit. Komentáře, které jistě nebudou zveřejněny: vulgární, vyvolávající flame, netýkající se tématu, komentáře psané bez diakritiky (háčky, čárky).

Komentáře jsou uzavřeny