Gozala / reducers

Library for higher-order manipulation of collections
MIT License
181 stars 8 forks source link

Implement `finalize` function #35

Open Gozala opened 11 years ago

Gozala commented 11 years ago

At the moment once reducer returns reduced(result) consumed input is signaled that reducer no longer wishes to consume it. In a way it's a signal to stop an input. Any further values yield will are suppressed by reducible which is core function for creating reducibles.

Unfortunately this design choice prevents performing any asynchronous finalization tasks after reduced(value) is returned. Consider a case where reducible task represents:

function read(path) {
  return expand(callback(fs.open, path), function(fd) {
    return concat(fs.readStream(fd), callback(fs.close, fd))
  })
}

If only parts of the content is read fs.close is never executed. Obviously this can be fixed by adding some function like finalize:

function finalize(input, f) {
  return reducible(function(next, initial) {
    reduce(input, function(value, result) {
      if (value === end) return reduce(f(result), next, result)
      if (isError(value)) return reduce(concat(f(result), value), next, result)
      result = next(value, result)
      if (isReduced(result)) return reduce(f(result.value), next, result)
    }, initial)
  })
}

The problem is though that according to an API stream should not yield anything after reduced(value) is returned by a consumer. Although if async task is just executed in case of error there will be no one handling it.

Gozala commented 11 years ago

Only solution I can imagine of is by required end value even in cases when reduced(value) is returned by a consumer. Unfortunately this adds complexity on the side of input source implementer. In addition broken input may break expectations by sending more values after reduced(value) is returned.

This also means that errors may occur in attempt to finalize input which would mean errors after reduced(value) may occur, which complicates API.

Gozala commented 11 years ago

@Raynos feedback and suggestions on this subject is very welcome.

Raynos commented 11 years ago

This is a pain in the ass. All I want to know is whether a reducible is finished not being able to put more values into a reducible.

Finalize means we can add more values into a finished reducible which is silly. You need some kind of onBeforeFinish hook which can't be done when user sends reduced(...)

You can still do finalize just don't reduce the result of it.