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

Infarkt v sedmadvaceti
článek | 24. srpna 2015
Terminalita #27
povídka | 13. srpna 2015
Terminalita #26 - Carl Solomon
povídka | 13. srpna 2015
Terminalita #25 - Anit
povídka | 13. srpna 2015
Terminalita #24 - Kaplan
povídka | 13. srpna 2015
Terminalita #23 - Rakovina
povídka | 13. srpna 2015
Terminalita #22 - Neklid
povídka | 16. července 2015
Terminalita #21 - Zóna
povídka | 16. července 2015

poslední komentáře

Jak jsem se (skoro) stal vegetariánem
kaja47 | 16. července 2015
Jak jsem se (skoro) stal vegetariánem
Michy | 16. července 2015
Ray Bradbury - 451 stupňů Fahrenheita
Anonym | 10. července 2015
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

největší kecalové

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

K47i © 2002 - 2015 K. aka Kaja47