📜 ⬆️ ⬇️

Language K: Displaying a graphical interface from data

As always, I talk about APL, or rather about the old version of the K language, which contained a GUI, with a very unusual approach to it.

Unfortunately, the new versions of the K language decided to focus only on data processing and excluded the GUI, so this approach remains in history, but maybe someone will tell similar modern frameworks - it would be very interesting to see.

Let's start. A brief description of the API that is available to us:
`show$`v show variable v `hide$`v hide variable v 

This is all, nothing more. Those. The main feature is that the GUI in K is a direct mapping of data in memory. And now how you can work with it comfortably.

First, let's try the simplest:
 C:\>k K 3.1 2004-01-28 Copyright (C) 1993-2004 Kx Systems WIN32 2CPU 4030MB ws-1341.x.com 0 EVAL a:10 _draw 100 / list a 20 51 12 34 31 51 29 35 17 89 `show$`a 

A table appears on the screen with a list

Any value edited, change 35 to 135 and this change immediately changes the value in the list:
  a 20 51 12 34 31 51 29 135 17 89 

If we change the value in the list, it is then updated in the interface.
')
Display a small list is not a problem, but what if there is a lot of data? Let it be a lot:
  a:(10 10000000) _draw 100 / 10   10   `show$`a 


No problems - everything is quickly displayed, scrolled and edited.

Name the columns: it is logical that the column name is a key, and the list is the value from hashtable:
  t:.((`a;10 _draw 100;);(`b;10 _draw 100)) `show$`t 



But it's all very simple, see what else is there. Attributes and triggers — in fact, it’s just a key value in a hashtable bound to a variable, depending on whether there is such a value or not — different actions occur:

The simplest example: adding a label.
  val:10 val..l:"Input field" `show$`val 



The following attributes affect mapping in gui:
  Display attributes (for variables that have class). x width integer(KFONT width) y height integer(KFONT height) a arrangement nest of symbols(class `form) o options list of symbols(class `radio) l label string kl click label string (also klr) Data-display attributes (for variables that have class `data). functions (monadic, constant or array) default e editable 0 or 1 1 f format string from data 11$(11.2$) g getdata data from string 0$ etc. u update update[old;new] : fg foreground integer(rrggbb) 0 bg background integer(rrggbb) -1(808080) expressions/events (strings) ins, del, f1 ... f12, ctrl_a ... ctrl_z k, kr, kk click, click right, double click(precludes e) c class(display) symbol `data(default) atom, list, dict, list of lists, dict of lists `chart as above where atom is list of y values `plot as above where atom is matrix of (x;y) values `check 0 or 1 `radio symbol (one of ..o; see below) `button expression or dictionary of expressions `form dictionary of entries of any class(incl. `form) 

I will not describe the detailed features of each of the attributes, since most of them are obvious from the description and do not feel like doing a manual.

For ease of creating a dictionary - the language allows you to work in the context within the dictionary - i.e analogy with folders and modules that are just hash tables:
  \d form val:100 incr:"val+:1" incr..l:"Increment" decr:"val-:1" decr..l:"Decrement" incr..c: decr..c: `button \d ^ form /  -   . .((`val;100;) (`incr "val+:1" .((`l;"Increment";) (`c;`button;))) (`decr "val-:1" .((`l;"Decrement";) (`c;`button;)))) 


Attribute ..a set the display order.
  form..a:`incr`val`decr form.val..e:0 /   . 



..a can be any shape. For example, add a couple of buttons.
  form.incr10:"val+:10" form.decr10:"val-:10" form.incr10..c : form.decr10..c: `button form..a:(,`incr;`decr10`val`incr10;,`decr) form..a (,`incr `decr10 `val `incr10 ,`decr) 



Those. the point is that everything GUI is described by primitive structures of the language and is their direct mapping. You can include hash in hash, i.e. include the form in the form composing the elements and so on.

Well, now the most interesting, namely a few examples:

Calculator:
 calc..a:(`exp `va`vb`vc`vd `n0`n1`n2`n3 `n4`n5`n6`n7 `n8`n9`lp`rp `fa`fs`fm`fd`fe `eval`clear) /     calc:@[_n;1_-1_ calc..a;:[;"exp,:(~_v)`l"]] / expressions calc[.;`l]:"abcd0123456789()+-*%:" / labels calc.eval:"exp:5:. exp" calc.clear:"exp:\"\"" calc[.;`c]:`button calc.exp:calc.exp..l:"" `show$`calc 



You can draw graphics:
  p..c:`chart p:(5 5) _draw 100 `show$`p 



Or highly artistic daub:
 `show$.,((`p;({[x] (2 30)_draw 30}'!10);.,(`c;`plot;))) 



And now the amazing thing that once surprised me with its brevity and clarity (with minimal knowledge of the dictionary of course), that I decided to start learning K more deeply:

Broadcast server:
 d:10 _draw 10 w:!0 / empty client list .mg:{w,:_w;d} / return data .mc:"w@:&~w=_w" / retain clients .ms:{. x;w 3:\:x;} / (log `l 5:,x) apply and broadcast \mi 1 listen on port 1 

Customer:
 h:3:(`;1) / connect to server d:h 4:_n / get database d..t:"if[0=_w;h 3:(_v;_i;:;_v ._i)]" / send my updates `show$`d 

These few lines create a server with a simple list as data. And as many clients as they like join it and have a co-edited list with a real-time update, only 9 lines. Such code (without a GUI of course) is currently used on many major exchanges for transport and balancing nodes that serve the Q instances of the databases (the new version of K).

The picture of course does not convey how it works in dynamics.

Source: https://habr.com/ru/post/205844/


All Articles