k47.cz
mastodon twitter RSS
bandcamp explorer

Scala - gimmicks

— k47 (CC by-sa)

Věci, které mě zaujaly natolik, abych o nich napsal aspoň jednu větu, ale nemají na vlastní článek.


for println

Pokud chcete něco vypsat upostřed for comprehension s mnoha generátory, můžete to udělat takto:

for {
  c <- collection
  _ = println(c)
  s <- c.subCollection
} yield s

Vnořené komentáře

Scala podporuje strukturované komentáře. Každý začátek víceřádkového komentáře /* musí mít odpovídající ukončení */. Na první pohled se to může jevit jako zbytečnost, ale ve skutečnosti je to docela užitečná funkce.

Když mám nějaký takovýhle kód:

code

/*
anotherCode
*/

stuff

andNowSomethingCompletelyDifferent

A chchi zakomentovat blok od code do stuff:

/*
code

/*
anotherCode
*/

stuff
*/

andNowSomethingCompletelyDifferent

Se strukturovanými komentáři to funguje přesně jak člověk zamýšlel. Kdyby Scala měla šla tradiční cestou, kdy komentář skončí jakmile narazí na */, nevungovalo by to, protože stuff by byl už mimo.

Vnitřní metody definované přes def vs. =>

// tyto dva zápisy jsou ekvivalentní
// funkce x vrátí funkci, která vrací Int, tedy () => () => Int
def x = { () => 2 }
def x = { def a = 2; a _ }

Přílišná specializace

Vezměte si následující kód. Schválně, co dělá?

class X[@specialized A, @specialized B, @specialized C](a: A, b: B, c: C)

Nic moc. Když ho zkusíte zkompilovat, bude to chvíli trvat a ve výsledku vygeneruje 729 tříd. Paráda. Specializace je super vlastnost, ale musí se užívat jenom tam, kde je to nezbytně nutné.

Jenom pro úplnost čtyři specializované parametry vygenrují přes 6500 tříd a v podobném duchu to pokračuje dál.

Podtržítka bez podtržítek

Funkční objekt se z metody vytvoří kouzelným podtržítkem.

val a = println()  // a je Unit
val b = println(_) // b je funkce Unit => Unit, _ nahrazuje jeden argument
val c = println _  // c je funkce Unit => Unit, _ nahrazuje všechny argumenty

Pokud má být požadovaným argumentem funkce, může se podtržítko vynechat.

Seq(1, 2, 3).foreach(println _)
Seq(1, 2, 3).foreach(println(_))
Seq(1, 2, 3).foreach(println) // <- _ vynecháno

Tohle pravidlo platí i v některých neočekávaných situacích. Pohleďte:

Seq(1, 2, 3).map(x => 1 + x) // vrátí Seq(2,3,4), nic překvapivého
Seq(1, 2, 3).map(1 + _)      // pořád dobré
Seq(1, 2, 3).map(1+)         // eh... funguje úplně stejně

Syntaxe metod

Scala má velice flexibilní syntaxi. Následující útžky kódu jsou ekvivalentní

obj.meth(a).meth(b).meth(c)
obj.meth(a)meth(b)meth(c)
obj meth a meth b meth c

Typová rekurze

K tomu, aby byl programovací jazyk Turing-kompletní stačí while cyklus, podmíněný skok nebo rekurze. Samotný typový systém Scaly obsahuje rekurzi a je sám o sobě Turing-kompletní.

Co s tím?

Můžeme provozovat nějakou černou magii nebo na to balit holky.

píše k47, ascii@k47.cz