Идиоматический "получить или еще обновить" для immutable.Map?
Каков идиоматический способ getOrElseUpdate для неизменяемых экземпляров .Map?. Я использую фрагмент ниже, но он выглядит многословным и неэффективным.
var map = Map[Key, Value]()
def foo(key: Key) = {
val value = map.getOrElse(key, new Value)
map += key -> value
value
}
Ответы
Ответ 1
Позвольте мне подвести итог вашей проблеме:
- Вы хотите вызвать метод в неизменяемой структуре данных
- Вы хотите вернуть некоторое значение и переназначить
var
- Поскольку структура данных неизменна, вам необходимо
- возвращает новую неизменяемую структуру данных или
- выполнить назначение внутри метода, используя поставляемое закрытие
Итак, ваша подпись должна выглядеть как
def getOrElseUpdate(key: K): Tuple2[V, Map[K,V]]
//... use it like
val (v, m2) = getOrElseUpdate(k)
map = m2
или
def getOrElseUpdate(key: K, setter: (Map[K,V]) => Unit): V
//... use it like
val v = getOrElseUpdate(k, map = _)
Если вы можете жить с одним из этих решений, вы можете добавить свою версию с неявным преобразованием, но, судя по только подписям, я бы не думал, что любой из них находится в стандартной библиотеке.
Ответ 2
Я бы, вероятно, использовал метод getOrElseUpdated
, подобный этому:
def getOrElseUpdated[K, V](m: Map[K, V], key: K, op: => V): (Map[K, V], V) =
m.get(key) match {
case Some(value) => (m, value)
case None => val newval = op; (m.updated(key, newval), newval)
}
который возвращает исходную карту, если m
имеет отображение для key
или другое отображение с добавлением отображения key -> op
. Определение этого метода похоже на getOrElseUpdate
of mutable.Map
.
Ответ 3
Нет такого пути - мутация карты (обновление), когда вы получаете значение карты, является побочным эффектом (что противоречит неизменности/функциональному стилю программирования).
Если вы хотите создать новую неизменяемую карту со значением по умолчанию, если другое значение для указанного ключа не существует, вы можете сделать следующее:
map + (key -> map.getOrElse(key, new Value))
Ответ 4
Почему бы не использовать withDefault
или withDefaultValue
, если у вас есть неизменяемая карта?