concatenative gui?
stevan apter — 2004-09-11 16:15:45
i asked slava if he had given any thought to gui in factor.
let me describe how we (the k programming community) have
tackled the problem, and how i imagine something similar
could be engineered for factor.
the platform in which the approach was first developed was
A+ (http://www.aplusdev.org). The original, GUI-less version
of the language was designed and implemented by arthur whitney
at morgan stanley. The "+" part consisted of an interprocess
communications facility (dan fisher) and a gui (myself and
jeffrey birnbaum.)
A was the first high-performance APL, developed to meet the
requirements of the automatic program trading group at morgan.
APL was too slow and development in C was insufficiently
agile. Later, when the work shifted from automatic trading
to interactive applications in fixed-income trading and
sales, we developed the A+ gui.
The central idea of the gui is that windows are views of
global variables. For example, given a vector, say
V <- 10 20 30
the view of V is a window
V
-
10
20
30
if V or any part of V changes under assignment:
V[0] <- 12
then the window is updated to reflect the change:
V
-
12
20
30
and if the user edits a cell in V:
V
-
12
13
30
then the global variable V is updated to reflect the edit:
V = 12 13 30
in other words, window edits are semantically identical to
assignment of a value to a cell in V.
to complete the programming model, we provide global variable
attributes, the most important of which are f, g, t, and d.
f is a function which takes a value from V and returns a string.
g is a function which takes a string and returns a value to V.
t is a function which executes when a value is assigned to V.
d is a function which executes when V is referenced *and is in
the unmarked state*.
suppose A is 10 and B has the d attribute {A+10}, the function
of no arguments which returns A+10. Suppose you now assign A:
A <- 12
B is marked "invalid". the next time you reference B, its d is
executed and returns 22 = 12+10. this is the new value of B,
which is remarked "valid".
if A and B are both on the screen, and the user edits A, the
value he enters is a string which will be run through A's g
attribute. The value is assigned to A. B is marked invalid
and its d attribute is executed, giving B a new value. B's
f attribute is run, yielding a string which is written to the
screen.
an application consists of a set of global variables, some of
which are mapped to the screen, mediated by f and g functions.
moreover, variables are functionally related through their t
and d functions.
all side-effects of window-based events eventually reduce to
function-calls involving the assignment of global variables.
an event, such as a window-click, results in the execution of
a functional attribute. these are classical callbacks.
all window properties are first-class and functional. for
example, the color of a cell is the result of the interpreter
calling a functional attribute of the variable. we coined
the term "callforward" for functions of this kind.
k's native gui takes a similar approach.
at our firm, we've taken this model and implemented another
gui for k, writing the widget toolkit in swing. for example,
consider the following example.
we want a window, incdec, which contains an numeric value
and two buttons: inc, which increments the value, and dec,
which decrements it. we want incdec to have the following
appearance:
num: 10
[ inc ] [dec ]
we say:
incdec.num:0
incdec.inc:{num+:1}
incdec.dec:{num-:1}
incdec.inc..c:`button
incdec.dec..c:`button
incdec..c:panel
incdec..a:(`num;`inc`dec)
incdec is a dictionary (namespace) containing three variables:
num, inc, and dec. we say that the semantic model for a
button is a function, which we write in k with curly braces.
"x.y" refers to variable y in dictionary x. "x..y" refers
to attribute y of variable x. the "c" attribute specifies
the class of the variable. the "a" attribute is a list
whose structure describes the arrangement of variables in
a panel, and `x is a symbol denoting the variable x.
k dictionaries are more complex than standard namespaces. we
say that the elements of a dictionary are triples: a name,
a value, and a dictionary of attribute variables. so if d
is a dictionary containing a variable v with value 12, and v
has attributes x with value `red and y with value {x+y}, then
d has the structure:
[ v 12 [ x `red emptydictionary ]
[ y {x+y} emptydictionary ]]
syntactically, we say:
d.v 12, the value of d.v
d.v..x `red, the value of d.v's x attribute
d.v..y {x+y}, the value of d.v's y attribute
hence, dictionaries are recursive in two dimensions:
variables can be dictionaries, and attributes can have
attributes.
now it seems to me that since factor has namespaces, it
should be possible to design a data-driven gui along
similar lines. Two-dimensional namespaces are useful,
but not indispensable: we can say that every screen
variable is a namespace, and that the value of a
screen variable is always found in the $value variable
within that namespace; everything else in the namespace
is an attribute:
v.$value
v.color
v.font
instead of
v
v..color
v..font
Slava Pestov — 2004-09-13 04:00:13
stevan apter wrote:
> The central idea of the gui is that windows are views of
> global variables. For example, given a vector, say
>
> V <- 10 20 30
>
> the view of V is a window
>
> V
> -
> 10
> 20
> 30
Does the window reflect the object stored at V, or the variable V? The
fact that you have it titled with the variable name reflects the latter.
Is there a distinction between the two even, given (as I understand it)
K's call by value semantics?
> if V or any part of V changes under assignment:
>
> V[0] <- 12
How are notifications managed?
> f is a function which takes a value from V and returns a string.
> g is a function which takes a string and returns a value to V.
I guess these are similar to Factor's parsing and prettyprinting words.
They are not currently polymorphic (they're implemented as a series of
conditionals) however I intend to develop a form of polymorphism later.
> now it seems to me that since factor has namespaces, it
> should be possible to design a data-driven gui along
> similar lines. Two-dimensional namespaces are useful,
> but not indispensable: we can say that every screen
> variable is a namespace, and that the value of a
> screen variable is always found in the $value variable
> within that namespace; everything else in the namespace
> is an attribute:
I've thought of having a GUI system based on presenting text attributed
with multiple fonts and hyperlinks (it could also contain images and so
on). The GUI wouldn't present objects such as lists and vectors
directly, rather it would present attributed strings formed by
'prettyprinting' these objects. Clicking on an object would show a menu
of actions (determined using polymorphic words). The actual GUI would be
put together as a giant tree of text nodes, and a tiled browser/editor
interface.
Slava
stevan apter — 2004-09-13 11:28:24
----- Original Message -----
From: "Slava Pestov" <slava@...>
To: <concatenative@yahoogroups.com>
Sent: Monday, September 13, 2004 12:00 AM
Subject: Re: [stack] concatenative gui?
>
> stevan apter wrote:
> > The central idea of the gui is that windows are views of
> > global variables. For example, given a vector, say
> >
> > V <- 10 20 30
> >
> > the view of V is a window
> >
> > V
> > -
> > 10
> > 20
> > 30
>
> Does the window reflect the object stored at V, or the variable V? The
> fact that you have it titled with the variable name reflects the latter.
> Is there a distinction between the two even, given (as I understand it)
> K's call by value semantics?
the variable V. i.e. the triple (`V;value;attribute-dictionary), where
value is the "object".
>
> > if V or any part of V changes under assignment:
> >
> > V[0] <- 12
>
> How are notifications managed?
by the interpreter. i don't know the details.
>
> > f is a function which takes a value from V and returns a string.
> > g is a function which takes a string and returns a value to V.
>
> I guess these are similar to Factor's parsing and prettyprinting words.
> They are not currently polymorphic (they're implemented as a series of
> conditionals) however I intend to develop a form of polymorphism later.
$x takes anything x and returns a string. x$y takes anything y and
formats it according to x; 7.3$12.2 -> " 12.200". f can be any user-
defined function which takes a value and returns a string. g is
usually the near-inverse. if g throws an error on user input, the
interpreter displays the error in a window and does not perform the
assignment.
>
> > now it seems to me that since factor has namespaces, it
> > should be possible to design a data-driven gui along
> > similar lines. Two-dimensional namespaces are useful,
> > but not indispensable: we can say that every screen
> > variable is a namespace, and that the value of a
> > screen variable is always found in the $value variable
> > within that namespace; everything else in the namespace
> > is an attribute:
>
> I've thought of having a GUI system based on presenting text attributed
> with multiple fonts and hyperlinks (it could also contain images and so
> on). The GUI wouldn't present objects such as lists and vectors
> directly, rather it would present attributed strings formed by
> 'prettyprinting' these objects.
right.
it seems to me that the approach i outlined could be usefully
adapted to factor, given that it has name-spaces. then a window
is a projection of a name-space to the screen. update the
name-space -> update the window; edit the window -> update the
name-space.
Clicking on an object would show a menu
> of actions (determined using polymorphic words). The actual GUI would be
> put together as a giant tree of text nodes, and a tiled browser/editor
> interface.
>
> Slava
>
>
>
>
> Yahoo! Groups Links
>
>
>
>
>
>
>
sa@dfa.com — 2004-09-14 15:47:50
"stevan apter" <
sa@...> wrote on 09/13/2004 07:28:24 AM:
> > I guess these are similar to Factor's parsing and prettyprinting words.
> > They are not currently polymorphic (they're implemented as a series of
> > conditionals) however I intend to develop a form of polymorphism later.
>
> $x takes anything x and returns a string. x$y takes anything y and
^^^^^^^^^^
any atomic value x
$ applied to any non-atom recurses to the atoms, turns those into
strings; the result has the structure of x.
> formats it according to x; 7.3$12.2 -> " 12.200". f can be any user-
> defined function which takes a value and returns a string. g is
> usually the near-inverse. if g throws an error on user input, the
> interpreter displays the error in a window and does not perform the
> assignment.