From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from nez-perce.inria.fr (nez-perce.inria.fr [192.93.2.78]) by yquem.inria.fr (Postfix) with ESMTP id 281CABDDB for ; Fri, 2 Sep 2005 14:40:04 +0200 (CEST) Received: from pauillac.inria.fr (pauillac.inria.fr [128.93.11.35]) by nez-perce.inria.fr (8.13.0/8.13.0) with ESMTP id j82Ce3g8032681 for ; Fri, 2 Sep 2005 14:40:03 +0200 Received: from nez-perce.inria.fr (nez-perce.inria.fr [192.93.2.78]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id OAA06101 for ; Fri, 2 Sep 2005 14:40:02 +0200 (MET DST) Received: from smtp3.adl2.internode.on.net (smtp3.adl2.internode.on.net [203.16.214.203]) by nez-perce.inria.fr (8.13.0/8.13.0) with ESMTP id j82Cdubs032646 for ; Fri, 2 Sep 2005 14:40:01 +0200 Received: from rosella (ppp32-47.lns1.syd2.internode.on.net [59.167.32.47] (may be forged)) by smtp3.adl2.internode.on.net (8.12.9/8.12.6) with ESMTP id j82Cdf8k091779; Fri, 2 Sep 2005 22:09:43 +0930 (CST) (envelope-from skaller@users.sourceforge.net) Subject: Re: [Caml-list] Re: Feeding the OCaml GUI troll From: skaller To: Ville-Pertti Keinonen Cc: Matt Gushee , caml-list@inria.fr In-Reply-To: <1125646841.735.57.camel@acerf.exomi.com> References: <20050830174757.99765.qmail@web30510.mail.mud.yahoo.com> <200508302001.58080.jon@ffconsultancy.com> <3d13dcfc05083101487092acd5@mail.gmail.com> <43168841.9000302@havenrock.com> <1125580528.7192.23.camel@localhost.localdomain> <1125646841.735.57.camel@acerf.exomi.com> Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="=-xm2LYBbRgk2JbTlzjd3H" Date: Fri, 02 Sep 2005 22:39:41 +1000 Message-Id: <1125664781.7262.51.camel@localhost.localdomain> Mime-Version: 1.0 X-Mailer: Evolution 2.2.1.1 X-Miltered: at nez-perce with ID 43184823.000 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Miltered: at nez-perce with ID 4318481C.000 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Spam: no; 0.00; caml-list:01 ocaml:01 callbacks:01 threads:01 gui's:01 inverting:01 widget:01 conceptually:01 experimented:01 ocaml:01 inverted:01 low-level:01 callbacks:01 terminate:01 recursive:01 X-Attachments: type="application/pgp-signature" name="signature.asc" X-Spam-Checker-Version: SpamAssassin 3.0.3 (2005-04-27) on yquem.inria.fr X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=disabled version=3.0.3 --=-xm2LYBbRgk2JbTlzjd3H Content-Type: text/plain Content-Transfer-Encoding: quoted-printable On Fri, 2005-09-02 at 10:40 +0300, Ville-Pertti Keinonen wrote: > On Thu, 2005-09-01 at 23:15 +1000, skaller wrote: >=20 > > I am. My idea is this: GET RID OF CALLBACKS. > > The idea is to use (user space) threads instead. > >=20 > > The big problem with GUI's is that they're passive. > > You write 'event handlers' and have to store the current > > state manually. By control inverting the code, you can > > just use a thread for each widget. >=20 > Have you actually done this in a GUI context, or do you just find it > conceptually attractive? I have done some brief experiments to check it can be made to work .. but the real answer is no, it is only a planned application (of Felix). But see below .. > I've experimented with GUI concepts and event mechanisms in OCaml, and > created an event mechanism that could relatively easily be used in a > sort-of control inverted form by manually wrapping things into > continuations. I never ended up making use of that form of events for > the actual low-level GUI functionality, because it always seemed easier > to just use methods or attach callbacks to events and use explicit > state.=20 Yes, that seems likely for simpler low level things: for example for a button (my example) clearly you just need a boolean flag, which is pretty easy to maintain manually. However I *have* used the mechanism in a sophisticated embedded environment, namely a telephony system. We found, as above, that for some event handling, callbacks were indeed better: some events like=20 'phone call disconnected' are global, pervasive, and in this case quite final. Other events didn't fit so easily into this category. Excuse brief explanation: the system used an asynchronous real time data base. One task was to terminate a prepaid phone call when the client's money ran out. In a place like USA, where phone companies offer various deals, and there are multiple time zones, the costing algorithm can be quite complex -- especially if the client is mobile (basically a recursive tree search with pruning is required to find the minimum cost 'route') To do this with hand written callback driven code is=20 well nigh impossible. The algorithm is hard enough written in a functional form with referential transparency to help reason you have it right. The fact the control inverted (event driven) form is object oriented/procedural, yet equivalent to a purely functional algorithm, makes mechanical control inversion attractive -- but the utility is only apparent in more complex examples. > Now that could simply be because I was sort-of porting a GUI > library that I had written earlier (in C++ and Scheme) and I'm rather > used to GUI mechanisms layered around inheritance (one of the few places > where it actually seems natural to me). I guess you start with simplistic procedural code, but then find it is too hard to tailor and start using=20 inheritance to help with that. Unfortunately, a bit further down the track, you again find it isn't good enough, and you need much more dynamics -- and you have to switch to delegation. Further still, even that isn't dynamic enough, and you start needing real message passing, that is, posting events into the event queue as a means of communicating between widgets. The real question is, at this stage of sophistication, whether you wouldn't be better off due to strong static type checking, implementing stuff with functional style instead: functional code can represent state too, using closures. I don't know the answer .. but I do know existing GUI's are pretty bad. It is FAR too hard to get even simple things to work, and hardly any GUI applications around have any really high level functionality: the programmers are struggling so hard to get really basic things to work. > > For example for a button something like: > >=20 > > let rec wait_down () =3D > ... >=20 > > and wait_up () =3D > ... >=20 > > is purely functional: it uses the program counter > > to maintain state, instead of a mutable state variable. >=20 > But consider that the state of a button isn't quite that simple. The code was just an example of the style: for a more sophisticated widget -- I mean lets go all the way and look at a tree widget, an edit widget, or a canvas ... it isn't clear functional code will be easier. > Tracking the state explicitly isn't difficult=20 No, not for a button. But for complex widgets it is. Lets face it -- most programmers can't even get the mouse cursor right. GQView, magnify/shrink with the mouse changes the mouse from (+) to (-) when you next move the mouse .. which is plain wrong (it should change as soon as you click to magnify or shrink). Many games .. mouse droppings (they got the double buffering wrong). So the fact is, programmers simply cannot manage trivial state in a modern GUI correctly -- particularly they cannot keep the user view of the state properly synchronised with the internal state. Interestingly I think Tk handles this quite well (it knows when state is changed and re-renders the right things at the right time automatically). Windows is particularly BAD at some things, for example, the tool used to edit the environment is utter rubbish: PATH etc have very long string values and the dialog box is small and fixed size .. this is just rubbish. Another example: the ocamlbrowser is quite nice, except it spawns top level windows left right and centre, gets the size wrong, so every window has to be adjusted. Any decent tool would allow you to spawn those windows inside a pane or container of your choice: modern 'Window managers' are just rubbish. Sophisticated applications (eg Visual Studio) will give you the choice .. but it is all hand programmed for that particular application. I have designed a=20 system called HWM (Hierarchical Window Manager) which does away with that completely -- instead of a toolbar you get a tree widget, which allows you to move windows around in groups, and mutate their containers to any kind you like (top level, panes, notebooks, etc).=20 I have actually implemented this three separate times. It relieves the programmer of the burned of hand coding 'mega-widgets' and leaves the organisation of widgets up to the end user in a consistent way. Of course .. this is a fairly radical concept .. the=20 Open Source community would rather just copy Windows and add minor improvements than bother to do any real design work. The real problem, IMHO, is C. You just cannot consider new high level concepts for a GUI and implement them in C: it is way too hard.=20 Ocaml offers opportunities to do much better .. but there is no point just copying existing GUIs: we already have LablTk and LablGtk, which provide standard functionality rewrapped more nicely. If we're going to do a real GUI designed to take advantage of an advanced functional programming language, we need to do a whole lot better than what we already have .. and I do not see how to do this without a lot of design work. We do NOT want something with the same look and feel as existing GUIs. They suck. But we have to have something much better to be convincing .. do you remember the days before Drag-and-Drop existed? IMHO the *key* problem with GUI's -- and why real (TM) developers hate using them -- is the lack of automation: unix script=20 sucks, but it does provide automation. If we're going to make a new GUI it has to have full automation capability. The only way I can think of to do that is to base the=20 core components of the GUI on Category Theory -- for example have 'product' widgets and 'sum' widgets which represent a collection and a set of alternatives, respectively, and a standard way to combine them graphically. --=20 John Skaller --=-xm2LYBbRgk2JbTlzjd3H Content-Type: application/pgp-signature; name=signature.asc Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.5 (GNU/Linux) iD8DBQBDGEgNsRp8/9aGVGsRAoJrAJ92DQXyu017jicd09uJTrn1uNfatwCfeGvU jgUdCmjLKeVxC9FDTUqNbuE= =iuAU -----END PGP SIGNATURE----- --=-xm2LYBbRgk2JbTlzjd3H--