přihlásit se
k47.cz
Už deset let na vašich monitorech.

Scala - String interpolation

autor: kaja47 - CC by-nc-sa - publikováno: - sekce obsah » programování #2395
štítky: a

String interpolation (SIP-11) je jedna z mnoha novinek jazyka Scala plánovaných pro verzi 2.10. Je to vlastnost typická pro dynamické jazyky, kdy můžete přímo do stringového literálu uvést proměnné, které jsou následně interpolovány, ale v podání Scaly je maximálně zobecněná, aby dala programátorům co největší moc.

String interpolation si můžete vyzkoušet už teď, když si stáhnete nejnovější nightly build a použijete přepínač -Xexperimental.

Ve Scale se (stejně jako v Javě) stringy spojují pomocí operátoru +. Konvence Scaly je kolem plusů nedělat mezery.

"Bob is "+n+" years old"

To všechno funguje, ale když spojujete fůru stringů, začne být situace velice nepřehledná + může být celkem těžké v tom zmatku správně napsat mezery, uvozovky nebo závorky.

SIP-11 zavádí novou syntax pro tzv. processed string:

s"Bob is $n years old"
  • s na začátku oznamuje, že se jedná o interpolova­ný string
  • $ uvozuje jméno proměnné

Funguje to i pro víceřádkové stringy:

s"""
  Bob
  is
  $n
  years
  old
"""

Ve složených závorkách můžeme uvést libovolný výraz:

s"Bob is ${bob.years} years old"

Obsah ve složených závorkách spadá do syntaktické kategorie BlockExpr, takže tam může být skutečně cokoli. Klidně můžete dovnitř stringu schovat celý váš program.

s"""Move along. There's nothing to see. ${ class MyHiddenClass() } Did you see something? I don't think so!"""

Ale však to znáte: proto, že můžete neznamená, že byste měli.

Další typ řetězce je formátovaný string uvozený f, ve kterém můžete za proměnnou/výrazem specifikovat formát používaný v printf. Proměnná se pak vypíše v uvedeném formátu.

val c = 7
f"His codename is $c%03d" // proměnná $c, formátovací string: %03d, vrátí: "His codename is 007"
f"His codename is ${secretAgent.codename}%03d"

Skutečná síla se ale skrývá v tom, jak se interpolované stringy překládají. Nejjednodušší by bylo prostě mít jednu nebo dvě nové formy syntaxe, které se přímo přeloží na string (jak je běžné v dynamických jazycích), ale to by nebylo příliš flexibilní.

String s"Bob is ${bob.years} years old" se přeloží jako:

StringContext("Bob is ", " years old").s(bob.years)

Všechny konstantní části stringu jsou předány objektu StringContext, identifikátor stringu s je pak jenom obyčejná metoda, které jsou všechny interpolované proměnné předány jako vararg. Pokud tedy chcete vlastní druh stringu, stačí vytvořit vlastní StringContext, který má požadované metody a implicitní konverzi, která zkonvertuje základní StringContext na ten váš.

A aby to byl ještě o něco mocnější nástroj, můžeme na interpolovaných řetězcích dělat patter matching. Musíte mít StringContext, jehož metoda id vrátí objekt, který funguje jako extraktor.

val id"""matching to variable $a and $b""" = x

Nejlepší na tom všem je, že interpolovaný string se chová jako jiný jazyk vložený do scalovského kódu, kde proměnné mají jiný význam než v kódu okolo. Podobá se to pojetí Perlu 6 nebo plánovaným Quasi-Literalům z ECMA Scriptu.

Možná použití: makra

macro def atomic[A](expr: A): A = scala"""
  scala.concurrent.transaction.withinTransaction {
    (implicit currentTransaction: Transaction) =>
      $expr
}
"""

Můžeme tak nahradit nativní podporu XML.

xml"""
  <body>
    <a href="/$url"> ${linktext.take(100)} </a>
  </body>
"""

Když vezmeme v potaz plánovaná makra a metoda xml nebude obyčejná metoda, ale makro metoda, můžeme během kompilace provést validaci xml.

Další použití může být v regulárních výrazech:

val regex"^($name\w+)\s*=\s*($value\w+)$" = "MainAntagonist = SHODAN"

Nebo pro konstrukci sql dotazů:

sql"select * from $table where name = $name"

sql může provést kontextové escapování, table bude uvozeno zpětnými uvozovkami, name bude uvozen jako sql string dvojitými uvozovkami. Výsledkem přitom vůbec nemusí být řetězec, ale objekt reprezentující databázový dotaz, výsledek nebo iterátor řádků.

Další možné použití je pro lokalizaci textů:

l10n"""$n bear bottles standing on the wall"""

Typicky se pro lokalizaci používá nějaká funkce, která má jako první argument překládaný string, která má čísla nahrazena nějakým placeholderem a další argumenty jsou čísla, podle kterých se použije jednotné nebo množné číslo:

translate("%d bear bottles standing on the wall", n)

Interpolovaný string se přeloží na něco velice podobného:

L10NStringContext("", "bear bottles standing on the wall").l10n(n)

Takže ve výsledku Scala bude mít další mocný nástroj, který bude ještě mocnější ve spojení s makry.


komentáře RSS

Zatím žádné komentáře. Buďte první.
Komentář bude formátován pomocí Texy! syntaxe.
Např: **tučný text**, *kurzíva*, "text odkazu":adresa.
Na ostatní komentáře můžete odkazovat pomocí [čísla komentáře].

Napište komentář!

 

o autorovi:

K. Jmenuji se Karel Čížex, v síti také známý jako kaja47 - tak trochu spisovatel, trochu programátor, trochu webař, milovník divné hudby atd atd.
mail:
jabber: kaja47@jabbim.cz

další projekty

wyhledawacz fel.log stalkr vtipy.k47.cz k47.shop Zkracovač adres stripbot

živě z twitteru

N/A

tadá

poslední články

Techno-optimismus ještě nevymřel
článek | 22. června 2015
Terminalita #18 - Velkej a malej Pítr
povídka | 29. května 2015
Terminalita #17 - Tomy
povídka | 29. května 2015
Terminalita #16 - Konec světa
povídka | 29. května 2015
Terminalita #15 - K.
povídka | 29. května 2015
Zapomínám
| 3. května 2015
Terminalita #14 - Nonexistent ideals
povídka | 3. května 2015
PragoFFest je dekadentní a zvrácený
článek | 15. dubna 2015
Intermezzo
| 14. dubna 2015

poslední komentáře

Sedm let post-rocku
Pavel Kohout | 15. května 2015
Kdybych chtěl napsat autobiografii...
kaja47 | 14. dubna 2015
Kdybych chtěl napsat autobiografii...
Severák | 3. dubna 2015
Temná a vágní fantasy
Michy | 16. února 2015
Meč, který ukončí dějiny
Marty | 28. ledna 2015
Meč, který ukončí dějiny
adam | 21. ledna 2015

největší kecalové

Severák Severák
Pavel Kohout Pavel Kohout
Michy Michy
adam adam

K47i © 2002 - 2015 K. aka Kaja47