GithubHelp home page GithubHelp logo

dylemma / scala.frp Goto Github PK

View Code? Open in Web Editor NEW
24.0 9.0 6.0 508 KB

Functional Reactive Programming for Scala

Home Page: http://javadoc.io/doc/io.dylemma/scala-frp_2.11/1.3

License: MIT License

Scala 100.00%

scala.frp's Introduction

Scala FRP

This library replaces the idea of Publishers and Subscribers with EventStreams. An EventStream can be treated like a collection of events; it can be transformed similarly to any other Scala collection, and instead of needing to call publisher.addEventListener(new EventListener(){...}), you simply call eventStream.foreach{...}

###Background

Scala FRP (stands for Functional Reactive Programming) is a library inspired by Ingo Maier's paper, Deprecating the Observer Pattern. Ingo Maier made an implementation of his "scala.react" framework which is available on Github in its original form. I also made a version of the same library that works with SBT to manage its dependencies, available here.

###Getting it

Add the following to your build.sbt file:

libraryDependencies += "io.dylemma" %% "scala-frp" % "1.2"

###Example Usage

import io.dylemma.frp._

// Mix in `Observer` for free memory management.
object Example extends App with Observer {

	// Create a source of events.
	val ints = EventSource[Int]

	// You can derive new event streams any other event stream.
	val evenInts = ints.filter{ _ % 2 == 0 }
	val intsWithIndices = ints.zipWithIndex
	val soonInts = ints.before(2 seconds fromNow)

	// Attach event handlers.
	ints.foreach{ x => println(s"An int: $x") }
	evenInts.foreach { x => println(s"Even int: $x") }
	intsWithIndices.foreach { case (x, i) => println(s"$ith int was $x") }
	soonInts.foreach { x => println(s"$x came soon enough") }

	// Fire events!
	ints fire 1
	ints fire 2
	ints fire 3

}

###FRP-101

Attaching event handlers requires an implicit Observer. The observer helps make sure that no cyclical references are made between the EventStream and the handler function; it keeps a weak reference to the handler so that the handler function may be garbage-collected once the Observer is garbage-collected. You can get an implicit Observer one of two ways:

  • Make one yourself: implicit object myObserver extends Observer
  • Mix it into the containing class, like in the example above. The Observer trait has an implicit reference to itself.

With that requirement out of the way, you're ready to start! There are two main classes that you will want to interact with.

  • EventStream is a read-only class that you can attach event handlers to, and create mappings and combinations with.
  • EventSource is a concrete implementation of EventStream that also exposes fire and stop methods.

###FRP-102

EventStreams are finite. At a low level, they emit events as an Event[A], which can either be a Fire(item) or a Stop. When you call foreach on a stream, it will receive all Fire events until the stream emits a Stop. You can attach to these lower-level events with the sink(handler: Event[A] => Boolean) method. The handler will remain attached until it returns false in response to an event.

Because of the concept of finite EventStreams, streams are able to be concatenated; handlers may be attached that simply wait for the last event from the stream, or the eventual Stop.

For further details and a full list of capabilities, check out the docs

scala.frp's People

Contributors

dylemma avatar stanch avatar thangiee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scala.frp's Issues

Handlers added to MappedEventStream get GCed

I’m on Android, but I don’t think it matters.
What happens is that given a continuous stream of events stream,

  • stream.foreach(_ ⇒ Log.d("S1", "working")) gets printed all the time, even after GC_EXPLICIT, but
  • stream.map(_ + 1).foreach(_ ⇒ Log.d("S2", "working")) stops after first GC_FOR_ALLOC (see here for the meaning).

Strange thing is that Observer still keeps all four references (two Function1s, an EventSource and a MappedEventStream): I made a custom observer to debug this.

I am not sure what else could be garbage collected there. Any thoughts?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.