TIP 92: Move Package Load Decisions to Application Developer

Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2017 Conference, Houston/TX, US, Oct 16-20
Send your abstracts to tclconference@googlegroups.com
by Aug 21.
Author:		Clif Flynt <clif@cflynt.com>
State:		Withdrawn
Type:		Project
Vote:		Pending
Created:	13-May-2002
Post-History: 
Tcl-Version:	8.4
Keywords:	package require, namespace, pkg_mkIndex

Abstract

This TIP makes the loading of packages far more flexible, so as to better support their use by application authors in situations above and beyond those foreseen by the developer of the package.

Overview

I believe that we've been misdirecting our efforts in solutions to the Package issue.

These techniques limit the application writer to the behavior (and uses) envisioned by the package author and is counter to the concept that application developer best understands how they need a tool to perform for their application. The Tcl community, in particular, has grown largely because the tools have had applications far beyond those imagined by their initial developers.

Moving the decisions about when and how to load a package from pkg_mkIndex to the package require command allows the application writer the freedom to find new styles of use that the package author may not have conceived.

Being able to force an immediate load into the current namespace rather than always loading packages into the global scope provides support for lightweight object style data structures without the need for extensions like Incr Tcl, OOTcl, etc.

Loading a package/namespace into the current namespace provides mechanisms for lightweight inheritance, and since namespaces can contain both code and data, loading a namespace multiple times (in separate namespaces) is a lightweight aggregation model.

I do not propose that this power removes the need for full object oriented programming models within the Tcl community. However, I believe that putting the power to develop these lightweight models into the application developer provides the developer with a more versatile tool kit than they currently have. (One that I've been using for several years, with workarounds.)

This proposal is to add new flags to the package require command, allowing an application developer to determine when and how to load a package.

-current: Load the package into the current namespace rather than the global space. Implies immediate.

-multiple: Allow loading multiple copies of this package, for use with -current when the application programmer wishes to create multiple nested copies of a package.

-immediate: Load immediately, rather than defer loading the package until needed. This is the default behavior with Tcl 8.3 and later.

-defer: Load package when required. The default with Tcl 8.2 and earlier, or when pkg_mkIndex -lazy used with Tcl 8.3.

-exact: No change to this option. Requires an exact Major/Minor revision match to be an acceptable package.

Script Example

The code below implements a simple stack object that can be merged into other namespaces to create objects that contain individual stacks.

 package provide stack 1.0
 namespace eval stack {
     namespace export push pop peek size
     variable stack ""

     proc push {val} {
         variable stack;
         lappend stack $val
     }

     proc pop {} {
         variable stack;
         set rtn [lindex $stack end]
         set stack [lrange $stack 0 end-1]
         return $rtn
         }

     proc peek {{pos end}} {
         variable stack;
         return [lindex $stack $pos]
     }

     proc size {} {
         variable stack;
         return [llength $stack]
     }

 }

With this data structure available, the guts of a Tower of Hanoi puzzle becomes simple:

 namespace eval left {
         package require -current -multiple  stack 1.0
         namespace import [namespace current]::stack::*
     }   
 namespace eval center {
         package require -current -multiple  stack 1.0
         namespace import [namespace current]::stack::*
     }
 namespace eval right {
         package require -current -multiple  stack 1.0
         namespace import [namespace current]::stack::*
     }

 proc move {from to} {
         ${to}::push [${from}::pop]
     }

This creates 3 'objects' each of which contains a private stack with the stack methods.

Reference Implementation

A reference implementation of the -current and -multiple flags has been created for Tcl 8.4a4 and is available at http://noucorp.com/PkgPatch8.4.zip

The implementation required these modifications to generic/tclPkg.c:

Minimal testing has been done using pure Tcl packages.

History