'''[ycl] shelf''', by [PYK], is a simple yet effective [Programming with Prototypes%|%prototype]-based [object orientation%|%object system]. ** Description ** Are you confused/bored/annoyed by class-based object systems? Then `shelf` might be the system for you! `shelf` provides the functionality needed to work with [namespace ensemble%|%namespace ensembles] as objects in a prototype-based object system. In this documentation, the word ''prototype'' signifies the namespace ensemble that is the [handle] for the object. The ensemble map defines the interface, and it is expected that all methods are called through the ensemble, even when called by other methods bound to the same prototype. Because of this methods usually take the name of the ensemble as their first argument, although this is just a convention. `shelf` won't be offended in the slightest if the name of the ensemble is passed in some other position, or not at all. `shelf` arranges for the ensemble's namespace to be deleted when the ensemble is deleted. The code footprint of shelf is quite small, and that's partially because components of it have been refactored into other components of [ycl]. `[ycl] dupensemble` provides the ability to produce new namespaces based on a prototype namespace, and `[ycl] var` provides methods such as `$`, `$.exists`, and `$.locate` for reading variables up the hierarchy of a prototype. A prototype has a `prototype` method that can be used to access methods and attributes in prototypes from which the it was derived. `shelf` does not currently utilize [TclOO], but it certainly might in the future. ** Built-in Methods ** The first argument to all built-in methods is the name of the ensemble, and is not noted in the descriptions here. '''`$`''' '''''`name`''''': Returns the value of the first variable named ''name'' in the hierarchy for the prototype. '''`$.locate`''' '''''`name`''''': Returns the [namespace qualifiers%|%fully-qualified] name of the first variable named ''name'' in the hirarchy for the prototype, or an error if a matchin variable is not found. '''`$.exists`''' '''''`name`''''': Like `$.locate`, but returns a boolean, indicating whether a matching variable was found. '''`~`''': Executed just prior to the deletion of the ensemble. '''`asmethod`''' '''''spec''''': ''spec'' is a method specification of the form : ''args'' ''objvars'' ''nsvars'' ''body'' : Where ''args'' and ''body'' are the standard arguments to `[proc]`. ''objvars'', is a list of names of variables that belong to the prototype, and ''nsvars'' is a list of names of variables in the namespace in which the procedure will be defined. `asmethod` transforms ''body'' such that variables ''objvars'' and ''nsvars'' are [upver%|%linked] in the local scope of the procedure to the appropriate variables. This allows the procedure body to be written in an a manner that is agnostic to the particular object system in use, since it need only concern itself with local variables. Other object systems may use the same ''spec'', linking the local variables as appropriate for that system. : `shelf` uses this internally, so an example, although a bit convoluted at the moment (the refactoring is in progress), can be found [http://chiselapp.com/user/pooryorick/repository/ycl/artifact/a7830a4032ea503f%|%here] '''`eval`''' '''''`script`''''': Evaluate ''script'' in the namespace of the ensemble. '''`init`''': Executed by `new`. The default `init` does nothing. Provides a convenient hook for customing the initialization of a newly-created prototype. '''`method`''' '''''`cmdname`''''': Register a command as a method of the ensemble by adding it to the map and arranging for the fully-qualified name of the ensemble to be passed as the first argument to the command. `method` does not transform the command in any way, but it must already exist. '''`new`''' '''''`name`''''': Create a new copy of the prototype. If ''name'' is the [empty string], automatically select an appropriate name. Returns tkjhe name of the new prototype. The namespace ensemble of the current prototype is copied to the new prototype, and occurrences in the map command prefixes of the fully-qualified name of the the current prototype are replaced with the name of the new prototype. The map entry for `parent` is modified so that it contains the fully-qualified name of the current prototype. '''`ns`''': Returns the name of the namesapce associated with the ensemble. '''`ondeath`''' '''''`script`''''': Arranges for ''script'' to be evaluated in the [global] namespace when the ensemble is deleted. This command is currently additive. with no way to delete any already-registered scripts, except by using `[trace]` directly. It isn't anticipated that such a feature would be needed, but it could be added at some point. '''`prototype`''': Returns the name of the prototype for this prototype. '''`subcmd`''' '''''`cmdname`''''': Like `method`, but doesn't arrange for the name of the ensemble to be passed as the first argument to the command. ** Built-in Prototypes ** `glass`: a prototype configured such that any command in its associated namespace reachable as a subcommand prototype. `shelf`: The mother of all prototypes, including itself. ** Example ** ====== shelf new swallow swallow $ airspeed 9 proc fly _ { upvar 0 [$_ $.locate airspeed] airspeed puts "$_ is flying at a speed of $airspeed!" } swallow method fly swallow fly swallow new european european $ airspeed 11 european $ airspeed ;# -> 11 european fly ====== <> object orientation