From: Will Duquette Date: May 29, 2004 1:53:06 PM PDT To: snit@lists.wjduquette.com Subject: [Snit] Snit Reconsidered #6: Snit Meta-Programming This is the sixth in a number of essays I'm writing as I work toward Snit 1.0. Here's a nifty idea; it's so cool I can hardly contain myself. Best of all, it's a simple addition to the Snit language. I'll begin with an example: snit::type dog { # Define "breed" to be property variable breed mutt method breed {args} { if {[llength $args] == 0} { set breed } elseif {[llength $args] == 1} { set breed [lindex $args 0] } else { error "expected '$self breed ?value?'" } } } The above code gives the dog type a property called "breed"--effectively, a public variable that can be set like this: dog spot spot breed spaniel puts "Spot is a [spot breed]" In Tk code you'd usually use an option rather than doing something like this; however, some Snit users use this pattern regularly. The problem is, you have to repeat the code for every property you want to define. Now, consider this code instead: snit::macro property {name} { variable $name set body { if {[llength $args] == 0} { set %n } elseif {[llength $args] == 1} { set %n [lindex $args 0] } else { error "expected '$self %n ?value?'" } } method $name {args} [string map [list %n [list $name]] $body] } snit::type dog { property breed } The snit::macro command defines a new macro, which is simply a proc that executes in the slave interpreter that Snit uses to interpret Snit type definitions. The "property" macro simply executes the same type definition statements used in the previous example. But now, you can define as many properties as you like. You can also use snit::macro to support conditional compilation. Suppose you've got a type that will make use of a compiled extension if it's available, but will fall back to its own implementation otherwise. You can distinguish this at type definition time. if {[catch {package require FastPackage}]} { snit::macro gotFastPackage {} {return 0} } else { snit::macro gotFastPackage {} {return 1} } snit::type mytype { if {[gotFastPackage]} { method doComputation {} { # Use FastPackage } } else { method doComputation {} { # Use fallback implementation } } } The one restriction is that you're not allowed to rename the standard Snit type definition commands. ------------------------------------------------------------- will -at- wjduquette.com | Catch our weblog, http://foothills.wjduquette.com | The View from the Foothills _______________________________________________ Snit mailing list Snit@lists.wjduquette.com http://lists.wjduquette.com/listinfo.cgi/snit-wjduquette.com