What: scrobj - scripted Tcl_Objects
Where: http://nullhomotopie.de/programs/scrobj-page.html Description: extension that allows to implement Tcl_Object types on the script level. Updated: 12/2008 Version: 1.0
Quote from the man page:
Tcl's fundamental mantra says that "everything is a string" and much of Tcl's simplicity derives from this rule. Strings can, however, carry with them an internal representation as some other data type, and this is one reason for Tcl's astonishing performance. For example, Tcl maintains such an internal representation for integers, lists, byte- codes, and many other types. Extension writers have long been able to add new custom types using Tcl's C interface. The scrobj package allows you to do the same from the script level. Unfortunately, in order to achieve this the package has to violate a basic assumption of Tcl's bytecode engine, namely that it is not get- ting invoked recursively from a call to Tcl_GetString. A consequence is that scrobj can be used to crash the application, although this does require a rather contrived setup. To prevent such crashes in the legitimate cases the package uses a ded- icated Tcl interpreter for every registered type. Both Tcl 8.5 and Tcl 8.6 seem to tolerate recursive invocations of the bytecode engine, as long as they execute in different interpreters.
Here's an example that's taken from the included scrobj::rational package: it implements a new Tcl_Object type for rational numbers:
package require scrobj 1.0 # Register the object type for rational numbers. A fraction $a/$b # is represented as [list $a $b]. scrobj register scrobj::rational { irep { foreach {num den} $irep break # update string from internal rep if {$den != 1} { return $num/$den } return $num } } { inp { # parse rational number from string if {[regexp {^([*-]?[0-9]+)(/[0-9]+)?$} $inp -> num den]} { if {$den eq ""} { return [list $num 1] } set den [string range $den 1 end] if {$den != 0} { return [list $num $den] } return -code error "denominator must not be zero" } return -code error "rational number expected" } }
This declares a new type "scrobj::rational" with the given conversion routines between the string representation and the internal representation. Implicitly, a dedicated new Tcl interpreter is created where these conversion routines are executed. The type can then be used as follows:
# get the internal representation of $a as a rational number: scrobj convert scrobj::rational $a # generate a new value of type "rational" with given numerator and denominator scrobj value scrobj::rational {17 456}
The package comes equipped with two sample subpackages scrobj::expression and scrobj::rational that serve to illustrate its use. See the files "rational.tcl" and "expression.tcl" for details.
Lars H: Interesting! In proper integers implementation I toyed a bit with the idea of having Tcl_Objs whose intrep was a "parsed" form of the string rep, but that still required writing C for the conversions (and the project was thoroughly obsoleted by TIP#237 anyway). Making it possible to use Tcl also for the conversions is a nice step forward. Having to run the conversion code in a separate interpreter may feel like a hack, but it could also be a good thing, since generating a string or internal representation is supposed to be side-effect free.