Date: Mon, 01 Sep 1997 08:21:55 -0400 From: Bakul Shah <bakul@torrentnet.com> To: "Jordan K. Hubbard" <jkh@time.cdrom.com> Cc: freebsd-chat@FreeBSD.ORG Subject: Re: sysinstall (was Re: Conclusion to "NT vs. Unix" debate) Message-ID: <199709011221.IAA19858@chai.torrentnet.com> In-Reply-To: Your message of "Sun, 31 Aug 1997 23:16:28 PDT." <7098.873094588@time.cdrom.com>
next in thread | previous in thread | raw e-mail | index | archive | help
> Perhaps I'm just biased from my previous installation experience, but > the way I see this working is as a series of linked "black boxes", > each black box representing some functional block of installation > hackery with an API for getting/setting its internal state and > executing it. You allow boxes to be named, to depend on other boxes > and to be arbitrarily chained together themselves. A "novice install" > then becomes a simple matter of creating a chain of operations and > starting the user off at the head of it. You'd have some sort of > "escape mode" which allowed the user to jump up a level and examine > this operation chain, moving forwards or backwards and perhaps able to > distinguish completed from uncompleted actions by their appearance. Seems like a `frame' data structure would nicely represent one of your black boxes! [For the unfamiliar:] A frame has a set of named `slots', a slot has a set of named `facets', a facet can have a list of values. A value can be pretty much anything including a reference to some other frame. A frame's slots (properties) or facets (sub properties) can be inherited, defaulted or computed. You can add, change or delete any number of slots, facets or values at any time. The process of adding/deleting can also be made to trigger other changes. This flexibility, coupled with a rich set of get/set functions (see below) make it a very useful data structure in situations where a lot of information has to be inferred. For instance, you can define a generic display-frame like so: display-frame: { background-color: {value: {white}} foreground-color: {value: {black}} next: { display: {button} location: {"-1-1"} action: {select-next} } prev: { display: {button} location: {"-1+1"} action: {select-prev} } clear: { display: {button} location: {"-1+20"} action: {clear-all} } help: { display: {button} location: {"-1+40"} action: {show-help} } } When this frame is given to some display procedure it will interpret the frame's contents and display all slots that have the display facet. It will attempt to display slots at per their location facet. The first two slots are obvious. The next four slots define action buttons if a correponding button is pressed. An action facet can be a procedure that is given the calling frame, slot and facet. The select-next function can choose a different next frame depending on the user (novice or expert). Alternatively you can define two facets: novice-action, expert-action. Now a frame that requires the above behavior can be defined simply as: foo: { a-kind-of: {value: {display-frame}} help: {value: {"this is a foo frame"}} ... } The a-kind-of slot can be used to inherit from multiple frames. When foo is given to display(), its contents as well as its inherited contents are displayed. When the help button is pressed, {foo,help,action} is passed to show-help, which can extract foo.help value and display that. > Sysinstall also currently requires that each functional block roll its > own GUI more or less from scratch - that's painful. It'd be a lot > nicer if you could simply say that each block had some attributes and > when you "visited" one, more generic attribute editing code could take > over the job of presenting the appropriate dialogs. You have some > known attributes for designating whether a block can be undone or has > gone past the point of no return, etc. and so forth. Yup. This is easily possible. Slots that can be edited can have a edit facet. Instead of undoing an action you can simply wait till all the information is filled in or inferred before doing anything. The beauty of a frame is that it has a very regular structure so adding more attributes etc. does not require you to change a struct definition or worry about how to make two structs compatible when they differ only `slightly'. Since every object can be used as a prototype for some other object you can dispense with a lot of bookkeeping ala C++. -- bakul PS: Frames were first described in a 1975 paper by Marvin Minsky -- I believe you can get a scanned copy of this paper from some mit site. They are also described in some Lisp books. Frames are almost always implemented in Lisp but I see no reason why they can't be implemented in other languages or why such a rich data structure should be left alone for the use of AI heads :-) In C you can't define functions on the fly but that should not be a problem in tcl or perl. The basic frame functions are get-fsf(frame-name, slot-name, facet-name) returns values corresponding to the frame-slot-facet triple. or NULL if no such value exists set-fsf(frame-name, slot-name, facet-name, value) adds to the value list for the frame-slot-facet. also creates frame, slot and facet if missing. del-fsfv(frame-name, slot-name, facet-name, value) deletes value if it exists. deletes facet if no values left. deletes slot if no facets left. deletes frame if no slots left. get-fs(frame-name, slot-name) same as get-fsf(fame-name, slot-name, "value") get-fsd(frame-name, slot-name) in addition to what get-fs does, it also looks in the "default" facet. getI(frame-name, slot-name,facet-name) same as get-fsf but if that fails, it walks up the a-kind-of tree to extract the facet. This would be an *Inherited* facet, hence the getI name. getN(frame-name, slot-name) same as getI(frame-name, slot-name, "value") but if no value was found, it then tries getI(frame-name, slot-name, slot-name, "default") and if that fails, it tries getI(frame-name, slot-name, slot-name, "if-needed") The last getI may return a function, which when evaluated will yield the actual value. The `N' in the function name to remind us that first we walk up the a-kind-of tree, then come all the way down and try it again with a different facet, walking up again and so on. getZ(frame-name, slot-name) this function goes across first and then up. That is, try get-fsf(frame-name, slot-name, "value") or else try get-fsf(frame-name, slot-name, "default") or else try get-fsf(frame-name, slot-name, "if-needed") or else for each f in get-fsf(frame-name, "a-kind-of", "value") try the same three facets. set(frame-name, slot-name, facet-name, value) like set-fsf. In addition it will also invoke an "if-added" facet procedure for slot-name if one exists or can be inherited. This way changes in one frame can be made to side-effect anything else. del(frame-name, slot-name, facet-name, value) like del-fsf. In addition it will also invoke an "if-removed" facet procedure (which may be inherited) if one exists.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199709011221.IAA19858>