Thank you very much Anthony and Adrien, your comments helped me a lot, I now have plenty of material to think on! Best, ph. 2012/2/15 Anthony Tavener > Hrm... when I re-read my prior post before sending, it made sense. Several > hours later it seems inadequate, and I've thought of something to say more > clearly... > > The execution of code bounces between the UI and the mainline. When the > mainline processes a "gui hit" it will resume the UI code *right where it > left off (yielded)*... then the UI will do something and get to another > point where it yields, awaiting input and thereby resuming the mainline > where it was (back to processing gui hits). > > Why would I want this? So that I don't have stateful UI code which has to > trickle down to the right place all the time. The UI code is clearer > because it doesn't need to be re-entered from the top each frame. This > suits the declarative style of GUI specification, like the example you > gave, since we don't need special state or messages to communicate what the > GUI is doing. GUI state becomes a property of the... well, the stack. It's > the current scope of the code. > > Hope this helps! > > -Tony > > > On Tue, Feb 14, 2012 at 11:02 AM, Anthony Tavener < > anthony.tavener@gmail.com> wrote: > >> Apologies Philippe, this is a bit long... >> >> The "update loop" I mentioned might be a bit of a red-herring, as I'm >> only using that for continuously active UI elements: such as changing >> cursor to represent the action which would be taken on click. It has >> nothing to do with the basic UI flow. >> >> I didn't understand delimcc right away, and I hardly understand it now! :) >> >> I was looking to write UI code much as your example of packing buttons >> together with directly bound activation functions. >> >> Here's my "menu_of_list", which takes a list of string * 'a pairs, >> calling GUI code to make a menu using the strings as labels, and using the >> 'a values as return values... >> >> let menu_of_list lst return = >> (* snipped: preamble which handles positioning, stacking order, getting >> font, etc *) >> Gui.add_widget gui >> (new Gui.vbox pos stacking spacing >> (lst |> List.map >> (fun (label,value) -> >> Gui.wit_fn gui >> (new Gui.rectangle_text w h fnt label) >> (fun () -> return (Some value) ) ))) >> >> The important part here is the "return" function. This will resume the UI >> coroutine. It is given to "menu_of_list" by the UI code, then when the GUI >> has an activation of a menu button this "return" is called... resuming the >> UI where it left off, and with the "Some value" which was associated to the >> button. >> >> The magic of how this works is in delimcc capturing portions of the run >> stack. Here I've extracted the relevant bits of code: >> >> >> (* this runs as a coroutine with the "mainline" *) >> let ui ui_process () = >> >> (* in actual code, this menu comes after a "right click", for special >> actions *) >> let act = yield ui_process (menu_of_list coord >> [ ("Equip",`Equip); >> ("Spell",`Spell); >> ("End",`End) ] ) in >> (* ... handle whatever action the user chose! *) >> >> >> (* given SDL events, calls activation functions of 'hit' widgets *) >> let gui_react gui events = >> let hits = gui_select gui events in >> match hits with >> | h::t -> begin >> match get_binding gui h with >> | Some f -> f () (* runs activation function of widget, such as >> "return" to coroutine! *) >> | None -> () >> end >> | [] -> () >> >> let _ = >> (* A prompt is delimcc's mechanism for marking the stack to -limit- the >> * continuation, rather than creating whole-program continuations. *) >> (* So here, the "ui" is initially run, and will *resume* this mainline >> continuation >> * at the end of the "user" function call. *) >> let ui_prompt = new_prompt () in >> push_prompt ui_prompt (ui ui_prompt); >> >> ... >> >> (* in mainloop *) >> gui_react gui events; >> >> ---------------------- >> >> Now I'm going to restate the yield function here, and try to explain... >> >> let yield level fn = >> shift level (fun k -> >> fn k; >> abort level () ) >> >> "shift" and "abort" are delimcc. This runs the given function "fn" with a >> continuation 'k'... so this continuation is the "return" function passed to >> menu_of_list, and therefore bound to each menu-button. The abort exits the >> "ui coroutine", resuming the mainline, hence the name: yield. >> >> The continuation 'k' comes from the shift... the continuation is the code >> "outside" of the shift call... so when it's called (by the mainline's >> gui_react), it resume at the end of 'yield' and keep on going... in this >> example, handling the returned action! >> >> I hope this conveys at least the gist of what's going on... I read a lot >> of papers over-and-over, not understanding... although none were >> specifically GUI. Delimited continuations have numerous applications and a >> surprising number of configurations for just a pair of functions! (Abort is >> really a special case of "reset"... so it's shift and reset, in ump-teen >> configurations.) >> >> I'll try to explain if you have any further questions! However, I'm still >> trying to sort out how best to write my GUI code -- there is a lot of room >> for improvement. :) >> >> -Tony >> >> PS. I'd like to blame X. Leroy ;)... for a post some 10 years ago >> replying to someone's attempt to do a GUI in OCaml... Xavier casually >> replied something like "oh, you can use coroutines". That was a wild goose >> chase (or Dahu?)! Delimcc didn't exist at the time, and it's native-code >> implementation came about just a few years ago (thank-you Oleg!). Even >> then, I had no idea how I was supposed to use a coroutine to write GUI >> code! Oh well, it was an adventure, and I still don't know if this is a >> good thing, but I like it a lot more than "signals and slots" -- the usual >> scattered GUI code which is connected by messages/events. >> >> >> On Tue, Feb 14, 2012 at 3:17 AM, Philippe Veber > > wrote: >> >>> Hi Anthony, >>> >>> This looks interesting, however as I'm not very familiar with delimcc >>> (that's a shame, I admit), I fail to understand the flow of the program. >>> Would you mind giving a snippet of the update loop you mentionned? >>> >>> >>>> So far, I'm not sure how well this works out for a complete project. I >>>> like it so far, but I have complexity growing in some "update loop" stuff, >>>> which are little closures I add to be run each frame-update for reacting to >>>> mouse-over/hover. >>>> >>>> >>> >>> Good luck in the hunt for elegant UI (code)! >>>> >>> >>> Let's hope I'm not just Dahu hunting! >>> (http://en.wikipedia.org/wiki/Dahu) >>> >>> >>> >>>> >>>> Tony >>>> >>>> >>> >> >