DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
Securing Your Software Supply Chain with JFrog and Azure
Register Today

Trending

  • Understanding Data Compaction in 3 Minutes
  • Preventing Data Loss With Kafka Listeners in Spring Boot
  • How To Integrate Microsoft Team With Cypress Cloud
  • Which Is Better for IoT: Azure RTOS or FreeRTOS?

Trending

  • Understanding Data Compaction in 3 Minutes
  • Preventing Data Loss With Kafka Listeners in Spring Boot
  • How To Integrate Microsoft Team With Cypress Cloud
  • Which Is Better for IoT: Azure RTOS or FreeRTOS?

Functional Reactive Programming in Dart

Victor Savkin user avatar by
Victor Savkin
·
Aug. 08, 13 · Interview
Like (0)
Save
Tweet
Share
4.07K Views

Join the DZone community and get the full member experience.

Join For Free

Functional Reactive Programming (FRP) is a paradigm for modeling interactions in a reactive style. It enables rich composition and allows for the testability of complex interactions. Sean Kirby and I put together a small library prototype (available at: https://github.com/vsavkin/frp_dart) to show how this paradigm can be used in Dart.

What is functional reactive programming?

As I said, it is a programming paradigm that is built on top of the following:

  1. The concept of streams, which model sequences of discrete events.
  2. The concept of properties, which model continuous values.

An example of a stream would be when all key-ups are triggered on some input element. The input element’s text can be modelled as a property.

Adding Properties

Since the Dart SDK gives us only one of the two basic FRP abstractions (streams), we have to implement the property ourselves.

abstract class Property {
  //the current value of the property at any given moment in time
  get value;

  //the stream you can subscribe to to be notified when the property changes
  Stream changes;

  //a shortcut to attach a listener to the changes stream
  void onChange(Function listener);

  //broadcasts the current values to all the listeners
  void notify();

  //creates a derived property
  Property derive(Function mapper);
}

Creating Properties

A property can be created using one of the following ways:

Using a Constant

var propertyThatIsAlways10 = fromConst(10)

Using an Initial Value and a Stream

targetValue(_) => _.target.value;
var login = fromStream("", loginField.onKeyUp.map(targetValue));

By Deriving a Property

bool isPresent(String _) => _.trim().isNotEmpty;
var loginPresent = login.derive(isPresent);

By Using a Function

var coin = new ComputedProperty(() => new Random().nextInt(1));

Combining Properties

What really makes FRP interesting is that properties can be composed of other properties. One example would be joining a bunch of them together.

var password = fromStream("", passwordField.onKeyUp.map(targetValue));
var passwordConfirmation = fromStream("", passwordConfirmationField.onKeyUp.map(targetValue));

var tuples = join([password, passwordConfirmation]);

At the beginning, the value of the tuples property is: ["", ""]. If I type a into the password field, the value will change to ["a", ""]. Similarly, after entering b into the confirmation field, the value will become ["a", "b"].

There are a bunch of combinators that will be used in pretty much any interaction. One of them is and.

var loginPresent = ...;
var passwordPresent = ...;
var bothFieldsPresent = and([loginPresent, passwordPresent]);

Example

Now, having gone through the basics of functional reactive programming, let’s see how we can use it for modelling a simple interaction.

Suppose we have a sign-up form.

Sign Up Form

We would like to enable the button when the login field is present, the password field is present, and the password and confirmation fields match.

First of all, let’s define the form’s interface.

abstract class SignUpForm {
  Stream<String> get loginFieldValues;
  Stream<String> get passwordFieldValues;
  Stream<String> get confirmationFieldValues;
  void toggleButton(bool enabled);
}

This separates the DOM-specific code from the interaction itself, which allows the replacement of the real form with a test double when needed.

Second, import the FRP library.

import 'package:frp/frp.dart' as _;

Next, implement the interaction itself.

signUpInteraction(SignUpForm form){
  var password = _.fromStream("", form.passwordFieldValues);
  var passwordPresent = password.derive(isPresent);

  var confirmation = _.fromStream("", form.confirmationFieldValues);
  var passwordConfirmed = _.same([password, confirmation]);

  var login = _.fromStream("", form.loginFieldValues);
  var loginPresent = login.derive(isPresent);

  var validForm = _.and([loginPresent, passwordPresent, passwordConfirmed]);

  validForm.onChange(form.toggleButton);
}

Finally, we need to instantiate the form and call the interaction.

class DomSignUpForm implements SignUpForm {
  Element form;
  DomSignUpForm(this.form);

  get loginFieldValues         => _fieldValues("input[name=login]");
  get passwordFieldValues      => _fieldValues("input[name=password]");
  get confirmationFieldValues  => _fieldValues("input[name=confirmation]");
  toggleButton(enabled)        => form.query("input[type=button]").disabled = !enabled;

  _fieldValues(selector) => form.query(selector).onKeyUp.map((_) => _.target.value);
}

main(){
  signUpInteraction(new DomSignUpForm(query("form")));
}

Wrapping Up

  • Functional reactive programming can be used for expressing complex UI interactions in a declarative way.

  • Properties can be created from streams and derived from other properties. In addition, they can be combined using such combinators as join.

  • The library presented in this article is just a prototype but, since the Dart SDK provides streams, building a production-ready library similar to Bacon.js should not be very difficult.

Read More About Dart

Read more about Dart at engineering.nulogy.com.



Functional reactive programming Reactive programming Dart (programming language) Property (programming) Interaction

Published at DZone with permission of Victor Savkin, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • Understanding Data Compaction in 3 Minutes
  • Preventing Data Loss With Kafka Listeners in Spring Boot
  • How To Integrate Microsoft Team With Cypress Cloud
  • Which Is Better for IoT: Azure RTOS or FreeRTOS?

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: