-1

学习函数式编程

我正在学习函数式编程。我决定使用元组在 Java 中进行尝试。

我阅读了 Sajal Chakraborty 的Java tuple – Working with tuples in Java并决定创建一些示例。Java 天生不包含元组功能。所以我安装了javatuples库。

函数式编程的好处

函数式编程的好处是无可争辩的。

  • 不可变对象在系统中传递时不会被修改——更好的并发性和并行性¹。
  • 更快的原型设计/更简洁——无需创建臃肿的样板填充 POJOs²。
  • 没有副作用——函数输出取决于输入³。
  • 简单易用的单元测试——无需担心按特定顺序调用函数或设置外部状态⁴。

事实上,Erik Meijer 在他的 edX 课程《函数式编程简介》中认为,函数式编程“允许以高层次抽象清晰、简洁地编写程序”。

但是,我正在为元组的基于索引的性质而苦苦挣扎。他们对我来说似乎不太清楚。

GPS 坐标示例

以一个接受并保存 GPS 坐标的虚构应用程序为例。

面向对象的版本

遵循面向对象编程 (OOP) 范式,您将创建一个 Java 对象。

public class Coordinates {
  private Double lat;
  private Double lng;

  public Coordinates(Double lat, Double lng) {
    this.lat = lat;
    this.lng = lng;
  }

  public Double getLat() {
    return lat;
  }

  public Double getLng() {
    return lng;
  }
}

然后,您将创建一个服务来保存坐标。

public class CoordinatesService {

  public static void saveCoordinates(Coordinates coordinates) {
    double latitude = coordinates.getLat();
    double longitude = coordinates.getLng();

        // Save the coordinates (before they are lost forever! ;))
  }
}

最后,您将创建新坐标并将它们传递给服务。

Coordinates coordinatesWithPojo = new Coordinates(34.90011, 46.62922);
CoordinatesService.saveCoordinates(coordinatesWithPojo);

函数式编程版本

遵循函数式编程范例(使用元组),您将创建一个服务来保存坐标。

public class CoordinatesService {

  public static void saveCoordinates(Pair<Double, Double> coordinates) {
    double latitude = coordinates.getValue0();
    double longitude = coordinates.getValue1();

        // Save the coordinates (before they are lost forever! ;))
  }
}

然后您将创建新坐标并将它们传递给服务。

Pair<Double, Double> coordinatesWithTuple = Pair.with(34.90011, 46.62922);
CoordinatesService.saveCoordinates(coordinatesWithTuple);

默默无闻的权衡?

虽然功能版本更简洁,但 OOP 版本似乎更清晰。在IntelliJ IDE中访问Coordinates对象时,很清楚该对象是由什么组成的。Coordinates

但是,当我访问元组中的字段时,它们会被索引遮挡。

很难知道哪个索引与纬度和经度相关联。如果他们不小心被调换了怎么办?这是一个简单的例子。但是这个问题随着元组中参数数量的增加而增加。

甚至参数注解在 OOP 版本中也更加清晰。

面向对象版本

功能版

问题

  • Java 元组创建晦涩的事实是坚持函数式编程范式的权衡吗?
  • 这是函数式编程的一般权衡吗?
  • 如果这是真的,这难道不是一个好的抽象的反面——创造人类理解和推理的清晰简洁的语言和意义吗?

注意:我有函数式编程的基本知识。这意味着我仍在学习如何构建关于该主题的问题和论点。因此,我很乐意接受有关问题本身的任何反馈。我的目标是更多地了解函数式编程——而不是陷入激烈的争论。


来源

¹ Java 8 in Action
²函数式编程简介
³函数式编程 HOWTO
⁴<a href="https://www.defmacro.org/2006/06/19/fp.html" rel="nofollow noreferrer">函数式编程我们其余的人

4

2 回答 2

1

Pair(或Tuple)是匿名的,如你所说的那样被索引。但是函数式编程也会调用以下函数

public class Coordinates {
  public final double lat;
  public final double lng;

  public Coordinates(double lat, double lng) {
    this.lat = lat;
    this.lng = lng;
  }

  public Coordinates translate(double dlat, double dlng) {
      return new Coordinates(..., ...);
  }
}

BiFunction<Coordinates, Coordinates, Coordinates> f = Coordinates::translate;
Coordinates c1 = f.apply(c2, c3);

这个版本的坐标是不可变的(最终字段),因此适合作为 FOP 类。

于 2019-09-30T16:04:33.757 回答
0

您的问题非常相关,当我想在 java 中使用 FP 时,我不得不面对这类问题。首先,Java 中没有函数式编程,因为 Java 不满足 FP 范式条件。

例如。java中的第一个公民是对象而不是函数

没有高阶函数,因此方法属于一个类

不可能在 java 上进行 currify,糟糕的选择是调用一系列方法,但与 myFunction(p1)(p2)(p3) 完全不同

如果您想训练和/或使用 FP,我建议使用具有 FP 范式的语言,例如 Javascript、Kotlin Scala 或 Haskell。

对不起我的英语不好,我希望它会有所帮助

于 2019-09-30T16:03:04.980 回答