ttt ttt - 4 months ago 17
Scala Question

Scala equivalent way of Range to on custom class

Recently looking at Kotlin and you can do

..
or
to
on some custom classes instead of
Int
or others.

Kotlin achieves that through an extension function as follow:

operator fun <T: Comparable<T>> T.rangeTo(that: T): ClosedRange<T>

which means as long as your class implements
Comparable
interface you can get that for free so you can do:

val now = LocalDate.now()
val vacation = now..now.plusDays(10)


I found that's quite convenient. Just wondering how can we do it in Scala, I know somehow we should achieve it through type class? Maybe right or wrong.

Can anyone showed me the simplest way to do it in Scala? Looks like there is no built in at least for
LocalDate

Answer Source

Well you can always use the old pimp-my-library pattern to add Range-like methods to classes of interest.

import java.time.LocalDate
import java.time.temporal.ChronoUnit

implicit class LocalDateRange(start: LocalDate) {
  // Note: LocalDate already has an until() method so can't add that here
  def to(end: LocalDate): IndexedSeq[LocalDate] =
    IndexedSeq.iterate( start
                      , ChronoUnit.DAYS.between(start, end.plusDays(1L)).toInt
                      )(_.plusDays(1L))
}

Usage:

val now = LocalDate.now()
val vacation: IndexedSeq[LocalDate] = now to now.plusDays(10)

I chose IndexedSeq[] because the Scala docs says that Range is "a special case of an indexed sequence" so it seemed appropriate.