28
votes

Does Google Dart language allow for functional programming to occur? In particular, are the following features supported?

  • functions stored as variables (references),
  • functional currying,
  • lazy parameters

Other features of functional programming?

It looks like Dart does not support immutable data.

7

7 Answers

35
votes

Dart has first-class functions and supports many functional programming constructs. Here are some examples of assigning functions to variables and of a curried function:

main() {
  f1(x) => x * 2;         // Define the function f1
  var f2 = f1;            // Assign f1 to the variable f2
  print(f2(7));           // Feel free to call f2 like any other function

  add(a) => (b) => a + b; // Curried addition
  print(add(3)(4));       // Calling curried addition

  var add3 = add(3);      // Combining the
  print(add3(2));         //  concepts
}

As expected, this produces:

14
7
5

I don't believe lazy parameters are possible, and you already noted that there is clearly mutable data.

8
votes

Depends on what you mean by "functional programming". Functions are first-class objects, which covers point 1, there is Function.apply which lets you implement currying yourself, so that covers point 2, but other than that, Dart isn't very functional (immutability -- no, referential transparency -- no, lazy evaluation -- no, what else have you -- probably also no).

6
votes

Small example about immutability:

class Point {
  Point(this.x, this.y);
  int x,y;
  int get sum => x + y;
}
class ImmutablePoint{
  final  int x,y, sum;
  const ImmutablePoint(x,y) :
    this.x = x,this.y = y,this.sum = x + y;
}

class SemiImmutablePoint {
  int _x, _y; // _ -like private but not access protected by the VM.
  SemiImmutablePoint(this._x, this._y);
  int get x => _x;
  int get y => _y;
}

void main() {
  List<int> li = [1,2,3,4,5];
  final List<int> immutableLi = const [1,2,3,4,5];
  li[1] = 10; //ok
  li = [6,7,8]; //ok
  immutableLi[1] = 10; //error because const
  immutableLi = [6,7,8]; //error because final
  var p = new Point(5,10);
  p.x = 10; //ok
  p.sum = 10; // error can't be directly mutated
  var p2 = const ImmutablePoint(5,10); // compile-time constant
  p2.x = 10; //error
}

You can use FP with the Dart or even languages without types or immutability like JS. it's just a style, it doesn't require native implementation in the language.

With the languages like Scala FP paradigms are normally implemented with the type system so it's more restrictive and harder to unintentionally breach. But at the same time you require from the lib user specialized knowledge of really complex type system, sometimes category theory - otherwise it's really hard to benefit from knowing that this thing is "monad" or "monoid" or whatever. I can use lists without knowing that those are monads or really useful concept of "future" in Dart. When you implement FP without "type magic" it's often clearer and more accessible to grasp by an average developer. But at the same time having powerful type system can help compiler perform advanced code optimizations and enable better static code analysis.

Category theory for JavaScript programmers - Worth watching.

added: Now collections have UnmodifiableListView UnmodifiableMapBase UnmodifiableMapView

5
votes

To your last point, immutability, see:

which provide library and codegen support for immutable collections and "value types". These help bridge the gap between OO and functional programming, for example allowing inline "updates" to immutable values:

var node = new Node((b) => b
  ..left.left.left.right.left.right.label = 'I’m a leaf!'
  ..left.left.right.right.label = 'I’m also a leaf!');
var updatedNode = node.rebuild((b) => b
  ..left.left.right.right.label = 'I’m not a leaf any more!'
  ..left.left.right.right.right.label = 'I’m the leaf now!');

Where "node" and "updatedNode" are both immutable. More detail in this article: built_value for Immutable Object Models.

3
votes

A package that improves Dart FP experience further https://github.com/vsavkin/fpdart

An open issue about tail recursion https://code.google.com/p/dart/issues/detail?id=29

3
votes

It seems there is a more popular solution called dartz

DARTZ

  • Type class hierarchy in the spirit of cats, scalaz and the standard Haskell libraries
  • Immutable, persistent collections, including IVector, IList, IMap, IHashMap, ISet and AVLTree
  • Option, Either, State, Tuple, Free, Lens and other tools for programming in a functional style
  • Evaluation, a Reader+Writer+State+Either+Future swiss army knife monad
  • Type class instances (Monoids, Traversable Functors, Monads and so on) for included types, as well as for several standard Dart types
  • Conveyor, an implementation of pure functional streaming
  • Examples, showcasing core concepts

I couldn't understand how to use it but there are examples.

1
votes

You can use this package for function currying : https://pub.dev/packages/functional

It can increase code readablity also.

  int add(int a,int b) => a+b;

and now this function can be curried as below.

  final inc = add % 1;
  final dec = add % -1;

  print(inc(5)); // Same as add(1, 5);
  print(dec(5)); // Same as add(-1, 5);