#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 , не так ли?