k47.cz  — každý den dokud se vám to nezačne líbit
výběr foto Praha povídky kultura
TECH ▞▞ kolo | twitter RSS

Scala - Zřetězené porovnávání

13. 12. 2010 (před 8 lety) — k47 (CC by) (♪)

Perl 6 (Duke Nukem Fo­re­ver mezi pro­gra­mo­va­cími jazyky, který je mi­mo­cho­dem na­prosto epic), má ne­u­vě­ři­telně bo­ha­tou syn­taxi a jednou z tisíce vy­chy­tá­vek je zře­tě­zené po­rov­ná­vání, kdy můžete zapsat pod­mínku ve tvaru 20 <= $temperature <= 25. Když se na to po­dí­váte, dává to smysl na první pohled, ale vět­šina jazyků výraz ne­vy­hod­notí jako 20 <= $temperature && $temperature <= 25, ale jako (20 <= $temperature) <= 25, což není, co by člověk chtěl.

Nicméně i zře­tě­zené po­rov­ná­vání se dá docela pěkně im­ple­men­to­vat ve Scale.


class CC[T <% Ordered[T]](val v: T, val b: Boolean = true) {
// view bound T <% Ordered[T] zaručuje, že T má metody <, >, <=, >=

  def toBool = b

  private def make(x: Boolean) = new CC(v, b && x)

  def <<:(a: CC[T]) = make(a.v < v) // <: je klíčové slovo - tzv. upper type bound
  def :<<(a: CC[T]) = make(v < a.v)

  def >>:(a: CC[T]) = make(a.v > v) // >: je klíčové slovo - tzv. lower type bound
  def :>>(a: CC[T]) = make(v > a.v)

  def <=:(a: CC[T]) = make(a.v <= v)
  def :<=(a: CC[T]) = make(v <= a.v)

  def >=:(a: CC[T]) = make(a.v >= v)
  def :>=(a: CC[T]) = make(v >= a.v)

  override def toString() = "CC " + b.toString
}

implicit def v2cc[T <% Ordered[T]](v: T) = new CC(v)
implicit def cc2b[T](v: CC[T]) = v.toBool

// test
val a = 20
val b = 15

if (10 <<: a :<< 30) { println("ok") } else { println("chyba") }
if (10 <<: a :<< 15) { println("chyba") } else { println("ok") }
if (10 <<: a :>> b)  { println("ok") } else { println("chyba") }

Metody kon­čící dvoj­teč­kou se v pozici ope­rá­torů volají v opač­ném pořadí. Metody se bo­hu­žel ne­mů­žou jme­no­vat <:>:, pro­tože to jsou klí­čová slova. Te­o­re­ticky všechny metody za­čí­na­jící dvoj­teč­kou by mohly mít podobu stan­dard­ních ope­rá­torů po­rov­nání (tedy místo :<< by se po­u­žilo <, místo :>> pak > atd), ale z důvodu kon­zis­tence a jako signál, že se děje něco ne­ka­lého, jsem nechal tvar takový jaký je.

Mi­mo­cho­dem, pří­klad fun­guje díky tomu, že kom­pi­lá­tor im­pli­cit­ními kon­ver­zemi trans­for­muje výraz 10 <<: 15 :<< 20 na cc2b(bv2cc(15).<<:(10).:<<(20)).

píše k47 & hosté, ascii@k47.cz