Определение операция для класса case

#scala

#scala

Вопрос:

Я хочу определить операцию для класса case в Scala. У меня есть:

 final case class Buffer(
  field1: Seq[Long],
  field2: Long
){
  def  (that: Buffer): Buffer = Buffer(
    (this.field1, that.field1).zipped.map(_   _),
    this.field2   that.field2
  )
}
  

единственная проблема заключается в том, что я хотел бы, чтобы мой код поддерживал что-то вроде (буфер не «пустой»):

 Buffer.empty   buffer = buffer   Buffer.empty = buffer
  

т.е. определение 0, но я не знаю, как это сделать.

Комментарии:

1. Определите empty значение val в сопутствующем объекте Buffer — В любом случае, вам нужен моноид , но cats и Spark находятся на несколько противоположных сторонах подхода к Scala , возможно, вы захотите взглянуть на frameless , но это может быть слишком много вещей, которые нужно изучить на данный момент.

Ответ №1:

Вы можете создать метод empty в сопутствующем объекте вашего класса. Это может выглядеть так:

 object Buffer {
    
  def empty: Buffer = new Buffer(Seq(), 0)
    
}
  

Но у него есть одна проблема. Вы хотите , чтобы оператор имел правильный идентификационный элемент (и был коммутативным). Но в вашей текущей реализации это работает следующим образом:

 Buffer(Seq(1,2,3))   Buffer.empty //Buffer(Seq(), 0)
  

Проблема связана с тем, как zip работает функция. Если вы заархивируете Seq более короткий с более длинным, результат будет иметь меньший размер (более длинный будет усечен).
Есть много способов решить эту проблему, но я думаю, что самым простым способом было бы использовать zipAll , где вы могли бы указать значение «по умолчанию», которое будет использоваться, когда одна из последовательностей короче:

 def  (that: Buffer): Buffer =
   Buffer(
     field1.zipAll(that.field1, 0L, 0L).map(a => a._1   a._2),
     field2   that.field2
   )
  

Вы также можете поделиться одним экземпляром пустого буфера и сделать empty val вместо def . В этом случае важно, чтобы вы использовали неизменяемый Seq.

 import scala.collection.immutable.Seq

object Buffer {
    
  val empty: Buffer = new Buffer(Seq(), 0)
    
}
  

Комментарии:

1. Было бы лучше использовать a val для empty , не так ли?