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

#299
článek | 27. srpna 2014
O čem mluvím, když mluvím o Murakamim
článek | 31. července 2014
Kafe v pět
povídka | 30. června 2014
O bestii
povídka | 30. června 2014
Úvod do zrcadel a labyrintů
článek | 12. května 2014
Slova starého feťáka
článek | 17. dubna 2014
669.350
| 8. dubna 2014

poslední komentáře

MySQL group by trik
mrsa | 20. března 2014
Vodník
cbvcxy | 22. února 2014
Rozdělení velkých tříd ve Scale
JeLiTo | 11. ledna 2014
Božena Němcová - V zámku a podzámčí
Anonym | 27. prosince 2013
Sedm let post-rocku
Woodbin | 9. prosince 2013

největší kecalové

JeLito JeLito
Anonym Anonym
mrsa mrsa
Okurka369 Okurka369
cbvcxy cbvcxy

K47i © 2002 - 2014 K. aka Kaja47