Version 89 of Generic Calculator Namespace Package Example

Updated 2011-06-25 01:27:54 by gold

Generic Calculator Namespace Package Example


This page is under development. Comments are welcome, but please load any comments in the comments section at the middle of the page. Thanks,gold


gold Here is an eTCL script for generic calculator in a namespace. The original program used global statements to pass data among subroutines. Some routines are working in canvas, clear,fillup,exit,load new testcase and solve with button. With number and all of variables so specified upfront, not sure how to float the calculations into the shell. Other than to put an statement answer is expr{ side1*side2...}


Context and starter code for namespace version

aspect /excerpted/ many of your examples seem to have a common presentation, with a similar GUI consisting of:

a set of labelled boxes for user input a "Solve" button which calls your main logic with the inputs as arguments a few "Testcase" buttons to illustrate examples and test the code "About", "Clear" and "Exit" buttons

I for one would love to see the GUI side of the code factored out into a common framework which each example could share. That way the wiki page for each calculator example could be focussed on the logic, looking something more like this:

namespace eval linear_interp {
  set name "Linear Interpolation Calculator"
  set inputs {"First X value" x1 "First Y value" y1 "Second X value" x2 "Second y value" y2 "Solve for x" xx}
  set about "This is Gold's linear interpolation calculator, © 2011
  .. with some more information on how it works and is used, etc"
  set testcases {
    {10. 10. 200. 50. 123.}
    # etc
  }
  proc calculate {x1 x2 y1 y2 xx} {
    return [expr {some magic here to calculate the result}]
  }
}
load generic_calculator_gui.tcl
generic_calculator_gui linear_interp

As a secondary advantage, your calculator could then without modification be used in other contexts, such as a command line or web tool or automatically invoking all the test cases. Of course, the GUI can also be easily re-skinned to the user's preferences without impacting the main code.

I hope you don't find the above overly critical or discouraging, that's certainly not my intention -- but I do think keeping the above points in mind will make your pages more appealing to other wiki'ers and encourage collaboration .. which is what we're all here for, after all!


gold changes: pulled procs pi,interlinear,pol,errorx,height5. and changed to wm . "title". Former idea was that user could use interpolate routine in the punched console. Conjecture below was that in a namespace version, subroutines would be available, but not all called from the namespace.


In that case, you might consider placing them into a namespace (i.e. ::gold::) and placing that common code on your main "gold" page. Then each other example page can refer to that one common location for the common items. Of course you would want to modify the examples to both load the ::gold definitions file from the gold page, and to make use of the procs therein instead of defining each individually.


 Testcase 1.
quantitynumberunits
star formation 10.rate per year
stars with planets .5stars
potential life 2.
actual life 1.
fraction develop civilization .01 none
fraction technology .01none
years available 10000.years
number of civilizations equal 10.* .5 * 2. * 1. * .01 * .01 * 10000.
answer: 10. civilizations

Screenshots Section

http://img13.imageshack.us/img13/9372/image38b.gif http://img846.imageshack.us/img846/1619/image41c.gif


Comments Section

Please place any comments here, Thanks.


References:


Appendix Code

appendix TCL programs and scripts


*Pretty Print Version

Trial Version under test

          package provide calculatorslot 1.0
            namespace eval slot {
                # program:  "generic calculator in namespace"
                # drake equation usded in calculations
                # written on Windows XP on eTCL
                # working under TCL version 8.5.6 and eTCL 1.0.1
                # gold on TCL WIKI , 24may2011
                variable colorhigh
                variable colorback
                variable answer2
                variable answer3
                variable side1
                variable side2
                variable side3
                variable side4
                variable side5
                variable side6
                variable side7
                variable side8
                variable maxlist
                namespace export clearx
                namespace export fillup
                array set params \
                        {
                            title     {calculator}
                            width     400
                            height    240
                            ratio     1.6888
                            colorback {aquamarine4}
                            colorhigh {brown}
                            maxlistx   5
                            side1      .1
                            side2      .1
                            side3      .1
                            side4      .1
                            side5      .1
                            side6      .1
                            side7      .1
                            side8      .1
                        }
                set maxlist $params(maxlistx)
                proc initdisplay {} {
                    variable titlex
                    variable colorhigh
                    variable colorback
                    variable quantitylist
                    variable maxlist
                    variable side1
                    variable side2
                    variable side3
                    variable side4
                    variable side5
                    variable side6
                    variable side7
                    variable side8
                    frame .frame -relief flat -bg $slot::colorback
                    pack .frame -side top -fill y -anchor center
                    set names $slot::quantitylist
                    foreach i {1 2 3 4 5 6 7 8 9 10} {
                        if {$i >= $maxlist} {break}
                        label .frame.label$i -text [lindex $names $i] -anchor e
                        entry .frame.entry$i -width 35 -textvariable side$i
                        grid .frame.label$i .frame.entry$i -sticky ew -pady 2 -padx 1
                    }
                    frame .buttons -bg $slot::colorback
                    ::ttk::button .calculator -text "Solve" -command { slot::calculate  }
                    ::ttk::button .test2 -text "Testcase1" -command {slot::clearx;slot::fillup 10. .5 2. 1.  .01 .01 10000. 10.}
                    ::ttk::button .test3 -text "Testcase2" -command {slot::clearx;slot::fillup 11. .5 2. 1.  .01 .01 10001. 10. }
                    ::ttk::button .test4 -text "Testcase3" -command {slot::clearx;slot::fillup 12. .5 2. 1.  .01 .01 10002. 10.  }
                    ::ttk::button .clearallx -text clear -command {slot::clearx  }
                    ::ttk::button .about -text about -command {slot::about}
                    ::ttk::button .cons -text report -command { slot::reportx }
                    ::ttk::button .exit -text exit -command {exit}
                    pack .calculator  -in .buttons -side top -padx 10 -pady 5
                    pack  .clearallx .cons .about .exit .test4 .test3  .test2   -side bottom -in .buttons
                    grid .frame .buttons -sticky ns -pady {0 10}
                    . configure -background $slot::colorback -highlightcolor $slot::colorhigh -relief raised -border 30
                    wm title . $slot::titlex
                }
                proc about {} {
                    variable msgx
                    set msg $slot::msgx
                    tk_messageBox -title "About" -message $msg
                }
                
                proc calculate { } {
                    variable maxlist
                    variable answer2
                    variable answer3
                    variable side1
                    variable side2
                    variable side3
                    variable side4
                    variable side5
                    variable side6
                    variable side7
                    variable side8
                    set answer2 1.
                    set answer2 [ expr {$answer2 * $::side1 }]
                    set answer2 [ expr {$answer2 * $::side2 }]                 
                    set answer2 [ expr {$answer2 * $::side3 }] 
                    set answer2 [ expr {$answer2 * $::side4 }]
                    set answer2 [ expr {$answer2 * $::side5 }]
                    set answer2 [ expr {$answer2 * $::side6 }]
                    set answer2 [ expr {$answer2 * $::side7 *1. }]          
                    set ::side8 $answer2 
                }
                proc fillup {aa bb cc dd ee ff gg hh} {
                    variable maxlist
                    foreach i {1 2 3 4 5 6 7 8 9 10} {
                        if {$i >= $maxlist} {break}
                        .frame.entry$i insert 0 "1.0"
                    }
                    variable side1
                    variable side2
                    variable side3
                    variable side4
                    variable side5
                    variable side6
                    variable side7
                    variable side8
                    set ::side1 $slot::params(side1)
                    set ::side2 $slot::params(side2)
                    set ::side3 $slot::params(side3)
                    set ::side4 $slot::params(side4)
                    set ::side5 $slot::params(side5)
                    set ::side6 $slot::params(side6)
                    set ::side7 $slot::params(side7)
                    set ::side8 $slot::params(side8)
                    set ::side1 $aa
                    set ::side2 $bb
                    set ::side3 $cc 
                    set ::side4 $dd 
                    set ::side5 $ee
                    set ::side6 $ff
                    set ::side7 $gg
                    set ::side8 $hh
                }
                proc clearx {} {
                    variable maxlist
                    foreach i {1 2 3 4 5 6 7 8 9 10} {
                        if {$i >= $maxlist} {break}
                        .frame.entry$i delete 0 end
                    }
                }
                proc reportx {} {
                    variable colorwarning
                    variable colorback
                    variable answer2
                    variable answer3
                    variable side1
                    variable side2
                    variable side3
                    variable side4
                    variable side5
                    variable side6
                    variable side7
                    variable side8
                    console show;
                    puts " "
                    puts "    star formation /yr:  "
                    puts "    fraction w/ planets:  "
                    puts "    poss life :  "
                    puts "    actual life:  "
                    puts "    civiliation develop:  "
                    puts "    detectable signs:  "
                    puts "    length years:  "
                    puts "    civilizations:  "
                    puts "answer is   "
                }
            }
            #-------------------------- end namespace
            proc slotshell {} {
                set slot::titlex "Drake Equation Calculator in Namespace"
                set slot::colorback aquamarine4
                set slot::colorhigh brown
                set slot::msgx "Drake Calculator in Namespace.
                from TCL WIKI,
                written on eTCL "
                set slot::quantitylist  {{} {star formation /yr:} {fraction w/ planets:} {poss life :} {actual life:} {civiliation develop:}
                    {detectable signs:} {length years:} { civilizations:} }
                namespace import slot::*
                array set slot::params \
                        {
                            title     {calculatorx}
                            width     999
                            height    999
                            ratio     1.6888
                            colorback {aquamarine4}
                            colorhigh {brown}
                            maxlist     9
                            side1      10.
                            side2      .5
                            side3      2.
                            side4      1.
                            side5      .01
                            side6      .01
                            side7      10000.
                            side8      10.
                        }
                set slot::maxlist $slot::params(maxlist)
                slot::initdisplay
                # button configure statement does not work before or  
                # if initdisplay is not initialized!!!
               .test3 configure  -text "Testcase5"
               .test3 configure  -command {slot::clearx;slot::fillup 11. .5 2. 1.  .01 .01 10009. 10. }
             }
            slotshell

For the push buttons, the recommended procedure is push testcase and fill frame, change first three entries etc, push solve, and then push report. Report allows copy and paste from console, but takes away from computer "efficiency".


Second Example

The 2 line calculator in A little calculator from Richard Suchenwirth et al can be packaged with a namespace. For those with bad eyes, the text shown with green background and big black font has been shown as easier to read than most, as in the old DOS program Wordstar. The window cut and paste procedures in label can be added to the namespace for screen capture of output.

                  # autoindent from ased editor
                  # program " 2 Line Calculator in Namespace"
                  # written on Windows XP on eTCL
                  # working under TCL version 8.5.6 and eTCL 1.0.1
                  # TCL WIKI , 25may2011
         package provide calculatorliner 1.0
            namespace eval liner {
                proc initdisplay {} {
                    pack [entry .e -textvar e -width 50 ]
                    bind .e <Return> {catch {expr [string map {/ *1./} $e]} res; set e $res} ;# RS & FR
                }}
            proc linershell {} {
                namespace import liner::*
                liner::initdisplay
                .e configure -bg palegreen
                .e configure -fg black
                .e configure -font {helvetica 50 bold}
                .e configure -highlightcolor tan -relief raised -border 30                                   
                focus .e
                button .b -text clear -command {set e ""} 
                button .c -text exit -command {exit} 
                pack .b .c   -side left -padx 5
                . configure  -bg palegreen
                wm title . "Suchenworth 2 Line Calculator"
            }
            linershell

Third Example

For the third example, the two line calculator is modified to switch to some operator notation. We would like some operators in the calculator like * 1 2 3 = 6 and + 4 5 = 20. For the switch in the eval button, the if{catch ...expr fails } aborts to an eval command. The return action was left as before.


The program is testing some one line procedures for operator math. This modifies the sum of list procedure from RS in the Zen of Tcl and Elegance vs. performance and see reference Math Operators as Commands.The commands are in the form of !+ 4 5 6= 15, !* 1 2 3 =6, !- 1 2 3 =-4, and !/ 2 3 = 0.66666. The recursive multiplication seems a useful procedure for the TCL calculators, as well as the reciprocal procedure (!1/ below). Assuming at least two arguments, the reciprocal procedure !1/ 1 2 would give the sum of 1/1 and 1/2 or 1.5 The program checked some of the trivial arguments, but not all (eg. !* 0 = 0, !- 0 = 0, !/ 0 = 0,!1/ 1 = 1,!+ 1 = 1,!* 1= 1 )


The program is importing the +*-/ commands from mathops. These commands are working in the form of + 1 2 3=6,* 4 5 = 20, - 5 4=1, and so on. The trig commands are working as sin(.45) and cos(.30).

                    # autoindent from ased editor
                    # program " Modified Line Calculator in Namespace"
                    # written on Windows XP on eTCL
                    # working under TCL version 8.5.6 and eTCL 1.0.1
                    # TCL WIKI , 24jun2011
                    package provide calculatorliner 1.0
                    namespace eval liner {
                        proc evalwild {e} {
                            if [catch {set res [expr [string map {/ *1.0/} $e]]}] {
                                catch {uplevel #0 eval $e} res
                            }
                            set ::e $res
                        }
                        proc initdisplay {} {
                            variable e
                            pack [entry .e -textvar e -width 50 ]
                           bind .e <Return> {catch {expr [string map {/ *1./} $e]} res;set ::e $res } ;# RS & FR 
 
                        }}
                    namespace import ::tcl::mathop::+
                    namespace import ::tcl::mathop::*
                    namespace import ::tcl::mathop::-
                    namespace import ::tcl::mathop::/
                    proc !+ args { expr [join $args +] }
                    proc !* args { expr [join $args *] }
                    proc !- args { expr [join $args -] }
                    proc !/ args { expr [join $args *1./] }
                    proc !1/ args { expr [ join $args  +1./ ]}
                    proc linershell {} {
                        namespace import liner::*
                        liner::initdisplay
                        .e configure -bg palegreen
                        .e configure -fg black
                        .e configure -font {helvetica 50 bold}
                        .e configure -highlightcolor tan -relief raised -border 30
                        focus .e
                        button .a -text eval -command {liner::evalwild $e}
                        button .b -text clear -command {set e ""}
                        button .c -text exit -command {exit}
                        pack .a .b .c   -side left -padx 5
                        . configure  -bg palegreen
                        wm title . "Modified Line Calculator"
                    }
                    linershell

tcl8.5 code scraps

 push report button and etcl console comes up
 1% namespace import ::tcl::mathop::*
 2% * 5 6 7 8 8
 13440
 3% * 2 2 2 2 2 2 2 2 2 2 
 1024
 * $slot::params(side1) $slot::params(side1) $slot::params(side2) $slot::params(side3)
 2%  * $slot::params(side1) $slot::params(side2) $slot::params(side3) $slot::params(side4)
 10.01
 4% winfo children .
.frame .buttons .calculator .test2 .test3 .test4 .clearallx .about .cons .exit
 . configure -background $slot::colorback -highlightcolor $slot::colorhigh -relief raised -border 30
 # configure test buttons in the shell 
 # statements working in the console started by push report.
 #? .test3 reported as unknown when loaded in the shell?
 # configure statement does not work if initdisplay is not initialized!!!
 .test3 configure  -command {slot::clearx;slot::fillup 19. .5 2. 1.  .02 .02 10009. 10. }
 .test3 configure  -text "chg_Testcase5"
  #??? console eval {.test3 configure  -text "Testcase 5"}