Arjen Markus (17 October 2008) Normally I do not use any (formal) OO system to create my Tcl programs or libraries. But yesterday I bit the bullet - here is a small experiment to make a Snit type to store and manipulate data. Nothing fancy and certainly not something actually useful, I just wanted to get a feel for Snit (or any other kind of Tcl OO system).
Some remarks (see also the code):
NEM 18Oct08: I've changed the code below to fix some of these problems and use some more snit features. Hope the changes are useful!
# wrap_stat.tcl --
# Small experiment with Snit and wrapping some of the
# numerical functions in Tcllib, to get a more object-oriented
# approach.
#
# Some remarks:
# - dataset is a new command inside the mySnitExperiment, but it
# is not imported into the filter method.
# - without the global namespace in the call to filter (main code),
# the new object will reside in the mySnitExperiment namespace.
# - because I was too lazy to try and do it the more elegant way,
# the expression is not surrounded by braces, but explicitly
# escapes the $ before x. (y gets substituted, x not).
#
# Question:
# Can I define new methods on the fly for a particular object or
# redefine existing ones?
#
package require snit
package require math::statistics
namespace eval mySnitExperiment {
namespace import ::math::statistics::*
# dataset --
# Define a simple Snit type that contains data and can deal with
# statistical operations on these data. Could be extended to
# include plotting functionality.
#
::snit::type dataset {
option -data -default {} -configuremethod ChangeData
variable mean {}
variable cached 0
constructor args { $self configurelist $args }
method ChangeData {option value} {
set options($option) $value ;# commit change
set cached 0
}
method setdata {data} {
$self configure -data $data
}
method get {} {
return $options(-data)
}
method mean {} {
if { ! $cached } {
set mean [::math::statistics::mean $options(-data)]
set cached 1
}
return $mean
}
#
# Filter creates a new object with data that conform to
# some predicate, p.
#
method filter {name p} {
set newData {}
foreach x $options(-data) {
if {[{*}$p $x]} { lappend newData $x }
}
return [$type create $name -data $newData]
}
}
}
# Separate construction of functions/predicates from application
proc func {params body args} {
list ::apply [list $params [list expr $body]] {*}$args
}
# main --
# Test this very basic data type
#
::mySnitExperiment::dataset create series1
series1 setdata {1 2 3 4 5 6}
puts "Data: [series1 get]"
puts "Mean: [series1 mean]"
set y 4
series1 filter ::series2 [func {y x} {$x > $y} $y]
puts "Filtered data: [series2 get]"
AM I ran into a few difficulties with Snit or, rather, my understanding of it, and I posted them on comp.lang.tcl. The replies made me wonder about XOTcl - so, here is an Experiment with numerical methods and XOTcl.
AM Here is, however, a second experiment with Snit: Mathematical functions and Snit.