1

Is there an idiomatic way to chunk and concatenate?

The ways that I've found (examples for bytes):

    1.
import scodec.bits.ByteVector    

def byteChunk(n: Int): Process1[ByteVector, ByteVector] =
    process1.chunk(n).map(_.reduce(_ ++ _))

But the intermediate Vector (from chunk) isn't really needed in this case.

  1. Based on copy/paste from process1.chunk:
def byteChunk(n: Int): Process1[ByteVector, ByteVector] = {

  def go(m: Int, acc: ByteVector): Process1[ByteVector, ByteVector] =
    if (m <= 0) {
      emit(acc) ++ go(n, ByteVector.empty)
    } else {
      def fallback = if (acc.nonEmpty) emit(acc) else halt
      receive1Or[ByteVector, ByteVector](fallback) { in =>
        go(m - 1, acc ++ in)
      }
    }

  go(n, ByteVector.empty)
}

Is there a way to do the same with combining the existing Process'es?

A side question: could repeat be used instead of ++ go? Is this the same as the previous:

def byteChunk(n: Int): Process1[ByteVector, ByteVector] = {

  def go(m: Int, acc: ByteVector): Process1[ByteVector, ByteVector] =
    if (m <= 0) emit(acc)
    else ...

  go(n, ByteVector.empty).repeat
}
Vasiliy Levykin
  • 302
  • 4
  • 6

1 Answers1

0

I think you could simplify this a bit using take, last and scanMonoid

def byteChunk(n: Int): Process1[ByteVector, ByteVector] = {
  process1.take[ByteVector](n).scanMonoid.last ++ Process.suspend(go(n))
}

(or replace scanMonoid with something like .scan(ByteVector.empty)((acc, x: ByteVector) => acc ++ x) if you do not wish to implement Monoid[ByteVector]).

It also appears that Process.repeat will work instead of ++ Process.suspend(go(n)) and the way Process.repeat is implemented suggests it will be true as long as byteChunk(n) is pure.

Pyetras
  • 1,492
  • 16
  • 21