Is it possible to translate the Mario example from Elm to either pure JavaFX or to JavaFX+RxJava while preserving the high level abstraction of Elm?

StackOverflow https://stackoverflow.com/questions/22795062

Question

I've recently seen this interesting presentation about reactive programming in Elm.

This made me wonder whether the language constructs used to implement the Mario game (in the shown presentation, and also in the picture below) can be mapped to similar high level language constructs either in pure JavaFX or in JavaFX combined with RxJava ?

In other words, would it be possible to express the Mario game implemented in Elm using the same conceptual abstractions (i.e. time dependent values) in either JavaFX alone or in JavaFX+RxJava ?

So if an experienced 1) JavaFX programmer or an experienced 2) JavaFX+RxJava+Functional programmer wants to port the Mario game from Elm to either 1) JavaFX or to 2) JavaFX+RxJava then which programmer could accomplish this task by using similar high-level abstractions as was used in Elm ?

The abstractions I have in mind for JavaFX are bindings and for JavaFX+RxJava are bindings+Observables/Subjects/Subscription.

enter image description here

Was it helpful?

Solution

I had a quick look at Elm and it is quite impressive (and expressive).

In Elm you construct your scene as

Signal Element

which in JavaFX would be roughly equivalent to

ObservableValue<Node>

Naive translation to JavaFX would mean that you swap the whole scene on each update, which is prohibitively costly. In Elm, Element is an immutable abstract representation of a scene node, constructed off the screen (off the DOM). It is cheap enough to recreate the whole scene graph on every update (because of immutability, it is safe to reuse unchanged branches). The root Element is rendered to DOM, but, as I understand it, only the first time the full DOM is constructed. On subsequent updates, Elm runtime runs an algorithm to compare the new root element to the old one and only modifies those parts of the DOM that need updating, which is fast enough. The same technique is used by React.js. So both Elm and React.js provide high-level functional abstraction, but use mutability under the covers for performance reasons.

With some additional syntactic noise, you can translate most Elm constructs to JavaFX (*). For example,

lift2 display Window.dimensions gameState

is equivalent to

import static org.fxmisc.EasyBind.*;

combine(Window.dimensions, gameState, display)

The missing piece is the library of immutable abstract widget representations and their efficient rendering into JavaFX scene graph.

What you could do is:

  • create such a widget library for JavaFX;
  • or even compile Elm to JavaFX (instead of HTML+JavaScript).

I would love to see either of those done.


(*) I think Elm records are very powerful and would require a lot of boilerplate in Java (or Scala).

Elm:

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

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

Java:

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

Scala:

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

val p = Point(0.0, 0.0)
val q = p.copy(x = 5.0f)

OTHER TIPS

I say it is possible, without actually doing it :-)

This is only a guess as I have little experience in this field and none at all with Elm.

I think you will get closest to Elm by creating a ScalaFX wrapper for ReactFX, though you could probably also use Java 8 lambdas in combination with ReactFX rather than Scala. You will likely have to implement quite a few extensions to ReactFX as well as various other facilities to get the abstractions and elegance you desire.

Checkout Deprecating the Observer Pattern if you have not already done so. I think that it is quite relevant to this topic especially with regards to thinking about a reactive programming model as opposed to an observable model (which is what JavaFX ChangeListeners are). That said, I think if you use libraries such as ReactFX which are built upon the JavaFX property and listener frameworks, then you likely end up with the higher level abstraction of event streams that are useful for reactive programming.

Sure, you could make a Mario game in JavaFX without using ReactFX, but the code would be quite different and you would be working at a different level abstraction to that which you would be using with ReactFX. So pure JavaFX, without ReactFX would be less Elm like.

For a network layer, akka could be used to provide a reactive framework for multi-player games, this would allow you to use reactive programming top to bottom, both in your UI and in your communications system.

For the Sprite animations in the Mario sample, adopt the netopyr code for Creating a Sprite Animation with JavaFX.

For the physics calculations you could use the JBox2D library. You would need to create some kind of reactive wrapper around JBox2D to make it aware of stuff like JavaFX properties and ReactFX event streams and subscriptions. For the simplistic Mario sample, use of an external library would probably be more trouble than its worth. Instead you could use a basic home grown physics model (e.g. something like this ball animation experiment) and hook it into your reactive framework.

I advise getting in touch with Tomas Mikula, who has created ReactFX, and asking him your reactive programming for JavaFX questions. Robert Ladstätter has also done some cool stuff with ScalaFX and might be able to give you some further advice, though I don't know if he's worked with Reactive programming at all. I'd also suggest pinging the ScalaFX users forums, but I see you've already done that :-)

The Elm Mario sample is pretty simple, so I advise trying the translation to ReactFX yourself. Then I think the answer to your question will become self-evident. Now that I've written this => if you don't actually implement it and publish your solution as the correct answer, I might have to hunt you down and you wouldn't want that :-)

I'm currently comparing traditional object-oriented GUI programming with functional GUI programming for my master's thesis. In fact, one part that I am about to begin before long is using Elm to recreate a number of traditional GUI programs in JavaFX/ScalaFX. When I'm finished with that I will probably be able to give a much more precise answer but I still want to provide some generally useful pointers now.


First, there are two good papers that provide an overview of the FRP landscape, namely “A Survey on Reactive Programming“ and “Towards Reactive Programming for Object-oriented Applications”. The former, in particular, provides a taxonomy of FRP systems that distinguishes “Siblings of FRP” and “Cousins of FRP” (alluding to their kinship to the ideas of Fran). Siblings of FRP focus on time-varying values, Cousins of FRP focus on event streams, observable collections and asynchrony and don't have primitive abstractions for the representation of time-varying values. With that distinction in mind, Elm is a Sibling of FRP and RxJava/ReactFX is a Cousin of FRP. I guess you could say they are different animals even though both are FRP systems and have overlaps, naturally.

Second, the paper “Crossing State Lines: Adapting Object-Oriented Frameworks to Functional Reactive Languages” provides a very nice and succinct summary of the differences between the FRP approach as in Elm and the traditional OOP approach as in JavaFX:

OO makes state explicit but encapsulates it, whereas state in FRP is hidden from the programmer by the temporal abstractions of the language.

So there is a fundamentally different approach to program design. Therefore, to me it is not yet clear if and how you can achieve the “same” high-level abstractions with JavaFX(+RxJava/ReactFX) as with Elm. That does not mean it is not possible but it is not obvious on the first glance.

Finally, a general observation about Elm and its extreme “alienness” compared to the traditional OOP approach from my thesis to make the obstacles in achieving the same result in JavaFX clearer:

A lot of GUI libraries even in pure functional languages are essentially a thin shim over an (imperative) object-oriented GUI toolkit. This means, for example, that widgets are not pure functions. Widgets have state and therefore an identity. If we metaphorically turn up the functional knob on a GUI toolkit's control board to its maximal value we must arrive at a situation where even the widgets are nothing but pure functions. Elm is such an example of a maximally functional language and GUI toolkit at the same time. As callbacks are all about side-effects Elm naturally does not use callbacks whatsoever for behavior-related code but instead FRP. Where customization in a OOP language is most often achieved with inheritance, in Elm there is only the way of function composition...

The key point is that in Elm the views are pure functions and, basically, Elm forces you to structure the code this way. In JavaFX you aren't forced so you must deliberately take care to do it.

By the way, there is a game skeleton for Elm games like Mario. You can study it and think about how you would design your JavaFX program following this skeleton. Maybe you could even create such a skeleton for JavaFX after your studies? I'd be interested in it.

I've posed this question a year ago. Since then I have learned a thing or two about FRP. I think the answer is no, at least not easily with RX, it would be much better to use JavaFX+Sodium FRP library.

Why not (very easily) possible with RX ? Because ELM is FRP, while RX is FRP minus transactions (vaguely speaking). So practically, if someone would want to implement the Mario Game in ELM then she would have to add transactions to RX (to avoid glitches).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top