The Egyptian wannabe developer/sys-admin ---- [Category Tcl Editors] ---- # Allow spaces and underscores in long number for easy reading proc norm {num} { if {[regexp {^(\s|\d|_)*(\.)?(\s|_)*(\d)+(\s|\d|_)*$} $num]} { string map {_ {} \ {}} $num } else { error "Number: $num is not in normal form" } } Example: expr [norm 10_000_000] + [norm 100._10_100] => 10000100.101 [AMG]: Neat! Here, this proc does the reverse (adds underscores): proc abnorm {num} { if {![string is double -strict $num]} { error "not a number: \"$num\"" } set point [string first . $num] if {$point == -1} { set point [string length $num] } else { for {set pos [expr {$point + 4}]} {$pos < [string length $num]} {incr pos 4} { set num [string replace $num $pos $pos _[string index $num $pos]] } } for {set pos [expr {$point - 3}]} {$pos > 0} {incr pos -3} { set num [string replace $num $pos $pos _[string index $num $pos]] } return $num } Example: % abnorm 100.10100 100.101_00 % abnorm 10000000 10_000_000 % abnorm 10000100.101 10_000_100.101 This code doesn't handle exponential notation or even negative numbers. I don't want to put much more effort into it, since I'm more interested in seeing some clever [[[regsub]]] version. If anyone wants to give it a try, ... go right ahead. Have a blast. [AMG]: I woke this morning with an inspiration about how to do this with [[[regsub]]]. proc sreverse {str} { set result "" for {set i [expr {[string length $str] - 1}]} {$i >= 0} {incr i -1} { append result [string index $str $i] } return $result } proc abnorm {num} { if {![string is double -strict $num]} { error "not a number: \"$num\"" } regexp {^(-|\+)?(\d+)?(\.)?(\d+)?(e|E)?(-|\+)?(\d+)?$} $num num sm int dot frac e se exp set result $sm append result [regsub -all {(?!^)(?=(\d{3})+$)} $int _] append result $dot append result [sreverse [regsub -all {(?!^)(?=(\d{3})+$)} [sreverse $frac] _]] append result $e$se$exp return $result } I don't bother putting _'s in the exponent because we can't have exponents 1000 and up. I have to do the [['''sreverse''']] bit because while we may have look-ahead regular expressions, we do not have look-behind. [AMG], 15 Dec 2006: There is now a [[[string reverse]]] command. ---- [RS] proposes this simpler version of ''sreverse'': proc sreverse str { set res "" set i [string length $str] while {$i} {append res [string index $str [incr i -1]]} set res } % sreverse hello olleh [AMG]: I saw that on the [Additional string functions] page, but I chose not to use it because even though it may be more efficient there's a few things I don't like about its style. (This doesn't reflect on your code, merely my preferences.) * I feel that it's an abuse to consider 0 to be false and nonzero to be true. I always explicitly make the comparison with zero. [Java] requires this, by the way. I find this especially important when using [[[string compare]]], where a naive reader would assume that ![[[string compare]]] tests for string inequality. * In many cases I dislike simultaneously using a command's side effect and its return value. Does [[[incr] i -1]] return the original value of '''$i''' or the changed value? I know the answer, but I would like it to be evident from the code structure. * [[[set] res]] bothers me because I'm accustomed to seeing [[[return]]]. I like being explicit about the fact that a proc returns a value, rather than relying on the (standard, documented) fall-off-the-bottom behavior. * I always brace the second argument to [[[proc]]] because that reduces the chance of typo if I add arguments or defaults later on. But I also see that my code's use of [[[expr]]] makes it hard to read. [[[for]]] is always funny, too. If not for the high price, I might consider using the [[[unknown]]] I mention at the bottom of the page of the same name, and write: proc sreverse {str} { set result "" foreach i [[expr {[string length $str] - 1}]-0] { append result [string index $str $i] } return $result } Hmm, that's pretty weird-lookin' too. Now you've got me wishing for '''$(...)''' syntax for [[[expr]]], but we can never have that because it's already used for arrays named "". '''$[[...]]''' maybe? Ah, I know how to do it without (explicit) [[[expr]]]. This is quite nice, I think: proc sreverse {str} { set result "" for {set i 0} {$i < [string length $str]} {incr i} { append result [string index $str end-$i] } return $result } Oh, look what we've done. We hijacked SYStems's page and turned it into a style discussion! - [RS] keeps on the hijacking with a collecting wrapper for simple loops: proc loop {_var from to body} { upvar 1 $_var var set res {} for {set var $from} {$var < $to} {incr var} {lappend res [uplevel 1 $body]} set res } % loop i 0 10 {set i} 0 1 2 3 4 5 6 7 8 9 Then we can write: proc sreverse {str} { join [loop i 0 [string length $str] {string index $str end-$i}] "" } % sreverse hello olleh ---- [Quoting] [Quoting Styles] ---- [Category Person]