From: Twylite <tw...@cr...> - 2010-10-21 16:44:35
|
Hi, > However, my understanding is that SQLite3 will be included with the > core as a standard package to support TDBC, and hence will always > be available by 8.7. Why not use it? TDBC (and SQLite3) are bundled packages. Maintainers of particular Tcl distributions are free to include or exclude them. If the core cannot build built without these packages, or crashes if they are missing, or even doesn't work with them missing, I think that's a problem. At that point they become dependent libraries rather than bundled packages. > The implementation is open to change; it might well be desirable to re-implement the ensemble in C, for example. SQLite3 is a convenience, > rather than a necessity. It has been argued on this list, by TCT members and others, that functionality that _can_ be implemented in an extension (be it C or Tcl) should be implemented as such and given a chance to mature before consideration for inclusion in the core. > As for including the command in the core--I wrote the TIP because > there was interest at last week's conference in having this functionality > in the core. Enough interest? We'll see. :-) Thanks - that provides a bit more background. Given which I shall proceed to comment on the TIP ;) 1. I feel that the dependency on SQLite3 should be removed. It's fine for a prototype, but not for a final core implementation. Compiling Tcl for an embedded environment shouldn't require TDBC and SQLite. 2. How is the execution of multiple bound scripts affected by a script throwing error, break or continue? 3. How are bindings affected by a script throwing an error? Tcl's [trace] for example will remove a script that throws an error, preventing redundant exceptions. 4. The object/binding dichotomy makes it easy to discover, remove or intercept on all bindings for an object, but assumes that some appropriate object can be identified. It should be possible for object to be the empty string (that may already be the case), and it would be convenient to allow object to be omitted entirely. 5. I think the subject/event dichotomy needs more investigation. Karl Hansen has already brought up the possibility of viewing the event as a hierarchical string. It is useful to bind to a specific event from a specific subject, and also to bind to a class of events that may originate from any subject. In the latter case the subject would be some well-known string, which would diminish the value of separating subject and event (the convenience of have the subject as a Tcl/Snit object would fall away). I suggest that bindings should be to an event, and events may be filtered to include only those from a particular subject. 'subject' is then always some unique identity of the sender, and never a generic 'class string'. i.e. notifier bind ?event? ?subject? ?object? ?binding? where event _should_ be hierarchically named, and subject may be empty (no filtering) or a unique identity. 6. The last point raises the issue of naming. As described the TIP is a slight generalisation of the Observer pattern (http://en.wikipedia.org/wiki/Observer_pattern), suggesting the names subject, event and observer. Binding to the event (as described in the last point) rather than the subject would be closer to the Publish-Subscribe model, suggesting the names publisher, message, and subscriber. Rather than argue the nuances of implied synchronicity (or lack thereof) of event, signal, and notice, I'll suggest something different entirely: hook. The idea of a hook as a place in a program at which code may be injected is well established. Many frameworks and extensible applications provide "hooks" as points to which callbacks may be attached. Hooks are necessarily synchronous, and the concept closely matches the functionality described by the TIP. 7. Harald Oehlmann's [call] needs more attention. I do not think that scripts should be able to control the execution flow of the notifier (by returning continue/break), but capturing the results of each bound script promotes this "notifier" to a "dispatcher" that is a fully-functional core for a plugin system. _That_ has my attention, being something I work with a lot more than unidirectional notification. For example, I have several applications that share various libraries and need to provide detailed reports (some of which come from the libraries). My libraries register themselves as "Reporter" plugins, and each plugin provides a callback to a "list_reports" function. One library is then able to find all reports linked into the application, and render them. Using [notifier]: # register as a plugin - accept <Reporter> calls from any subject notified bind <Reporter> {} $self [list $self] # discover all reports foreach response [notifier send $self <Reporter> list_reports] { ... } In this case the callback/binding is an ensemble (that implements the <Reporter> API). 8. Proposal (which still needs some thought, but I have to leave now) > hook bind ?event? ?subject? ?cmdPrefix? ?observer? - The convention for names to be in <angleBrackets> is not enforced. - [hook bind] returns a list of events that have active bindings - [hook bind $event] returns all bindings for the event (dict of observer->{subject cmdPrefix}) - The two-argument version [hook bind $event $cmdPrefix] binds cmdPrefix to matching events from any subject, generates and returns a unique observer ID string - [hook bind $event $subject $cmdPrefix] binds cmdPrefix to matching events from $subject only (or any subject is $subject eq {}), generates and returns a unique observer ID string - [hook bind $event $subject $cmdPrefix $observer] binds to matching events from $subject only, and uses $observer as the (non-unique) observer ID. Side effects: - Binding again to the same event/subject/observer combination replaces the existing binding (or removes it if cmdPrefix is empty). > hook call subject event ?args...? Calls all matching binding scripts, and returns a list of returnCode/result pairs (paired elements, not nested lists [*]). [*] Alternatives: return a flat list of observerId/returnCode/result tuples, or a dict observerId->{returnCode result} > hook notify subject event ?args...? As for [hook call], but errors propagate to [interp bgerror] [*] and nothing is returned. > hook forget observer Forget all bindings associated with the given observer. > Starting to get silly: hook foreach subject event ?args...? varList body The binding is called and its returnCode/result assigned into varList, then the body is evaluated (in the caller's context). Not that silly, because [hook call] and [hook notify] are trivially implemented using [hook foreach]. Moreover [hook foreach] can be used to combine the results of bindings in powerful and convenient ways (as Harald Oehlmann suggested), especially if the order in which bindings are called is predictable (my opinion). On 09:59 PM, Kevin Kenny wrote: > coroutine gensym apply {{} { > set x [yield [info coroutine]] > for {set i 0} {1} {incr i} { > if {$x eq {}} {set x gensym} > set x [yield $x$i] > } > }} > That is awesome :) Regards, Twylite |