Рассмотрим следующий частичный объектив для поиска значений в списке по индексу (обратите внимание, что это всего лишь педагогический пример, поскольку monocle.std.list.listIndex
обеспечивает эту функциональность с полки):
import monocle.Optional
def listIndexOptional[A](i: Int): Optional[List[A], A] =
Optional[List[A], A](_.lift(i))(a => l =>
if (l.isDefinedAt(i)) l.updated(i, a) else l
)
Теперь мы можем определить Optional
, что указывает на третий элемент в списке строк:
val thirdString = listIndexOptional[String](2)
и использовать его так:
scala> thirdString.set("0")(List("a", "b", "c"))
res4: List[String] = List(a, b, 0)
scala> thirdString.set("0")(List("a", "b"))
res5: List[String] = List(a, b)
Обратите внимание, что если нет третьего элемента, операция просто возвращает список немодифицированным. Если бы мы хотели бы знать, был ли обновлен элемент, мы можем использовать setOption
:
scala> thirdString.setOption("0")(List("a", "b", "c"))
res6: Option[List[String]] = Some(List(a, b, 0))
scala> thirdString.setOption("0")(List("a", "b"))
res7: Option[List[String]] = None
Тот факт, что метод Optional.apply
принимает в качестве второго аргумента функции A => S => S
частично является удобство, так как мы часто хотим определить частичный таким образом, и частично, чтобы мы не могли определить частичную линзу, где getOption
и setOption
не согласны с тем, существует ли цель.
Если вы действительно этого хотите, вы всегда можете определить Optional
с точки зрения установщика A => S => Option[S]
, наклеив на конец getOrElse(s)
.
Monocle предоставляет метод 'setOption' на' Optional', который обеспечивает операцию, которую вы ищете. 'set' просто возвращает данный' C' unmodified, если нет совпадения. –
Так может быть и дополнительный сеттер, выводимый из дополнительного геттера и общего сеттера? –
После проверки исходного кода для 'setOption', мне кажется, что он никогда не сможет создать« None », поэтому создание частичной линзы таким образом не кажется жизнеспособным, не так ли? –