k47.cz
mastodon twitter RSS
bandcamp explorer

Scala - postfixový if

8. 12. 2010 (aktualizováno 30. 5. 2021) — k47 (CC by-sa)

Některé jazyky jako třeba Ruby, Python nebo třeba CoffeScript mají takzvaný postfixový if a jeho obdobu unless, tedy podmínku, která se zapisuje ve formátu doSomething() if condition. Tahle syntaxe může být o něco příjemnější, protože je bližší přirozenému jazyku.

Scala postfixový if nemá, ale – hádejte co – je to jazyk natolik flexibilní, že v něm není problém implementovat vše, po čem vaše srdce touží. Bohužel nemůžeme použít klíčové slovo if, což je jediná vada na kráse. Tedy takhle: můžeme použít if, ale musíme ho pak vždy uvádět ve zpětných apostrofech. Svému účelu poslouží označení iff.

class Iff[T](a: => T) {
  def iff(cond: => Boolean) = if (cond) Some(a) else None
  def unless(cond: => Boolean) = if (cond) None else Some(a)
}

import scala.language.implicitConversions

implicit def postfixIf[T](a: => T): Iff[T] = new Iff(a)

// test
println("Je tam ještě?") iff true        // vypíše text
println("Je tam ještě?") iff 1 == 0      // nevypíše nic

println("Je tam ještě?") unless false    // vypíše text
println("Je tam ještě?") unless 1 == 1   // nevypíše nic

Vše funguje díky implicitním konverzím a argumentům předávaným jménem. Podmíněný kód se provede skutečně jen tehdy, když je podmínka pravdivá.


Výše uvedený kód stále funguje ve Scale 3. Ta nicméně nabízí prostředky jak vyjádřit to samé přímo bez implicitních konverzí a pomocných tříd. Třetí verze jazyka uvedla klíčové slovo extension, které dovoluje přidat metody k již existujícímu typu. Výsledek má identickou funkcionalitu, jen přímo říká, že metody rozšiřují generický typ T.

extension[T] (x: => T) {
  infix def iff(cond: Boolean) = if (cond) Some(x) else None
  infix def unless(cond: Boolean) = if (cond) Some(x) else None
}

Klíčové slovo infix povoluje, aby se iffunless mohly volat jako operátory syntaxí a iff b, namísto pouze a.iff(b).

píše k47, ascii@k47.cz