32

Google Dart 语言是否允许进行函数式编程?特别是,是否支持以下功能?

  • 存储为变量(引用)的函数,
  • 功能性柯里化,
  • 惰性参数

函数式编程的其他特点?

看起来 Dart 不支持不可变数据。

4

7 回答 7

40

Dart 具有一流的功能并支持许多函数式编程结构。以下是一些将函数分配给变量和柯里化函数的示例:

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
}

正如预期的那样,这会产生:

14
7
5

我不相信惰性参数是可能的,并且您已经注意到显然存在可变数据。

于 2013-05-25T07:49:46.833 回答
9

取决于您所说的“函数式编程”是什么意思。函数是一流的对象,它涵盖了第 1 点,Function.apply它可以让您自己实现柯里化,因此涵盖了第 2 点,但除此之外,Dart 的功能性不是很强(不变性——不,引用透明性——不,懒惰的评估——不,你还有什么——可能也没有)。

于 2013-05-25T06:52:17.247 回答
6

关于不变性的小例子:

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
}

您可以将 FP 与 Dart 甚至没有类型或不可变性的语言(如 JS)一起使用。它只是一种风格,不需要语言中的本机实现。

对于像 Scala FP 范式这样的语言,通常使用类型系统来实现,因此它更具限制性并且更难以无意中破坏。但同时你需要 lib 用户真正复杂的类型系统的专业知识,有时是类别理论 - 否则很难从知道这个东西是“monad”或“monoid”或其他什么中受益。我可以在不知道这些是单子或 Dart 中真正有用的“未来”概念的情况下使用列表。当您在没有“类型魔法”的情况下实现 FP 时,普通开发人员通常会更清晰、更容易掌握。但同时拥有强大的类型系统可以帮助编译器执行高级代码优化并实现更好的静态代码分析。

JavaScript 程序员的类别理论-值得一看。

补充:现在收藏有UnmodifiableListView UnmodifiableMapBase UnmodifiableMapView

于 2014-05-07T11:00:53.477 回答
5

最后一点,不变性,请参阅:

它为不可变集合和“值类型”提供库和代码生成支持。这些有助于弥合 OO 和函数式编程之间的差距,例如允许对不可变值进行内联“更新”:

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!');

其中“node”和“updatedNode”都是不可变的。本文中的更多详细信息:不可变对象模型的built_value

于 2017-03-29T11:24:35.803 回答
3

进一步提升 Dart FP 体验的包 https://github.com/vsavkin/fpdart

关于尾递归的公开问题 https://code.google.com/p/dart/issues/detail?id=29

于 2014-03-09T10:28:07.243 回答
3

似乎有一个更流行的解决方案,称为dartz

达兹

  • 以猫scalaz标准 Haskell 库为精神的类型类层次结构
  • 不可变的、持久的集合,包括 IVector、IList、IMap、IHashMap、ISet 和 AVLTree
  • Option、Either、State、Tuple、Free、Lens 和其他用于函数式编程的工具
  • 评估,读者+作家+状态+要么+未来的瑞士军刀单子
  • 包含类型以及几种标准 Dart 类型的类型类实例(Monoids、Traversable Functors、Monads 等)
  • Conveyor,纯功能流的实现
  • 示例,展示核心概念

我不明白如何使用它,但有例子。

于 2020-11-26T14:55:59.190 回答
1

您可以使用此包进行函数柯里化:https ://pub.dev/packages/functional

它还可以增加代码的可读性。

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

现在这个函数可以被柯里化如下。

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

  print(inc(5)); // Same as add(1, 5);
  print(dec(5)); // Same as add(-1, 5);
于 2020-06-17T10:07:06.633 回答