Version 105 of Command Line Calculator in Namespace Package Example

Updated 2014-05-21 16:46:04 by gold

Command Line Calculator in Namespace Package Example

This page is under development. Comments are welcome, but please load any comments in the comments section at the bottom of the page. Please include your wiki MONIKER in your comment with the same courtesy that I will give you. Its very hard to reply intelligibly without some background of the correspondent. Thanks,gold


Introduction

gold Here is an eTCL script for command line calculator in a namespace. 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.


The modified line calculator can 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 multiplication with polish notation 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 mathop. 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). The user can draw pi, deg2rad, and other procedures from Oneliner's Pie in the Sky. To put the math procedures inside the namespace, the catch {uplevel #0 eval $e} res statement can be modified to catch { eval $e} res


 Testcase 1.

Examples of operator notation from command line, importing mathop, and math local procedures. These examples include code that might be incompatible, inefficient, or redundant if installed in the same program. As discussed below, the local math procedures are not as efficient as importing mathop or mathfunc.

quantitynotationresultenabling statementtime result micros per iteration
a * 1 2 3 6namespace import ::tcl::mathop::* ;# import all1.305
b + 1 2 3 6 namespace path { ::tcl::mathop }1.464
c - 1 2 3 -5namespace import ::tcl::mathop::-1.052
d !1/ 1 2 1.5proc !1/ args { expr join $args +1./}20.89
e !+ 1 2 36proc !+ args { expr join $args +}15.129
f * 5 6 7 8 813440namespace import ::tcl::mathop::\\*1.494
g * 2 2 2 2 2 2 2 2 2 2 1024namespace import ::tcl::mathop::\\*5.061
h* 4 520namespace import ::tcl::mathop::\\*0.847
i + 4 5 9namespace import ::tcl::mathop::+0.845
1a pi 3.14proc pi {} {expr {acos(-1)}} ;#AMG 3.479
1b 3.*[pi] 9.42proc pi {} {expr {acos(-1)}} ;#AMG 3.98
1c acos -1 3.14tcl::mathfunc::acos -1 1.786
2a deg2rad0.0174 proc deg2rad {} {return expr {1.*[pi/180.} ]}5.356
3a rad2deg57.295 proc rad2deg {} {return expr {180./1.*[pi} ]}5.356
4a sqrt 5 2.23namespace import ::tcl::mathfunc::* ;# import all1.21
4a 1+1 2expr {1+1}0.967
4a + 1 1 2namespace import ::tcl::mathop::+1.169
4a incr 1 2incr 1.89

Screenshots Section

http://img846.imageshack.us/img846/1619/image41c.gif


Comments Section

Please place any comments here, Thanks.

In your example, you have these code snippets:

  namespace import ::tcl::mathop::\\+
  namespace import ::tcl::mathop::\\*
  namespace import ::tcl::mathop::\\-
  mamespace import ::tcl::mathop::\\/

On all but the import of * the \\ is superflurous, in that the only characters that are special to namespace import are glob-style characters (* and ?). However, all four lines can be replaced by this:

  namespace path { ::tcl::mathop }

With the result that not does +, -, *, and / become available, but every other ::tcl::mathop is also becomes available for use.

A bit further down, you have this:

  proc !+ args { expr [join $args +] }
  proc !* args { expr [join $args *] }
  proc !- args { expr [join $args -] }

If you make accessible the +, -, and * procs via namespace path/import, then you do not need to perform an expr indirection and join on arguments, because the ::tcl::mathop procs for +, -, and * already handle plural arguments:

  % + 1 2 3
  6

If you prefer the "look" of !+, !*, and !-, there is a much more efficient way of achieving the same. Setup an interpreter alias:

  foreach {new existing} [ list !+ + !* * !- - ] {
    interp alias {} $new {} $existing
  }

Now you have !+, !*, and !- available, but without the overhead of 1) a local proc call, 2) a join of arguments, and an expr call (to then parse the joined arguments).


gold Changed namespace import ::tcl::mathop::\\+, etc to namespace import ::tcl::mathop::*. Pulled local math procedures from code. Installed namespace path { ::tcl::mathfunc } Thanks.


The problem was you tried "mathfunc" not "mathop" in your namespace path call. ::tcl::mathfunc is a different namespace from ::tcl::mathop. Both contain math "things", but the +, -, *, /, etc. procs exist only in ::tcl::mathop. If you want access to all the math operators plus all the math functions, i.e. everything math related, the proper call is "namespace path { ::tcl::mathop ::tcl::mathfunc }


References:


Appendix Code

appendix TCL programs and scripts


*Pretty Print Version

                    # 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 path { ::tcl::mathop ::tcl::mathfunc }                    
                    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

 1% namespace import ::tcl::mathop::* ;#import all
 2% * 5 6 7 8 8
 13440
 3% * 2 2 2 2 2 2 2 2 2 2 
 1024
        proc call {args} {uplevel catch [list $args]}
        proc math { args } { set tcl_precision 17; puts [ expr [ expr { $args } ] ] }