Próbuję napisać kod, który śledzi zmiany w rekordzie i stosuje je w późniejszym terminie. W dynamicznym języku zrobiłbym to, po prostu przechowując dziennik z parami List [(String, Any)], a następnie po prostu stosując je jako aktualizację oryginalnego rekordu, kiedy ostatecznie zdecyduję się zatwierdzić zmiany.Typowe generyczne aktualizacje klas przypadków w Scali
Muszę mieć możliwość introspekcji aktualizacji, więc lista funkcji aktualizacji nie jest odpowiednia.
W Scali jest to dość banalne za pomocą refleksji, jednak chciałbym wprowadzić wersję bezpieczną.
Moja pierwsza próba polegała na spróbowaniu bezkształtnym. Działa to dobrze, jeśli znamy konkretne typy.
import shapeless._
import record._
import syntax.singleton._
case class Person(name:String, age:Int)
val bob = Person("Bob", 31)
val gen = LabelledGeneric[Person]
val updated = gen.from(gen.to(bob) + ('age ->> 32))
// Result: Person("Bob", 32)
Jednak nie mogę wymyślić, jak zrobić to ogólnie.
trait Record[T]
def update(???):T
}
Biorąc pod uwagę sposób, w jaki to bezkształtne radzi sobie z tym, nie jestem pewien, czy to byłoby nawet możliwe?
Jeśli przyjmuję dużą liczbę elementów, jako biedną wersję mans mogę zrobić coś na wzór:
object Contact {
sealed trait Field[T]
case object Name extends Field[String]
case object Age extends Field[Int]
}
// A typeclass would be cleaner, but too verbose for this simple example.
case class Contact(...) extends Record[Contact, Contact.Field] {
def update[T](field:Contact.Field[T], value:T) = field match {
case Contact.Name => contact.copy(name = value)
case Contact.Age => contact.copy(age = value)
}
}
Jednak nie jest to szczególnie eleganckie i wymaga wielu elementów. Prawdopodobnie mógłbym napisać własne makro, aby sobie z tym poradzić, ale wydaje się dość powszechne - czy istnieje sposób radzenia sobie z tym z Shapeless lub podobną biblioteką makr?
Czy spojrzałeś na elementy optyczne (soczewki, pryzmaty itp.)? – rightfold
Jeśli poprawnie rozumiem soczewki, pozwalają mi jawnie zaktualizować rekord, ale nie mogę rejestrować metadanych dotyczących zmian, które chcę później zastosować? –
Myślę, że bezkształtny zapewnia większość potrzebnych części. Możesz przejrzeć przykłady bezpiecznej delty i klasy przypadków a la carte w najnowszej bezkształtnej migawce 2.1.0. Poza tym twoje pytanie nie jest wystarczająco precyzyjne, abym mógł odpowiedzieć na to bez pisania wszystkiego dla ciebie ;-) –