I created a process to help me parse log files. The log files need to be tagged with a string tag. Not ever record can provide this string tag, so I need to maintain some state across each log event so that each event will have a tag. If an event is missing a tag, I want to use the last tag found. This allows me to parse logs like below and have a "tag" associated with the message lines even though they are part of eventindex04 record header. I could wrap the event in an envelope and have the logic in the envelope, but then I have an envelope everywhere which seems heavyweight.
eventindex01 start log ...
eventindex02 time ...
eventindex03 user ...
eventindex04 message
message1
message2
eventindex05 start log ...
I put together this process which works fine:
def extractStatefulAttribute[T, D](first: T)(getTag: D => Option[T]):
Process1[D, (T, D)] = {
def go(lastTag: T): Process1[D, (T, D)] = {
Process.receive1[D, (T, D)] {
event: D =>
val tag = getTag(event) getOrElse lastTag
Process.emit((tag, event)) ++ go(tag)
}
}
go(first)
}
This feels like it should be expressed as a scan/fold, but I could not make it work. Can this be rewritten as a scan/fold?