From: Richard Young Sender: European SOAR research communications To: Multiple recipients of list EU-SOAR Subject: Comments on Tcl/Tk for environment for cog models Date: Mon, 4 Mar 1996 13:07:20 GMT Soarers (and some others): These notes concern the suitability of Tcl/Tk for building simulated "external environments" to couple with cognitive models that require interaction with the outside world. It is based on my experiences building such a simulation for use with a particular cognitive model. The notes may be of interest to Soarers considering the potential of Tcl/Tk for their Soar7 models, and to cognitive modellers and HCI user modellers more generally. To save you having to skim through a long email message, I'll put the conclusions first, right here: Summary/Conclusions ------------------- 1. Based on my experience, Tcl/Tk certainly qualifies as "easy to learn". 2. Major complications of programming in Tk come from non-uniformities in its data structures. 3. Tk appears to have gaps in its coverage of basic functionality, that would pose real difficulties in its intended role for building interfaces. 4. Tcl/Tk is clearly able to support the kind of usage investigated here. Programming simulated environments to meet certain stringent criteria is still very difficult, but -- apart from the complications introduced by the limitations mentioned in #2 and #3 -- probably little of that difficulty is the fault of Tcl/Tk. It would be difficult in any programming language. 5. Driving a simulated environment through an "I/O Control Panel" seems an appropriate way for developing and understanding the environment. 6. Aiming early for a "toy" interface you can play with, can cause difficulties if you try to extend the initial version to a "real" one. The demo -------- If you want to run or read the code, it's available either through the "miscellaneous Soar stuff" in my WWW home page, http://www.mrc-apu.cam.ac.uk/personal/richard.young/ or else directly by anonymous ftp from ftp.mrc-apu.cam.ac.uk, directory pub/sum/recent-soar-misc, get either cg-sim.tcl (approx 70K) or cg-sim.tcl.gz (approx 19K). I suspect that the appearance of the interface is greatly affected by using a different font than the one that was default on my system. For the record, the font I used was apparently called "-Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*". The minimal sequence of moves to perform the Cricket Graph task is: out, right, right, right (to PM-1), move, double right, right, right (to Graph), move, press (to pulldown the menu) alert, in, down (to Line), move, release (to get dialogue box) alert, in, right, in, down, in, down (to Serial Position), move, click out, out, right, in, down, in, down, down (to Observed), move, click out, out, right (to New Plot), move, click (to get graph with labelled axes) alert, in, down ... down ... down ... down ... When driving the simulation, note that there is useful feedback information in the "affordances" of the upper part of the control panel, as well as in the visual data of the lower part. Enjoy! ============================================================================ COMMENTS ON THE SUITABILITY OF Tcl/Tk FOR BUILDING SIMULATED ENVIRONMENTS FOR COGNITIVE MODELS Richard M Young 4th March 1996 Contents: THE PROJECT HISTORY COMMENTS ON Tcl COMMENTS ON Tk SIMULATED ENVIRONMENTS FOR COGNITIVE MODELS REFERENCES The project ----------- Recently, John Rieman, working with Andrew Howes and myself, wrote a Soar model of the kind of exploratory learning that occurs when moderately experienced Macintosh users are asked to use a program they haven't seen before [ref 1]. In this case the program was Cricket Graph, and the task was first to get a default graph plotted against some given data (which is the part we model), and then to change the visual style of the graph to match a given example. For our Soar model, written in Soar6, we "simulated" the necessary aspects of the Mac and Cricket Graph (CG) with rules within Soar (which is quite a story in itself [2]). With the move to Soar7, it obviously made sense to consider building a simulation in Tcl. It also made sense at the same time to use the graphical capabilities of Tk to show the modeller what was happening on a simulated Mac/CG display. Because we don't yet have a version of the model in Soar7 to connect to the environment, it seemed appropriate to couple the simulation to a "control panel" from which the user can play the part of the cognitive model, issuing motor commands and receiving simulated visual input. (In this note, I'll use "model" to mean the cognitive model, and "simulation" to mean the simulation of the external environment.) The simulation within Soar we used previously was adequate to support the usage of Mac/CG we modelled, but it was limited and clearly getting more and more difficult to extend. For this new simulation in Tcl/Tk, I wanted to ensure that so far as possible the simulation was "objective", i.e. independent of the cognitive model, and sufficiently detailed to provide a rich environment for further modelling of exploratory learning. The principle was to keep psychological assumptions out of the environmental simulation. Ideally, one would like the simulation to be fixed, once and for all. But in practice one cannot afford the effort to build huge parts of the simulation that will never be reached by the model. Also, one wants to stop somewhere short of implementing a fully usable version of Cricket Graph in Tcl/Tk! One consideration I had in mind, suggested by Frank Ritter and his colleagues in their discussion of the requirements on an environment for cognitive modelling [3], was that perhaps the modeller should be able to interact directly with the same simulation as the model does. In the event, and as discussed further below, my program doesn't meet this criterion, and it's unclear whether I took this aim too seriously or not seriously enough. So my goals for this programming project were: - provide an environment that simulates basic behaviour of the Mac and Cricket Graph, and provides simulated visual input; - learn Tcl/Tk, and understand something of its capabilities and limitations; - make the simulation independent of the cognitive model, so that it provides a rich environment for further modelling of exploratory learning; - structure the program so that its coverage of the Mac/CG is easily extendable to further aspects; - and, maybe, have the simulation directly usable by the modeller (i.e. with the mouse, not through the control panel) as a kind of mock-Mac. Perhaps this was a little too ambitious for a first Tcl/Tk program, and -- again as discussed below -- I would now set about it differently if starting again from scratch. Driving the simulation through the control panel proves quite illuminating. If you cover up the simulated Mac screen and try to perform the task using just the information in the control panel, you get a good feel for the difficulty of the task faced by the cognitive model (or for that matter, perhaps, the real cognitive system). It became apparent very quickly, for example, that my assumptions about visual attention made it too difficult to move from a pulldown menu back to the menubar at the top, or specifically back to the header associated with the pulldown menu. The panel also provides a quick and easy way to try out different search strategies. History ------- On 15th February I bought a textbook on Tcl/Tk [4], and spent about a day reading it. One day later I had a rudimentary simulation running, which looked not unlike CG, with a menubar from which realistic-looking menus would pull down when the header item was pressed. None of the menu items did anything at that stage, execept that the "correct" one (Graph/Line) led to an (empty) dialogue box. The next week or so was spent in sorting out problems (aided by a helpful email exchange [5] with the author of the textbook!) and developing the basic mechanisms. That work included having to recover from an initial decision to use Tk's Listbox widget to simulate CG's listboxes, as described below. The last two or three days were spent in tidying and rationalising the code, and then filling in the details and extending the coverage. I had almost no prior experience of graphical programming, and the project took less than two working weeks. I have quite a number of complaints, but it is clear that Tcl/Tk was not difficult to learn. In retrospect, it was a mistake to try to build on the code I wrote that first day to give a rudimentary CG-lookalike. No-one can resist the temptation to rapidly get something on the screen that looks like the real thing, but I should have then thrown it away and started again from scratch, even though that way it would have taken longer before I had a partial simulation I could look at and play with. Again, more on that below. Comments on Tcl --------------- I don't have much to say about Tcl itself. It's a simple, string-oriented procedural language. Like other string-oriented languages, it is necessarily a bit fussy about quoting and naming. It has one or two idiosyncrasies, particularly concerning text layout and the use of brackets. It's a "small" language, smaller even than say Pascal. It is fast. My source file of around 2000 lines loads in a second or so, easily fast enough to be able to debug by reloading the program after each editing change. Tcl's main large-scale data structure is associative arrays. I found them flexible and easy to use to realise multidimensional arrays, attribute-values, lists, and so on. The most complex programming I did was to simulate the rather complicated behaviour of the Mac with menus, highlighting, etc., as a mouse is slid around with the button either pressed or released, over icons, headers, menu items, and so on. It seemed best to represent the behaviour in a kind of state-transition network -- which in fact forms the core of the Mac/CG simulation -- and the associative array serves very nicely for that purpose. There are just some hints of non-uniformities. For example, Tcl is mostly happy with unquoted strings. Just as you can say 'set x 5' for the variable x to take on the value 5, so you can say 'set x yes' for x to take the value "yes". But this doesn't work in expressions. In particular, you can write 'if {x == 5} ..', but 'if {x == yes} ..' gives a syntax error. You have to write 'if {x == "yes"} ..'. And I haven't yet succeeded in finding a way to use string values in conditional expressions. Comments on Tk -------------- Tk is another matter. It is riddled with non-uniformities; indeed, I'm tempted to call them inconsistencies. Just to give a feel for this issue in the first case, consider the observation that most Tk widgets have some associated string: the label on a button, the wording of a menu item, and so on. For most widgets, this string is stored as the -text attribute of the widget. But for some, it is the -label attribute, an undesirable and unnecessary kind of non-uniformity. Why does it matter? For straightforward uses of Tk to construct a hand-crafted interface, it's probably not too important. It will lead to some coding errors, which then have to be tracked down and corrected. But in my application, I'm using Tk "up a level" as it were, to *simulate* an interface, not to implement one. That means that my program needs to carry out generic functions such as "get the string associated with this simulated Mac object". The code then has to do elaborate case-analysis, to discover what kind of Tk widget has been used to represent the Mac object, and then use the appropriate kind of access. That adds a considerable overhead to the programming. Here are more examples: * Most Tk widgets are objects in their own right, accessed by their name. But menu items, for example, are not fully-fledged objects. Instead you have to access them by indexing from their parent menu. This complicates the process of finding their string, or finding their position on the screen, all of which has to be done by ad-hoc case analysis. And things drawn on a canvas aren't "objects" at all, which means that you have to handle them quite differently. * The two compound widgets, menus and listboxes, are analogous in many ways. They both display a vertical array of text items. They are both indexed starting from zero. To get at the last item of a menu, you use the keyword "last", so to get at the last item of a listbox, you use the keyword ... "end"! Great, that means that the same code won't work on both. Furthermore -- and computer scientists should love this -- in the case of menus, "last" indexes the last item. In other words, for a 6-item menu, it has value 5. But for listboxes, "end" indexes ONE BEYOND the final item: it has value 6. Another complication (and source of potential bugs) in the programming. * Consider the question of highlighting, i.e. marking selected items. On a monochrome Mac, highlighting is done by using "inverse video", i.e. white text on a black background. For most Tk widgets this works fine, you merely have to set the -background attribute to black and the -foreground to white. And, apart from the fact already noted that you have to access menu items by indexing, it works for them too. But it doesn't work for listbox entries. So far as I can see, there is no way to get at the appearance of individual listbox entries. So that makes it difficult, to put it mildly, to show highlighting in listboxes. And that leads me on to ... * ... the thing that caused me most grief. The Mac, like Tk, has listboxes: scrollable, vertical lists of items. So, it would seem to make sense to use Tk listboxes to simulate Mac listboxes. And for a while I tried it. I thought I had found a way to indicate highlighting of items in listboxes. Tk allows you to "select" one or more items from a listbox, and it allows you to specify the background and foreground colours for selected items. So by specifying black and white respectively, and telling Tk that certain items were "selected", we seem to have found a way to handle highlighting. But it doesn't work! On the Mac it's not uncommon to have items highlighted simultaneously in two or more listboxes, and that is done in CG. But in Tk, "selection" is all bound up with the underlying X-windows selection mechanism, and it turns out that X allows the selection to belong to only one widget at a time. So although you can select multiple items in a listbox, you can't select items in multiple listboxes. My conclusion from this is that not only was I garden-pathed during the programming, but also that Tk is seriously limited in its ability to implement interfaces using listboxes. In addition to these non-uniformities, some things are just difficult or plain impossible to do in Tk. I wanted to indicate on the graphical display the locus of the model's visual attention, by surrounding the attended object with a hollow oval, rather as if someone had taken a marker pen and circled the object of interest. But this proved difficult to achieve. Ovals can only be drawn on a canvas, but other objects (such as the menubar) placed on a canvas are *in front* of things drawn on the canvas itself. (And bringing the canvas to the front just hides the objects.) Furthermore, some things, like menus, are in a separate window from the canvas entirely, and of course in front of it. In the end I solved the problem by constructing a hollow rectangle out of four long, thin, black "frames" -- appearing as thick lines -- and positioning them round the attended object. I needed to have one such set of frames associated with each possible toplevel object (e.g. menu) that can appear. Problem solved, but not easily. Finally, Tk seems simply not to do certain things claimed in the book. For example, I couldn't get '-justify left' to work with Labels, and there appears to be no '-command' associated with Menubuttons, even though the textbook says there is. But maybe I was doing something wrong. Speculatively, I wonder what it would have been like trying to do this in Garnet? I don't know the language (though I think I once sat through a one-day tutorial), but my guess is that it would have taken much longer to learn, and perhaps even been slower to program, but that it wouldn't have had such blatant non-uniformities. But I could be wrong on any of these points. Simulated environments for cognitive models ------------------------------------------- Finally, I want to move away from the details of Tcl/Tk, and ask about what is involved in building simulated environments of this kind. This kind of simulation program has inherent conceptual difficulties. There are three different classifications and structuring of entities: the Tk widgets (such as Labels, Buttons, Menus, etc.); the Macintosh objects (menubars, pulldown menus, dialogue boxes, and so on); and the visual groupings and spatial relationships assumed by the cognitive theory. These really are different. First, the Mac ontology is not the same as that for Tk. Although there are many parallels, so that for example Mac buttons are implemented as Tk Buttons, and Mac pulldown menus as Tk menus, I've pointed out that it's not possible to implement Mac listboxes as Tk Listboxes. Instead, they have to be built out of more primitive components. Furthermore, Tk does not have specific types such as menubars, icons, and dialogue boxes. Instead, again, they neeed to be constructed from Tk's Frames, Labels, Buttons, and whatever. Second, the visual level is different to the Mac level (as well as, more obviously, the Tk level). The visual structuring is concerned with relations such as containment and proximity, while the graphical objects are concerned with relations such as parent-child belonging. These do not coincide. For example, a pulldown menu is (arguably) at the same visual level as the menubar, whereas from the viewpoint of graphical objects it is two levels down the hierarchy (i.e. a grandchild). Moreover, even where the visual and Mac levels do agree -- as perhaps in the case of the menubar, where the left-to-right ordering of headers is the same for both, and the parent-child relation corresponds to containment -- it would be a mistake to build that agreement into the structure of the simulation. We might later want to change our assumptions about visual parsing, and we should not have to change the "objective" simulation in order to do so. As stated earlier, psychological assumptions should be kept out of the simulation, so far as possible. There is a real tension between (a) exploiting what Tk provides, and having the interface "pretend" to be like a Mac, and (b) duplicating much of the functionality of Tk in code that simulates the Mac. The existence of the three different levels just described suggests implementing the simulation in strict "layers", with a well-defined Macintosh layer implemented in terms of Tk's widgets, and then a visual layer that interprets and reports information from the Mac layer. But that isn't really possible. Where there are parallels, as with menus, the code for the different layers tend to merge: you can't really stand not to program the Mac menus as the Tk level. More fundamentally, the visual layer can't be realised as a purely "observing" layer. Instead, when things happen (mainly at the Mac level), information needs to be passed to the visual layer. Consider the case of highlighting, discussed earlier at the Tk level. Highlighted objects are salient in the visual field, so it is important for the visual level to know about them. When an object is highlighted, the main change is to the actual physical display, detectable only to the modeller's eye. There is also an internal change to Tk's data structures, in so far as the background and foreground colours of objects are readable. Although in principle one might imagine the visual code examining all the Mac (or Tk?) objects to see if they are highlighted, it is easier to write the program so that whenever an object is highlighted or unhighlighted, a message is sent to the visual layer informing it of the event. But that does imply an intermingling of layers in the code. A tentative conclusion is that one could certainly structure the simulation more cleanly than my half-hearted attempt, but there are limits to how much separation there can be between levels. Another relevant issue raised is that graphical languages differ in their "internal observability". In some cases, the effect of the program is that "things just happen" and the display changes as a consequence. In other cases, the effect is reflected in a change to the program's data structures, which can be read by other parts of the program. Tk occupies an intermediate (and non-uniform!) position on that dimension. I suspect (but I could be wrong) that Garnet does somewhat better. Finally, I can imagine a very different organisation for the program. We could worry first about building a partial *implementation* of Mac/CG in Tk, so that in relevant respects it responds to the mouse in the same way as Cricket Graph itself does. (We would do that in such a way that extra information is maintained where necessary about the state of the display, to support "internal observability".) We would then add a separate simulation level, which causes pseudo-mouse-events to drive the Mac/CG implementation, and a visual layer which reports back on the results. Such an organisation would satisfy Frank Ritter's criterion, that the environment could be driven directly by the mouse as well as through the simulation, but I suspect it would lead to some very messy code. Summary/Conclusions ------------------- (See at the beginning of this message.) References ---------- [1] Rieman, J. F., Young, R. M. & Howes, A. (1996) A dual-space model of iteratively deepening exploratory learning. International Journal of Human-Computer Studies, in press. [2] Rieman, J. F. (1995) Using Excel and Mailmerge to generate Soar productions. Talk presented at 15th Soar workshop. Pittsburgh, September 1995. [3] Ritter, F. E. & Major, N. P. (1995) Useful mechanisms for developing simulations for cognitive models. AISB Quarterly No. 91 (Spring), 7-18. [4] Welch, B. B. (1995) Practical Programming in Tcl and Tk. Prentice Hall. [5] In the preface to his book [4], Welch states that he is still "open to comments" on this edition, and gives a (now out of date) email address. I sent him comments on what had struck me as the strong and weak points of the book, and asked for advice on something I was finding difficult. He kindly acknowledged the comments, responded to some of the specific points, and offered me guidance. Email is wonderful! ============================================================================