#312 Adding JavaFX Script features to Fan?

andrey Wed 23 Jul 2008

Hello,

Thanks to guy on Scala list who did introduce Fan to me and probably many others exploring alternative languages to bypass Java limitations.

Having some practical tasks in mind I found Fan to play great in the modeling space due to some of highlighted features (Declarative Programming, Dynamic Types, and Mixins). All these features have a big demand in modeling world, and Fan have a great potential to hit developers' minds: opposite to Scala's OO/FP positioning and features, most applications require strong modeling features and only a few have a strong FP demand.

From my (Fan newbie) standpoint, great modeling features is what I'm looking for in a new language and Fan offering is great among other languages I saw to date.

However, there is another beast from Sun you probably know: JavaFX Script. I do not know if Sun will make JavaFX Script as general purpose language, but in UI modeling it's definitely overplays others with some unique features: let me name a few for example:

Triggers

class X {
     attribute nums: Number*;
}

trigger on insert num into X.nums {
     System.out.println("just inserted {num} into X.nums at position {indexof num}");
}
var x = new X();
insert 12 into x.nums; // prints just inserted 12 into X.nums at position 0
insert 13 into x.nums; // prints just inserted 13 into X.nums at position 1

Incremental and Lazy Evaluation with bind operator

class X {
     attribute a: Number;
     attribute b: Number;
     attribute c: Number;
}

attribute X.a = 10;

attribute X.b = bind a + 10;
attribute X.c = bind lazy b + 10;


var x = new X();
System.out.println(x.a); // prints 10
System.out.println(x.b); // prints 20
System.out.println(x.c); // prints 30
x.a = 5;
System.out.println(x.a); // prints 5
System.out.println(x.b); // prints 15
System.out.println(x.c); // prints 25

These are very exciting features for UI programming, also brand new Microsoft's WPF technology introduced same trigger concept in XAML language for UI modeling.

Also type system in JavaFX is enriched with bidirectional links, see "inverse" clause in the following code:

class Person {
    attribute name: String;
    attribute parent: Person inverse Person.children;
    attribute children: Person* inverse Person.parent;
    function getFamilyIncome(): Number;
    function getNumberOfChildren(): Number;
    operation marry(spouse: Person);
 }

All of the above saves huge amount of time helping developer to focuse on the model instead of writing tons of code listening to model changes, setting inverse links, etc.

So I'm curious on Fan authors opinion regarding JavaFX Script features above, and possibility to implement some of them in Fan language? Together with (potential) possibility to compile to Adobe VM, Fan may become not only general-purpose language but also overplay others in RIA and Modeling spaces.

brian Wed 23 Jul 2008

Having some practical tasks in mind I found Fan to play great in the modeling

I do a ton of complicated modeling in my business, and I've suffered through how difficult building domain models in Java can be. So it is definitely a key driver for me (scratching my own itch).

I think a lot of what JavaFX is attempting to solve, Fan solves well with declarative and functional programming. If you look through some of the FWT demo code you can see it in action. For example a simple UI which prints to the screen when a button is pressed:

Window
{
  Button { text="Press Me"; onAction=|,| { echo("Pressed!") } }
}.open

Although I think you are really asking about the modeling aspects of JavaFX. To tell you the truth I haven't dug into them. Some of those concepts sound interesting - I need to research them. Although I think what goes into the core language needs to work for any type of model: relational dbs, document dbs, REST, OO, etc.

Together with (potential) possibility to compile to Adobe VM

This I most definitely want to happen. Everything about Fan is designed to be portable across VMs, including the library. I'm hoping this happens one day, although I'll probably never have time to do it. Looking at the Adobe VM bytecode I'm a little worried about some of the internals (for example I'm not sure they really support 64-bit primitives).

tompalmer Wed 23 Jul 2008

JavaFX features (all those listed above) would be sweet, but I agree that Fan being more general purpose, it might need slightly different solutions. I haven't thought through it in detail.

Also, I mentioned on a different thread that I think triggers should be part of a general AOP strategy.

tompalmer Tue 29 Jul 2008

By the way, to clarify JavaFX features, I like to think of it as being like a spreadsheet. In spreadsheets, a value can be just a value, or it can be a function of other values. Either way works.

So if Fan were the same, then Int x and |->Int| x would be equivalent. And x = 3 would be sort of like saying x = |->Int| {return 3}. And JavaFX's x = bind y + 2 would be like x = |->Int| {return y + 2}. Add automatic triggers to that and you get automatic data flow around your UI.

Data binding like that can be pretty sweet. Not to say that's how Fan should work. Just trying to clarify the relationship.

JohnDG Tue 29 Jul 2008

All this stuff is fallout from research done on functional reactive programming.

You wouldn't really need a lot of extra stuff to implement the ideas in Fan. Basically you just need support in FWT, and maybe a way to listen to changes in the value of any slot (not sure about that one).

You'd probably start by introducing DynamicVar, with subclasses DynamicBool, DynamicInt, etc. All properties of widgets could be assigned a DynamicVar, in which case any change in the variable propagates to the widget. Similarly, all properties of widgets (even read-only ones) are DynamicVar's. All DynamicVar's would have a method onChange that accepts a single-argument closure, which is passed the value of the variable, and is invoked whenever the variable changes (also when it's first added as a listener through onChange).

Then you do things like this:

normSlider := (slider.value - slider.min) / (slider.max - slider.min)

normSlider.onChange |Object value| {
   if (value < 0.25) label.text = DynamicString("Small")
   else if (value < 0.75) label.text = DynamicString("Medium")
   else label.text = DynamicString("Large")
}

Notice literals must now be wrapped in dynamic vars, because all properties of all widgets are dynamic vars and expect to be assigned to dynamic vars.

In the above example, if the slider changes, or if someone changes the min or max of the slider, then the label updates automatically.

Basically the style of programming eliminates the need for listeners -- what's left of the MVC pattern is the M and the V.

brian Tue 29 Jul 2008

I don't think you necessarily need to turn every value into a potential function. I think you just need a standard way to fire change events, and link those events to other methods/fields. Control systems have been graphically programmed this way for decades, and I've successfully used that model for both data flow and widget bindings. I just haven't had a good use case for this sort of stuff yet, but I'm sure it will be forthcoming.

If you've noticed the FWT design there isn't any java-bean like listener pattern - just callback functions.

JohnDG Tue 29 Jul 2008

I don't think you necessarily need to turn every value into a potential function. I think you just need a standard way to fire change events, and link those events to other methods/fields.

Yes, but the whole point of FRP is that you never need to fire change events, and you never need to link change events to methods/fields. :-)

One change to a widget propagates throughout the whole system, automatically. Even though FWT doesn't have listeners, people will be using callbacks for the same purpose.

JohnDG Tue 29 Jul 2008

One note: combined with my recent post to Wish List, you would no longer have to wrap fields in dynamic vars. My example becomes:

normSlider := (slider.value - slider.min) / (slider.max - slider.min)

normSlider.onChange |Object value| {
   if      (value < 0.25) label.text = "Small"
   else if (value < 0.75) label.text = "Medium"
   else                   label.text = "Large"
}

which is a lot cleaner.

I don't expect this stuff to make it into FWT but perhaps as a third-party library.

brian Tue 29 Jul 2008

Yes, but the whole point of FRP is that you never need to fire change events, and you never need to link change events to methods/fields.

I'm not suggesting that class developers have to fire change events or do the linking - I'm saying that language/framework takes care of those details. To give you an example: in the system I designed for my day job, all slots implicitly fire change events, check security context, and can be linked to other slots. It works quite nice, but I need something a little more general purpose for Fan. Although I haven't thought about how I'd do it in Fan, it would likely be some type of decorator plugin design.

JohnDG Tue 29 Jul 2008

Ah, I see. Look forward to seeing what you come up with!

tompalmer Tue 29 Jul 2008

I guess if the trigger stores the function, the slot itself doesn't have to. That makes sense.

andrey Thu 21 Aug 2008

Guys, thanks for comments. Tom's post regarding general AOP strategy sounds very attractive.

Probably every project relies on own or thirdparty framework to listen to model changes using JohnDG-alike classes, custom hand-made setters, or generated code like Eclipse Modeling Framework (EMF)... Everyone can provide a bunch of reasons why all of that sucks. What I'm dreaming about is to have better support for modeling at language level (not at framework level), either using AOP, specific language constructs (like JavaFX's bind), and/or provide templates for slot setters/getters to compiler (annotations driven?).

Fan really goes ahead with dynamic types, so I can add a filed with custom setter/getter code, this is great but do not look conceptually complete without having the same possibility for static type, what do you think on something like below:

class Person {
  @notify Str name;
}

...

@bind='notify'
class NotifyField : Field {
  ...
  Void set(Obj o, Obj v) { /* some code to access 'o' fields storage */; fireChg(...); }
}

This is of course not a replacement for AOP features, just a proposal to align static/dynamic typing in Fan.

brian Thu 21 Aug 2008

Andrey,

Probably six months ago I would have agreed that something just like @notify should exist in Fan and I would add it straight away. In fact most of the previous systems I've designed had that exact feature - to easily trap field sets and fire events, do verification, etc.

But now when I think about modeling, I'm thinking about how modeling works on highly concurrent systems - either 100s of threads or 100s of machines. Since the Fan memory model doesn't allow shared state, this problem needs to be rethought in terms of concurrency.

Shortly I will be starting a new project with Fan, and this issue is near and dear to my heart - so stay tuned. This stuff is going to get baked into Fan at a pretty core level.

andrey Tue 26 Aug 2008

Thank you for reply - I'll definitely stay tuned and this direction to highly concurrent systems is very exciting.

On a side note I'd like to say that "no shared state" != "no mutable objects", even in hihgly concurrent world actors often to be micro state machines dealing with isolated (internal) state.

Also if language support mutable fields (as Fan do), I guess developers would love to have better control on how this setters behaves either in dynamic or static scenarios.

This side note is just only to share concerns about Fan's concurrent features not to overshadow other domains, which are naturally modeled with shared objects and locking (like desktop UI).

Thank you again, and I'm anxiouly waiting for Fan updates.

Login or Signup to reply.