SORU
10 EKİM 2010, Pazar


Güncelleme için daha temiz bir yol yapıları iç içe

**9 iki es şu var ki:

case class Address(street: String, city: String, state: String, zipCode: Int)
case class Person(firstName: String, lastName: String, address: Address)

ve Person sınıf aşağıdaki örnek:

val raj = Person("Raj", "Shekhar", Address("M Gandhi Marg", 
                                           "Mumbai", 
                                           "Maharashtra", 
                                           411342))

Şimdi ise raj zipCode güncelleme istersem o zaman yaparım:

val updatedRaj = raj.copy(address = raj.address.copy(zipCode = raj.address.zipCode   1))

Bu iç içe daha fazla seviyeleri ile bu daha da çirkin olur. Böyle iç içe geçmiş yapıları güncelleştirmek için daha temiz bir yol (Clojure gibi bir şey update-in) var mı?

CEVAP
8 NİSAN 2011, Cuma


Kimse bu tür şeyler için YAPILMIŞ beri lens eklendi, bu çok komik. Yani, here CS arka plan kağıt üzerinde, here bir blog olan dokunmatik kısaca lens kullanımı Scala, here bir lens uygulaması için Scalaz ve here bazı kodlar kullanarak, şaşırtıcı gibi görünüyor soru. Ve, kazan plaka, here's dava sınıflar için Scalaz lensler üreten bir eklenti kesmek için.

Bonus puan için, here's S. O. başka bir lens ve Tony Morris tarafından paper hangi dokunuşlar soru.

Lensler hakkında büyük bir anlaşma birleştirilebilir olmasıdır. İlk başta biraz hantal, ama daha onları kullanın zemin kazanmaya devam ediyorlar. Ayrıca, yalnızca tek bir lens test etmek gerek, ve hafife bileşimleri alabilir, test edilebilirlik için çok iyiler.

Yani, bir uygulama bu cevap sonunda verdiği bilgilere göre, burada lens ile bunu nasıl yaptığınızla ilgili. İlk olarak, objektif bir adres bir posta kodu değişikliği bildirmek için, ve bir kişi bir adres:

val addressZipCodeLens = Lens(
    get = (_: Address).zipCode,
    set = (addr: Address, zipCode: Int) => addr.copy(zipCode = zipCode))

val personAddressLens = Lens(
    get = (_: Person).address, 
    set = (p: Person, addr: Address) => p.copy(address = addr))

Şimdi, bunları bir kişiye posta kodu değiştiren bir lens almak için Oluştur:

val personZipCodeLens = personAddressLens andThen addressZipCodeLens

Son olarak, bu lens raj değiştirmek için kullanın:

val updatedRaj = personZipCodeLens.set(raj, personZipCodeLens.get(raj)   1)

Ya da, bazı sözdizimsel şeker kullanarak:

val updatedRaj = personZipCodeLens.set(raj, personZipCodeLens(raj)   1)

Hatta:

val updatedRaj = personZipCodeLens.mod(raj, zip => zip   1)

İşte size basit bir uygulama, Scalaz, alınan bu örnek için kullanılır:

case class Lens[A,B](get: A => B, set: (A,B) => A) extends Function1[A,B] with Immutable {
  def apply(whole: A): B   = get(whole)
  def updated(whole: A, part: B): A = set(whole, part) // like on immutable maps
  def mod(a: A, f: B => B) = set(a, f(this(a)))
  def compose[C](that: Lens[C,A]) = Lens[C,B](
    c => this(that(c)),
    (c, b) => that.mod(c, set(_, b))
  )
  def andThen[C](that: Lens[B,C]) = that compose this
}

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Day9TV

    Day9TV

    22 NİSAN 2010
  • My Name Is Jeff

    My Name Is J

    26 ŞUBAT 2008
  • SRC RECORDS

    SRC RECORDS

    2 EKİM 2006