Planet JFX

This a proposal; it is designed to work in conjunction with Tuples_and_Maps and optionally Patterns.

There is an alternative proposal Sequences_are_Tuples, which shares some ideas, but is different.

An array is a function from a sub-range of integer to objects. For now I assume arrays are immutable.

A tuple is an ordered list of items. (An item is any object, value, or array, but a non-singleton tuple is not an item.) Tuples are flat: they do not nest. A tuple with a single item is the same as that item. Tuples are like the previous concept of sequences, but are not indexable. Tuples aren't first-class: you don't (can't?) store a tuple in a variable; they are just intermediate values.

Comma is a binary operator for constructing tuples.

1,2 ==> a tuple with two values
1,2,3 ==> a tuple with 3 values

Comma is associative:

1,2,3 is the same as (1,2),3 or 1,(2,3)

The zero-item tuple is written: () The zero-item tuple is the same as the "void value".

A function argument list is a tuple; more details later. A function can return a tuple:

 function divide (x, y) { .... return (quot, rem) }

Tuples can be specified in declarations:

 var (q, r) = divide(x,y)

For more details, see Patterns.

The square-bracket operator converts a tuple to an array.

[1,2,3] an array with 3 items

An array is indexable, using the same syntax as function call:

 let a = [1,2,3];
 a(2) ==> 3

(This allows you to simulate arrays with functions or vice versa. It also avoids confusingly overloading the [] syntax, which is now just for array *construction*.)

The @-operator is the inverse of the []-operator: It takes an array and converts it to a tuple:

 @([1,2,3]) ==> (1,2,3)

An important usage is concatenation:

 [@arr1, @arr2] ==> the concatenation of arr1 and arr2.
 let arr1 = [2,3,4];
 let arr2 = [10,11];
 [9, @arr1, 12, @arr2, 99] ==> [9,2,3,4,12,10,11,99]

Range tuples:

 2..5 ==> (2,3,4,5)

Commonly used within []:

 [2..5] ==> [2,3,4,5]
 [-1,2..5,10] ==> [-1,2,3,4,5,10]

Currently jfx allows [1,3..10] ==> [1,2,5,7,9] We could allow that, but I'm inclined to not special-case that.

Looping[]

 for (id in arr) body

Evaluate arr, then for each item set id to that item, and evaluate body. Result is the *tuple* (not array) of values from body:

 [for (i in [3,4,5]) { 2 * i }] ==> [6,8,10]
 for (id1 in arr1, id2 in arr2) body

is syntactic sugar for:

 for (id1 in arr1) for (id2 in arr2) body
 [for (i in [10,20], j in [1,2,3]) (i+j)] ==> [11,12,13,21,22,23]
  for (i in [1..3], j in [0..i]) (10*i+j)
   ==> (10, 11, 20, 21, 22, 30, 31, 32, 33)

While[]

 for (val in arr) while (cond) body

Same, but evaluate cond on each iteration and stop when false:

 for (i in [2,4,6]) while (i < 5) (i+10) ==> (12,14)

A while expression:

 while (cond) body

Is the same as:

 for (dummy in [0 .. infinity]) while (cond) body

The index of the current iteration can be accessed using indexof as in the current spec. Or we camp use "pair syntax" (later).

Back to OpenJFX Compiler.


Comments[]

I am not sure how having tuples makes it easier to write declarative UIs. Perhaps you could provide an example. I'm not sure that having maps is necessary or advisable, either. A common use of something like a map might be lookup in a UI, where we want to find the zip codes for a state. In the example below we just indicate what we want, and leave it up to the compiler or runtime to figure out the best way to implement it.

import javafx.ui.*;

class State {
   attribute name: String;
   attribute zipcodes: String*;
}

var states = [
State { name: "VA", zipcodes: [ "90101", "70101", "90101" ]}, 
State { name: "MD", zipcodes: [ "50101", "20101", "30101" ]}
]; 

Frame {
   var edit = TextField { value: "VA" }
   var currentState = bind select s from s in states where s.name == edit.value
   var zips = bind select " {z} " from z in currentState.zipcodes 
   width: 400
   content: Box {
       content: [
       Label { text: "State:" },
       edit,
       Label { text: bind "Possible zipcodes: {zips}" }
       ]
   }
}