5

我最近看到了这个关于 Elm 反应式编程的有趣演示。

这让我想知道用于实现马里奥游戏的语言结构(在显示的演示文稿中,以及在下图中)是否可以映射到纯 JavaFX 或结合 RxJava 的 JavaFX 中的类似高级语言结构?

换句话说,是否有可能在单独的 JavaFX 或 JavaFX+RxJava 中使用相同的概念抽象(即时间相关值)来表达在 Elm 中实现的马里奥游戏?

因此,如果有经验的 1)JavaFX 程序员或有经验的 2)JavaFX+RxJava+Functional 程序员想要将马里奥游戏从 Elm 移植到 1)JavaFX 或 2)JavaFX+RxJava,那么哪个程序员可以通过使用类似的高Elm 中使用的级别抽象?

我想到的 JavaFX 的抽象是绑定,而 JavaFX+RxJava 的抽象是绑定+Observables/Subjects/Subscription。

在此处输入图像描述

4

4 回答 4

7

我快速浏览了 Elm,它给人留下了深刻的印象(并且富有表现力)。

在 Elm 中,您将场景构建为

Signal Element

在 JavaFX 中大致相当于

ObservableValue<Node>

对 JavaFX 的幼稚转换意味着您在每次更新时交换整个场景,这是非常昂贵的。在 Elm 中,Element是场景节点的不可变抽象表示,在屏幕外(DOM 外)构建。在每次更新时重新创建整个场景图是足够便宜的(由于不变性,重用未更改的分支是安全的)。根Element被渲染到 DOM,但是,据我所知,只有第一次构建完整的 DOM。在随后的更新中,Elm 运行时会运行一种算法来比较新根元素和旧根元素,并且只修改 DOM 中需要更新的那些部分,这已经足够快了。React.js使用了相同的技术. 因此,Elm 和 React.js 都提供了高级功能抽象,但出于性能原因,在后台使用了可变性。

使用一些额外的语法噪音,您可以将大多数 Elm 构造转换为 JavaFX (*)。例如,

lift2 display Window.dimensions gameState

相当于

import static org.fxmisc.EasyBind.*;

combine(Window.dimensions, gameState, display)

缺少的部分是不可变的抽象小部件表示库以及它们在 JavaFX 场景图中的有效呈现。

你可以做的是:

  • 为 JavaFX 创建这样一个小部件库;
  • 甚至将 Elm 编译为 JavaFX(而不是 HTML+JavaScript)。

我很想看到其中任何一个完成。


(*) 我认为 Elm记录非常强大,在 Java 中需要大量样板文件(或斯卡拉).

榆树:

type Point = { x:Float, y:Float }

p = { 0.0, 0.0 }
q = { p | x <- 5.0 }

爪哇:

class Point {
    public final float x;
    public final float y;

    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }

    public Point updateX(float x) {
        return new Point(x, y);
    }

    public Point updateY(float y) {
        return new Point(x, y);
    }
}

Point p = new Point(0.0, 0.0);
Point q = p.updateX(5.0);

斯卡拉:

case class Point(x: Float, y: Float)

val p = Point(0.0, 0.0)
val q = p.copy(x = 5.0f)
于 2014-05-29T23:54:42.940 回答
4

我说这是可能的,但实际上并没有这样做:-)

这只是一个猜测,因为我在这个领域几乎没有经验,而且根本没有使用 Elm。

我认为您将通过为ReactFX创建一个 ScalaFX 包装器来最接近 Elm ,尽管您可能也可以将 Java 8 lambdas 与 ReactFX 而不是 Scala 结合使用。您可能需要对 ReactFX 以及各种其他工具实现相当多的扩展才能获得您想要的抽象和优雅。

如果您还没有这样做,请查看Deprecating the Observer Pattern 。我认为它与这个主题非常相关,特别是在考虑反应式编程模型而不是可观察模型(这就是 JavaFX ChangeListeners)方面。也就是说,我认为如果您使用诸如 ReactFX 等基于 JavaFX 属性和侦听器框架构建的库,那么您最终可能会得到对响应式编程有用的更高级别的事件流抽象。

当然,您可以在不使用 ReactFX 的情况下在 JavaFX 中制作马里奥游戏,但代码会完全不同,并且您将在与使用 ReactFX 的抽象级别不同的抽象级别上工作。因此,没有 ReactFX 的纯 JavaFX 将不像 Elm 那样。

对于网络层,akka可用于为多人游戏提供反应式框架,这将允许您在 UI 和通信系统中从上到下使用反应式编程。

对于马里奥示例中的 Sprite 动画,采用使用 JavaFX 创建 Sprite 动画的 netopyr 代码。

对于物理计算,您可以使用JBox2D库。您需要围绕 JBox2D 创建某种反应式包装器,以使其了解 JavaFX 属性和 ReactFX 事件流和订阅等内容。对于简单的马里奥样本,使用外部库可能比它的价值更麻烦。相反,您可以使用一个基本的自制物理模型(例如这个球动画实验之类的东西)并将其连接到您的反应框架中。

我建议与创建 ReactFX 的 Tomas Mikula 取得联系,并向他询问有关 JavaFX 问题的反应式编程。Robert Ladstätter还用 ScalaFX 做了一些很酷的事情,也许能给你一些进一步的建议,尽管我不知道他是否使用过响应式编程。我还建议 ping ScalaFX 用户论坛,但我看到你已经这样做了 :-)

Elm Mario 示例非常简单,因此我建议您自己尝试翻译成 ReactFX。那么我认为你的问题的答案将是不言而喻的。既然我已经写了这个 => 如果你没有真正实现它并将你的解决方案发布为正确的答案,我可能不得不追捕你,你不会想要那个 :-)

于 2014-04-01T20:41:15.837 回答
4

我目前正在为我的硕士论文比较传统的面向对象的 GUI 编程和函数式 GUI 编程。事实上,我即将开始的一部分是使用 Elm 在 JavaFX/ScalaFX 中重新创建许多传统的 GUI 程序。完成后,我可能会给出更准确的答案,但我现在仍然想提供一些普遍有用的指针。


首先,有两篇很好的论文提供了 FRP 领域的概述,即“A Survey on Reactive Programming”</a> 和“Towards Reactive Programming for Object-oriented Applications”</a>。尤其是前者,提供了 FRP 系统的分类法,区分了“FRP 的兄弟姐妹”和“FRP 的表亲”(暗示他们与Fran的想法有血缘关系)。FRP 的兄弟姐妹专注于时变值,FRP 的堂兄弟专注于事件流、可观察集合和异步,并且没有用于表示时变值的原始抽象。考虑到这一区别,Elm 是 FRP 的兄弟,RxJava/ReactFX 是 FRP 的表亲. 我想你可以说它们是不同的动物,即使它们都是 FRP 系统并且自然有重叠。

其次,论文“Crossing State Lines: Adapting Object-Oriented Frameworks to Functional Reactive Languages”</a> 对 Elm 中的 FRP 方法与 JavaFX 中的传统 OOP 方法之间的差异进行了非常简洁的总结:

OO 使状态显式但对其进行封装,而 FRP 中的状态通过语言的时间抽象对程序员隐藏。

因此,程序设计有一种根本不同的方法。因此,对我来说,尚不清楚是否以及如何使用 JavaFX(+RxJava/ReactFX)实现与 Elm 一样的“相同”高级抽象。这并不意味着它不可能,但乍一看并不明显。

最后,与我的论文中的传统 OOP 方法相比,对 Elm 及其极端“异化”的一般观察,以使在 JavaFX 中实现相同结果的障碍更加清晰:

许多 GUI 库,即使是纯函数式语言,本质上也是(命令式)面向对象的 GUI 工具包上的薄垫片。例如,这意味着小部件不是纯函数。小部件具有状态,因此具有身份。如果我们隐喻地把 GUI 工具包控制板上的功能旋钮调到最大值,我们必须达到一个情况,即使小部件也只是纯函数。Elm 就是这样一个同时具有最大功能的语言和 GUI 工具包的例子。由于回调都是关于副作用的,Elm 自然不会对与行为相关的代码使用回调,而是使用 FRP。在 OOP 语言中的定制最常通过继承来实现,而在 Elm 中只有函数组合的方式......

关键在于,在 Elm 中,视图是纯函数,基本上,Elm 会强制您以这种方式构造代码。在 JavaFX 中,您不是被迫的,因此您必须刻意注意去做。

顺便说一句,像马里奥这样的榆树游戏有一个游戏骨架。您可以研究它并考虑如何按照这个框架设计您的 JavaFX 程序。也许您在学习后甚至可以为 JavaFX 创建这样的骨架?我会对它感兴趣。

于 2014-05-28T10:27:58.953 回答
2

我一年前就提出了这个问题。从那时起,我对 FRP 了解了一两件事。我认为答案是否定的,至少使用 RX 不容易,使用 JavaFX+ Sodium FRP库会好得多。

为什么不能(很容易)使用 RX ?因为 ELM 是 FRP,而 RX 是 FRP减去事务(模糊地说)。所以实际上,如果有人想在 ELM 中实现马里奥游戏,那么她必须向 RX 添加交易(以避免故障)。

于 2015-07-08T16:25:20.960 回答