To get the latest development version of the library, add the following to your SBT build:
resolvers ++= Seq("snapshots" at "http://oss.sonatype.org/content/repositories/snapshots")
libraryDependencies += "org.scalaz.stream" %% "scalaz-stream" % "0.1-SNAPSHOT"
The library only builds against Scala 2.10, not earlier versions. There has not yet been a stable (non-snapshot) release, but we will probably cut a 0.1 release soon, after a few things stabilize.
scalaz-stream
is a streaming I/O library. The design goals are compositionality, expressiveness, resource safety, and speed. The design is meant to supercede or replace older iteratee or iteratee-style libraries. Here's a simple example of its use:
import scalaz.stream._
import scalaz.concurrent.Task
val converter: Task[Unit] =
io.linesR("testdata/fahrenheit.txt").
filter(s => !s.trim.isEmpty && !s.startsWith("//")).
map(line => fahrenheitToCelsius(line.toDouble).toString).
intersperse("\n").
pipe(process1.utf8Encode).
to(io.fileChunkW("testdata/celsius.txt")).
run
// at the end of the universe...
val u: Unit = converter.run
This will construct a Task
, converter
, which reads lines incrementally from testdata/fahrenheit.txt
, skipping blanklines and commented lines. It then parses temperatures in degrees fahrenheit, converts these to celsius, UTF8 encodes the output and writes incrementally to testdata/celsius.txt
, using constant memory. The input and output files will be closed in the event of normal termination or exceptions.
The library supports a number of other interesting use cases:
- Zipping and merging of streams: A streaming computations may read from multiple sources in a streaming fashion, zipping or merging their elements using a arbitrary
Tee
. In general, clients have a great deal of flexibility in what sort of topologies they can define--source, sinks, and effectful channels are all first-class concepts in the library. - Dynamic resource allocation: A streaming computation may allocate resources dynamically (for instance, reading a list of files to process from a stream built off a network socket), and the library will ensure these resources get released in the event of normal termination or when errors occur.
- Nondeterministic and concurrent processing: A computation may read from multiple input streams simultaneously, using whichever result comes back first, and a pipeline of transformation can allow for nondeterminism and queueing at each stage.
- Streaming parsing (UPCOMING): A separate layer handles constructing streaming parsers, for instance, for streaming JSON, XML, or binary parsing. See the roadmap for more information on this and other upcoming work.
There are more examples (with commentary) in the test directory scalaz.stream.examples
. Also see the wiki for more documentation. If you use scalaz.stream
, you're strongly encouraged to submit additional examples and add to the wiki!
Machines is a Haskell library with the same basic design as scalaz-stream
, though some of the particulars differ. There is also scala-machines
, which is an older, deprecated version of the basic design of scalaz-stream
.
There are various other iteratee-style libraries for doing compositional, streaming I/O in Scala, notably the scalaz/iteratee
package and iteratees in Play.