More about F3
By user12610627 on Jan 22, 2007
But I am posting this in the spirit of LtU as expressed by Ehud Lamm (the originator of LtU)
Note that from the perspective of LtU the expressiveness of the language constructs is the main thing, implementing them as efficiently as possible comes second: efficient implementation should be possible, but might still not exist in the marketplace.
The above quote is also very close to my original approach when I started F3. I knew from using Tcl/Tk in the mid-90's that high performance from F3 wouldn't be required for the vast majority of graphical user interface use cases. With Tcl/Tk all of the Tk widgets as well as my back-end code was implemented in C and Tcl was used simply to glue them together. And at that time Tcl was probably one of the slowest interpreters ever written as it actually reparsed the source code on every evaluation. So efficiency of the programmer in expressing such programs was my focus.
Although I don't think there's anything particularly innovative in F3 from a programming language point of view, my experience has been that the combination of features it provides proves more effective in expressing graphical user interface programs than other systems I've encountered (your experience may be different than mine). The language itself is only part of that. The libraries which provide useful abstractions for Widgets and 2D graphics and which, in particular, closely match the concepts used by graphic artists and content designers are also equally important.
Unfortunately, not having a background in math or formal logic, F3 doesn't have a formal basis. Prior to programming my primary interest was linguistics, so a lot my of opinions about what makes programming languages "expressive" comes from my observations and opinions about what allows us effective expression in natural languages.
Although I'm concerned that F3 may have fundamental flaws that haven't been exposed yet, I don't feel too bad about lacking a formal basis for F3, since to be honest I really never intended to write a programming language in the first place.
The F3 project was originally called GBTDS which stood for "GUI Builder That Doesn't Suck". I just wanted an easy way of creating GUI's.
I thought I could just create some visual tools where I allowed the user to define an object-oriented model, and then have them lay out widgets on the screen and somehow bind them to the model using a "stylesheet". My implementation of the model would automatically generate events whenever it changed and automatically update the widgets. Anyway, I originally wrote a working prototype of something like this (but without the visual tools). Unfortunately, it was a still a GUI builder that sucked.
There was always an impedance mismatch between the application model and the widgets and no effective way to really connect them together. I always had to add lots of extra attributes to the model as placeholders for things needed for the views or "hard-code" the styling. For example, if I had a Person class with a firstName and lastName attribute and I wanted to show a person's full name in the view, I had to add a fullName attribute to the model (and then write event handling code in Java to update it whenever firstName or lastName changed) in order to have something to bind the view to. In addition, each widget had to have special event handling plumbing to hook up to the model and special styling plumbing to hook up to the stylesheet, all written in Java (and there are quite a few widgets in Swing...).
It was obvious I needed a query language to project the model into a form that was suitable to bind to the widgets. So that's what I implemented next. Early on I recognized I needed dependency based evaluation of the query language to handle changes to the model. In the early versions this wasn't incremental, but rather reevaluated the entire query whenever any of its dependencies changed. I could reference such queries in the stylesheet and it was now much easier to express the styling of widget attributes. However, I still didn't have any reasonable way of expressing the structure and layout of widgets, and all the updates to the model had to be done through Java API's to my model (which was similar to programming through reflection, i.e. extremely tedious).
So next I added a procedural language, which used Java-like control structures and borrowed the update syntax from XQuery. This made it very easy to update the model compared to what I had before. In addition, I added support for list comprehensions to the query language (foreach, select) which allowed me to also declaratively project multi-valued attributes. Having all that I realized my "stylesheet" was really just the interface to the Widgets. So I ditched it and my Java Widget library, and wrote a set of F3 classes that wrapped the Swing widgets. Having done that I could pretty much write any Swing program declaratively all in F3. At that point I also implemented incremental dependency-based evaluation.
Although I could write any Swing program pretty easily there was obviously a large class of GUI's that I couldn't produce (including most of the demos you see on my weblog). So it was obvious I needed a declarative interface to Java2D as well.
Fortunately, a very talented young man, Jesse Grosjean, had written an excellent 2d scene graph toolkit based on Java2D called Piccolo. The conceptual model of Piccolo was very close to SVG, and I realized I could fairly easily implement F3 versions of SVG's declarative 2D graphics interfaces using Piccolo.
Once I had that, I could pretty much create any GUI or visual effect you find in Flash, Java, DHTML, or elsewhere, declaratively in F3 and started writing the demos you see today.
Anyway, as I said my original thinking was that I wanted an easy way of creating Model/View GUI's. To that end I wanted a simple, object-oriented system. The informal conceptual basis for this I borrowed from Martin and Odell.
To summarize the important points (informally):
- Classes correspond to the concepts we use to identify the common characteristics of the things around us and how they relate to each other.
- Thus a class declares a set of potential relationships (links) between objects.
- Once an object has been classified we can navigate those relationships to discover its properties, i.e. the other objects related to it.
- In F3 these properties are called
- In F3
functions are queries that navigate links or produce new objects in terms of existing ones, but do not modify the links of existing objects.
- In F3 all change consists of adding new objects or of adding, removing, or replacing the links between existing objects.
- In F3 Events are simply notifications of object instantiation or of "link addition", "link removal", or "link replacement"
- In F3
operations in addition to performing queries can sequentially perform one or more such link modifications. Such modifications may be sequenced with conditional logic and by selection and iteration over query results.
- The values of an object's attributes may be specified either through explicit assignment or by means of a bound query. In the latter case implicit modification of the attribute occurs whenever the inputs to the query expression change and produce a new result.
- So when a change occurs one way to specify the "effect" is to define a bound query that expresses how other objects depend on it.
- The other way to respond to change is by making further explicit modifications using
triggeris an operation that is performed whenever an insert, delete, or replace event which applies to it occurs.
F3 is still a work in progress.
When F3 is open-sourced the syntax of the language and API's will be open for discussion and change.