**Tcl Math Syntax is Inferior to JavaScript/Python/Ruby/C/C++/Java/Perl/PHP** ***Problem*** Tcl's mathematical expression & assignment syntax is unnecessarily verbose and thus inferior to many other programming languages (especially [Ruby], [JavaScript] & [Python]). Every extra redundant character means: * Potential typos/errors * More information that needs to be read and processed by both people and computers * More information that needs to be typed * Tarnishing Tcl's clean, simple and beautiful space delimited syntax ***Proposed Solution*** Add more standard operators to [tcl::mathop] in Tcl 8.6, such as: ====== = += -= *= /= %= **= &= |= ^= <<= >>= ++ -- ====== And add the function '''pi()''' to [tcl::mathfunc]. Quick and dirty hack implementation for demonstration purposes: ====== proc = {var args} { upvar 1 $var uvar set uvar [expr $args] } proc += {var args} { upvar 1 $var uvar set uvar [expr $uvar + ($args)] } proc ++ var { upvar 1 $var uvar incr uvar } ====== ***Examples/Comparisons of Clarity & Line Lengths*** Assign Result of Single Operator Expression ====== s = 60 * 60 * 24 # JavaScript, Python, Ruby $s = 60 * 60 * 24; # Perl, PHP int s = 60 * 60 * 24; # C, C++, Java set s [expr 60 * 60 * 24] # Tcl set s [* 60 60 24] # Tcl 8.5 = s 60 * 60 * 24 # Proposed Tcl 8.6 ====== Assign Result of Multiple Operator Expression (Long Version) ====== y = m * x + b # JavaScript, Python, Ruby $y = $m * $x + $b; # Perl, PHP float y = m * x + b; # C, C++, Java set y [expr $m * $x + $b] # Tcl = y $m * $x + $b # Proposed Tcl 8.6 = y m * x + b # Future Fantasy Tcl: lookup # unrecognized tokens as variables/procedures ====== Assign Result of Multiple Operator Expression (Short Version) ====== y=m*x+b # JavaScript, Python, Ruby $y=$m*$x+$b; # Perl, PHP float y=m*x+b; # C, C++, Java set y [expr $m*$x+$b] # Tcl = y $m*$x+$b # Proposed Tcl 8.6 = y m*x+b # Future Fantasy Tcl: lookup # unrecognized tokens as variables/procedures ====== Assign Result of Mixed Expression ====== $x = sin( pi() / 2 ); # PHP x = Math.sin Math::PI / 2 # Ruby x = Math.sin( Math.PI / 2 ) # JavaScript x = math.sin( math.pi / 2 ) # Python double x = Math.sin( Math.PI / 2 ); # Java const double PI = acos( -1 ); # C, C++: do it yourself Pi double x = sin( PI / 2 ); use constant PI => atan2( 1, 1 ) * 4; # Perl: do it yourself Pi $x = sin( PI / 2 ); proc pi {} { expr acos( -1 ) } # Tcl: do it yourself Pi set x [expr sin( [pi] / 2 )] = x sin( pi() / 2 ) # Proposed Tcl 8.6 = x sin pi / 2 # Future Fantasy Tcl: optional parenthesis ====== Accumulate/Addition ====== s += 60 # JavaScript, Python, Ruby s += 60; # C, C++, Java $s += 60; # Perl, PHP incr s 60 # Tcl += s 60 # Proposed Tcl 8.6 ====== Scale/Multiplication ====== x *= 2 # JavaScript, Python, Ruby x *= 2; # C, C++, Java $x *= 2; # Perl, PHP set x [expr {$x * 2}] # Tcl *= x 2 # Proposed Tcl 8.6 ====== Increment ====== ++x # JavaScript ++x; # C, C++, Java ++$x; # Perl, PHP x += 1 # Python, Ruby incr x 1 # Tcl incr x # Tcl 8.5 ++ x # Proposed Tcl 8.6 ====== ***Post Script*** If this has been previously recommended/discussed then could someone provide a link? I know this wiki may not be the ideal place to propose this, but it is the quickest. ---- [NEM] See e.g. [let] and [expr shorthand for Tcl9]. The proposed = command will be non-optimal as shown. See [Brace your expr-essions] for reasons why. The same applies to the other assignment short-cuts, which is probably why they were not added. See also http://tip.tcl.tk/ for various relevant TIPs along with rationale discussions. A ''pi()'' function is a simple addition. Such requests can either be TIPed or added as Feature Requests to the Tcl project tracker at http://sourceforge.net/projects/tcl. [techmisc] 2008-07-02 Re: Links: The expr shorthand link has a good discussion, but unfortunately concentrates mainly on expr and overlooks the set and expr combination. The combination is important because even if you were to only change Tcl's syntax/grammar and dedicate symbols to replace expr (eg. backticks), you would still need to use set which makes code unnecessarily verbose/lengthy. Compare Tcl with and without assignment (ie. combined set & expr) operators: ====== # Tcl for {set i 1} {$i <= 1024} {set i [expr {$i * 2}]} { myfunc $i } for {set i 0} {$i <= 10} {incr i} { myfunc [expr {2 ** $i}] } # Tcl (backticks for expr) for {set i 1} {$i <= 1024} {set i `$i * 2`} { myfunc $i } for {set i 0} {$i <= 10} {incr i} { myfunc `2 ** $i` } # Tcl (assignment operators) for {= i 1} {$i <= 1024} {*= i 2} { myfunc $i } for {= i 0} {$i <= 10} {++ i} { myfunc [expr {2 ** $i}] } # Tcl (backticks for expr & assignment operators) for {= i 0} {$i <= 10} {++ i} { myfunc `2 ** $i` } // JavaScript for (i = 1; i <= 1024; i *= 2) myfunc( i ) for (i = 0; i <= 10; i++) myfunc( Math.pow( 2, i ) ) ====== Re: "Non-optimal" code: That's why it's qualified as "quick and dirty", "hack" and "demonstration". :-) Thanks for the info on expr-ession execution. But since they run many (eg. 10!) times faster just by passing 1 argument instead of N arguments, then maybe expr or Tcl's parser could be improved. And I won't be adding a TIP because I'm a Tcl newbie. Hopefully someone else will pick up these ideas and run with them. I declare all content I have submitted Public Domain. ---- [Sarnold] See [xsource] for an attempt to solve this problem. [Lars H]: And [infix] for yet another approach. [techmisc] 2008-07-02 Thanks for the links. ---- [ZB] 30.06.2008. So, "duplicated syntax"? Both "++ x" and "incr x"? But what for? Those, who are accepting TCL's syntax, won't need it. For those, who feel uncomfortable with TCL's syntax, it's too limited change to be persuaded: "now you'll like TCL". So again: what for? I would to quote something from the main page: "Tcl is a simple-to-learn yet very powerful language. Its syntax is described in just a dozen rules". Not enough rules - let's add some more? Perhaps it could be much better to switch to "project [L]" syntax change proposals completely instead? Just to keep consistency. [techmisc] 2008-07-02 Tcl already has duplicated syntax: ====== set x [expr {$x + 1}] incr x set x [expr {pow( 2, 3 )} ] set x [expr {2 ** 3} ] ====== What's important is the duplicated syntax doesn't break Tcl's "command arg arg..." prefix style grammar/syntax. Neither do "= y $x", "+= s 60" or "++ x". And they are industry standard operators. If that's a problem, consider them C operators, which is where all the other languages got them. If that's still a problem, consider the syntax of the expr command is different to Tcl syntax. It probably came from C. Tcl is written in C, and it's almost certain operators just like the ones proposed are used. Also, the fact that there are so many other proposed solutions to expr & assignment syntax shows Tcl programmers believe there's room for improvement. You can still use "set x [expr {$x + 1}]". But you can also use "++ x" or "+= x 1" because they're shorter, simpler and clearer. ---- [WJG] (01/07/08) Personally I find that whilst the alternative symbols for keywords such as incr and set might make Tcl 'look more familiar' they are not necessary. In fact, I suspect that the replacing 'incr s' with '+= s' will cause as many key board entry errors. Indeed, my overall comment on such introspection would be that if a coder needs [python] or something else, then use it, Saying that Tcl needs to me more like python, [perl] or [c++] is just an argument against using Tcl rather than urging the introduction of symbol synonyms. Extensibility, as I understand it implies a simple core Tcl with flexibility entering through the development project led extensions. With so many packages now becoming shipped with Tcl, a 'batteries included' version of Tcl is becoming bloatware. The more that is added, the more there is to dislike. Surely, there will be a point when potential users, unable distinguish what is core and add-on will find it all too confusing and therefore pursue an alternative. I myself went through a period of introspection a while ago and seriously thought of swapping from Tcl to something else, such as [Lua] or Python using [wxWidgets]. But I came back to Tcl, not for anything new that has come along, but because the original idea was both simple and clean. The command syntax, in keeping the flavour of shell scripting is robust. Perhaps the emergence of eclectic collections of packages and extensions is because Tcl is now being 'designed by committee' rather than the outcome and the vision of its original creator. [techmisc] 2008-07-02 Re: Familiarity & Other languages: This proposal isn't about other languages. They were listed to demonstrate how Tcl can be improved by adding standard mathematical operators which would reduce character bloat. Re: Not necessary: Neither is incr, you can always "set x [expr {$x + 1}]". Neither are multiple loop control structures (for, foreach, while). Neither are multiple branching control structures (if, switch). But Tcl has them all because they make code simpler and cleaner. Re: Will cause typing errors: Actually the exact opposite. Compare: ====== set x [expr {$x * 2}] # 21 keystrokes *= x 2 # 6 keystrokes ====== Statistically you'll make more typos in Tcl as it is. And that's with short variable names. What about more meaningful names, which you have to repeat twice? ====== set well_named_var [expr {$well_named_var * 2}] # 47 keystrokes *= well_named_var 2 # 19 keystrokes ====== Re: Extensibility: The operators were proposed for the tcl::mathop namespace so they won't bloat Tcl's core commands. Re: Confusion: Any library feature you don't want to use can be ignored. But by including them in Tcl they will be a standard as opposed to each programmer reinventing the wheel. Additionally Tcl is confusing as is, for example there are two power commands/operators: pow and **. To decrement a value, you have to increment it (!) by a negative number (ie. there's a incr command, but no decr command). Re: Simple and Clean: Look at all the examples; the new operators will make Tcl cleaner by promoting space delimited syntax rather than having to include "set", "expr", "[", "]", "{" and "}" in statements. ---- [DKF]: We've been considering doing assignment operators. The problem was (IIRC) that it introduces a new syntactic class in our expression parser (approximately "lvalue") and that makes it tricky in a number of ways. Once that's done, doing a bunch of infix assignment operators is easy enough. You can do ''pi()'' for yourself right now. It's a one-line script! proc ::tcl::mathfunc::pi {} {expr {double(3.14159265)}} # I got the value from Google so it must be right! [Lars H]: Why not take advantage of Tcl's status as [dynamic language] to construct the procedure body automatically? proc ::tcl::mathfunc::pi {} [list return [expr acos(-1)]] In 8.5 this returns 3.141592653589793 for me, and all those digits are correct. [techmisc] 2008-07-02 Re: Lars H: Why not...: efficiency. Pi isn't going to change, hard coding it is OK. Unless someone wants to use Tcl's pi() to calculate the Nth digit... ''[Lars H]: Exactly, [pi] isn't going to change! DKF's version feeds the value through [double] every time it is called, mine just returns a cached value that was computed when the procedure was created. Though it occurs to me now that `interp alias {} tcl::mathfunc::pi {} return -level 0 [[expr acos(-1)]]` is probably better still.'' Re: DKF: Pi: Thanks for namespace tip, but I have no idea why it's not standard already... does Tcl have something against circles? ;-) Re: Syntactic Class: I don't know how Tcl's code is architectured, but since Tcl already has the very similar procedure [incr] built into the code, implementing the proposed operators should be (in theory) almost identical. Unless you're planning on implementing them as infix operators, but that would break Tcl's simple syntax. Not to mention potential rebellion by Tcl programmers against changing the existing grammar/syntax... But if infix operators are planned for Tcl then please allow user definable infix operators/procedures. Allowing only hardcoded infix operators wouldn't be very Tclish. [Lars H]: Unfortunately, the way the [expr] parser is currently implemented (a bunch of C functions that call each other recursively), they very much ''are'' hardcoded. '''[DGP]''' I guess you're looking at the Tcl 8.4 expr parser when you say that? Might want to have a look at the new one in Tcl 8.5. [Lars H]: Indeed — you got me — it was 8.4 when I last looked at that part of the source. The 8.5 implementation is quite different! Perhaps you can comment upon how flexible it is?... '''[DGP]''' The parser is not set up to support an extensible set of operators, or grammar or precedence rules for them, since that's what you seem to be looking for. Any proposal to do that would need careful review to check that whatever flexibility benefits are gained aren't more than paid for in performance losses. For now, the path for people who want to work with an extended set of operators is to define their own [[::my::expr]] command that does what they want. My response above was simply a reaction to the claim that the expr parser is a bunch of recursive C functions, which it no longer is. [DKF]: I wasn't interested in doing the most efficient version, I was just showing off that it could be done. There's no ''pi()'' right now because it's trivial to hard code. (It'd be better if [expr] understood π to be that constant directly, of course…) The syntactic class comment was ''exactly'' that we're looking at doing infix assignment operators for expressions. (Non-expression syntax will stay the same as now.) I don't know if we'll end up using '''=''' or ''':=''' (or something from the [unicode] zoo) for assignment; I'm not too worried over that detail for now. And we currently only allow a fixed set of operators with fixed semantics. Changing that is tricky, and has some really nasty consequences (see the [C++] standard library for many examples of misuse). OTOH, some functional languages ([SML] that I know of) allow the definition of extra operators without coming apart at the seams; mind you, most of their practitioners know better than to violate the type assumptions implicit in mathematical operations. [techmisc] Re: Syntactic Class: I see. I thought you meant introducing infix into statements eg. "my_var = 1" and I was arguing for "my_var my_proc 1" (as opposed to the current "my_proc my_var 1"). I think user defined operators in expr are of less importance because expr implies mathematics, not general purpose use. Unless you want to write a complex number operator, I guess. But I wouldn't worry too much about the consequences of giving power to Tcl programmers, they can already do anything thanks to the power of everything is a string. In the spirit of matching the functionality of expr with procedures in mathop (ie. "expr {1 + 1}" to "+ 1 1"), I'm hoping any new assignment operators in expr will have mathop equivalents, meaning a minimum functionality of: ====== expr {$s = 0} -> = s 0 expr {$s += 60} -> += s 60 expr {$x *= 2} -> *= x 2 expr {$s = 60 * 60 * 24} -> = s [expr {60 * 60 * 24}] expr {$y = $m * $x + $b} -> = y [expr {$m * $x + $b}] expr {$x = sin( pi() / 2 )} -> = x [expr {sin( pi() / 2 )}] ====== And if you consider the mathop assignment procedures to be of the same style as "if" and "while" then hopefully they can have an implied "expr" as their second argument: ====== = s {60 * 60 * 24} = y {$m * $x + $b} = x {sin( pi() / 2 )} ====== Not quite as brief as they could be, but far better than: ====== set x [expr {sin( pi() / 2 )}] ====== Hopefully increment and decrement operators will be available too: ====== for {= i 1} {$i <= 10} {++ i} {} for {= i 10} {$i >= 1} {-- i} {} ====== Unfortunately passing results of expressions to procedures will still be verbose: ====== myfunc x / y # Ruby myfunc( x / y ) # JavaScript, Python myfunc( $x / $y ); # Perl, PHP myfunc( x / y ); # C, C++, Java myfunc [expr {$x / $y}] # Tcl ====== I have no idea how to fix that without introducing new syntax (eg. backticks for expr): ====== myfunc `$x / $y` # Fantasy Tcl ====== Since backticks are shell features, and Tcl is shellish, this might be acceptable. If they were introduced, it would also allow the commands: ====== `$s = 60 * 60 * 24` `$y = $m * $x + $b` `$x = sin( pi() / 2 )` `$s += 60` `$x *= 2` `++$x` ====== Re: "=" vs ":=" vs other: I would bet most programmers would prefer "=" because it's become standard. A bonus is typing "=" is at least twice as fast as ":=" (you have to shift ";" to get ":" on English keyboards). It also leaves ":" free for other uses. And obviously ISO-8859-1 over Unicode, think of the vi(m) users! ---- [techmisc] 2008-07-02 Thanks to whoever added markup to the original message. I also fixed some bugs and added a Scale/Multiplication example alongside Addition. [DKF]: You're welcome. [techmisc] If it's possible to rename the page to "Math Syntax", that would be great. I didn't realize people would have to type "Tcl Math Syntax is Inferior to JavaScript/Python/Ruby/C/C++/Java/Perl/PHP" everytime they wanted to link here. ---- !!!!!! %| [Category Suggestions] |% !!!!!!