scala: Map.orElseThrow()

scala: Map.orElseThrow()
Julian_
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1703
0

Jak nie znajdzie klucza w mapie to niech wyrzuca wyjątek.

Kopiuj
val onError: Unit = {
    logger.error("Not found iso code for country name: " + countryName)
    throw new Exception
}

isoCountryIsoCodeMap.get("argentina") match {
    case Some(s) => Some(s)
    case _ => onError
})

w powyższym ZAWSZE odpala mi onError

DQ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 141
1

Jeśli bardzo chcesz rzucać wyjątek to po prostu zrób isoCountryIsoCodeMap("argentina"). Jak nie znajdzie klucza to rzuci NoSuchElementException. Nie mniej, zwróć uwagę na to, że API kolekcji w Scali nie bez powodu nie oferuje takich metod jak getOrElseThrow. Jeśli masz przypadek gdzie klucza może nie być to użyj .get i zostań z Optionem aż do momentu w którym możesz coś z nim zrobić. Staraj się nie rzucać wyjątków

Julian_
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1703
0
DisQ napisał(a):

Jeśli bardzo chcesz rzucać wyjątek to po prostu zrób isoCountryIsoCodeMap("argentina"). Jak nie znajdzie klucza to rzuci NoSuchElementException.

To by było OK gdyby rzucał którego elementu nie znalazł.

Wibowit
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: XML Hills
0
  1. Twój link do SO prowadzi do pytania i odpowiedzi o Javowych Optionalach. Jak to się niby ma do Scali?
  2. Wypisz zawartość tablicy żeby się upewnić co w niej jest.
  3. To by było OK gdyby rzucał którego elementu nie znalazł. - przecież rzuca.
DQ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 141
0
Julian_ napisał(a):
DisQ napisał(a):

Jeśli bardzo chcesz rzucać wyjątek to po prostu zrób isoCountryIsoCodeMap("argentina"). Jak nie znajdzie klucza to rzuci NoSuchElementException.

To by było OK gdyby rzucał którego elementu nie znalazł.

Możesz do tego podejść albo poprzez rzucanie wyjątków, albo poprzez stworzenie struktur, które będą odpowiednio reprezentowały to co chcesz uzyskać (oczywiście pod warunkiem, że ten optional jest nie do przyjęcia), pi razy drzwi:

Kopiuj
sealed trait IsoCodeRetrievalStatus extends Product with Serializable
final case class IsoCodeRetrieved(isoCode: String) extends IsoCodeRetrievalStatus
final case class IsoCodeMissing(isoCountry: String) extends IsoCodeRetrievalStatus

val x: IsoCodeRetrievalStatus = isoCountryIsoCodeMap.get("argentina").fold[IsoCodeRetrievalStatus](IsoCodeMissing("argentina")(isoCode => IsoCodeRetrieved(isoCode))

Wtedy, jak już będziesz musiał się dowiedzieć czy się udało czy nie to możesz zrobić pattern matching:

Kopiuj
x match {
    case IsoCodeRetrieved(isoCode) => ???
    case IsoCodeMissing(isoCountry) =>
        log.error("Missing ISO code for country: {}", isoCountry)
        ???
}
Wibowit
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: XML Hills
3

Aaaa dobra, już widzę o co biega.

Kopiuj
val onError: Unit = {
    logger.error("Not found iso code for country name: " + countryName)
    throw new Exception
}

Powyższe to zwykła (zachłanna) zmienna, a więc zostanie zawsze wykonana. Jak chcesz mieć metodę to zrób def:

Kopiuj
def onError: Unit = {
    logger.error("Not found iso code for country name: " + countryName)
    throw new Exception
}
Julian_
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1703
0

Prościej będzie tak:

Kopiuj
def getOr(key: A, onError: A => Unit): B {
    val value = map.get(key)
    value.getOrElse(onError(key))
    value
}

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.