Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/expr?V=184
QUERY_STRINGV=184
CONTENT_TYPE
DOCUMENT_URI/revision/expr
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.71.190.87
REMOTE_PORT27540
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR34.230.68.214
HTTP_CF_RAY86bbe59eeba31744-IAD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTclaudebot
HTTP_CF_CONNECTING_IP34.230.68.214
HTTP_CDN_LOOPcloudflare
HTTP_CF_IPCOUNTRYUS

Body


Error

Unknow state transition: LINE -> END

-code

1

-level

0

-errorstack

INNER {returnImm {Unknow state transition: LINE -> END} {}} CALL {my render_wikit expr `'''\[http://www.tcl.tk/man/tcl/TclCmd/expr.htm%|%expr\]'''`,\ a\ \[TclCommands%|%built-in\]\ \[Tcl\]\ command,\ evaluates\ an\ expression.\n\n\n\n**\ See\ Also\ **\n\n\ \ \ \[A\ little\ math\ language\]:\ \ \ adds\ features\ &\ sugar\ to\ `expr`\n\n\ \ \ \[A\ real\ problem\]:\ \ \ \n\n\ \ \ \[Additional\ math\ functions\]:\ \ \ \n\n\ \ \ \[Arbitrary\ precision\ math\ procedures\]:\ \ \ \n\n\ \ \ \[Brace\ your\ expr-essions\]:\ \ \ \n\n\ \ \ \[compute\]:\ \ \ more\ sugar\ for\ `expr`\n\n\ \ \ \[Converting\ numbers\ from\ arbitrary\ bases\]:\ \ \ \n\n\ \ \ \[DebuggingExprCalls\]:\ \ \ \[rwm\]\ sometimes\ it\ is\ difficult\ to\ debug\ `expr`\ calls\ where\ the\ operands\ are\ variables.\ \[DebuggingExprCalls\]\ explains\ how\ to\ wrap\ expr\ to\ help\ with\ these\ cases.\n\n\ \ \ \[double\ substitution\]:\ \ \ \n\n\ \ \ `\[cmdSplit%|%exprlex\]`\ and\ `\[cmdSplit%|%funclex\]`:\ \ \ Split\ expressions\ and\ functions\ into\ their\ lexical\ components.\n\n\ \ \ \[gotcha\]:\ \ \ where\ `expr`\ figures\ prominently\n\n\ \ \ \[Tcl\ and\ octal\ numbers\]:\ \ \ The\ Octal\ Bug\n\n\ \ \ \[expr\ problems\ with\ int\]:\ \ \ historical\ (pre-8.5)\ information\ on\ the\ limits\ of\ number\ representation\ (both\ integer\ and\ float)\ inherited\ from\ C\n\n\ \ \ \[for\]:\ \ \ \n\n\ \ \ \[How\ can\ I\ do\ math\ in\ Tcl\]:\ \ \ \n\n\ \ \ \[if\]:\ \ \ \n\n\ \ \ \[Importing\ expr\ functions\]:\ \ \ use\ `expr`'s\ functions\ without\ explicitly\ calling\ that,\ see\ \[Importing\ expr\ functions\].\n\n\ \ \ \[infix\]:\ \ \ a\ package\ to\ facilitate\ writing\ sequences\ of\ mathematical\ formulae\ in\ the\ familiar\ infix\ form\n\n\ \ \ \[Math\ function\ help\]:\ \ \ \n\n\ \ \ \[Modeling\ COND\ with\ expr\]:\ \ \ Braced\ expressions\ can\ span\ several\ lines\n\n\ \ \ \[Numerical\ Analysis\ in\ Tcl\]:\ \ \ \n\n\ \ \ \[Sample\ Math\ Programs\]:\ \ \ extremely\ simple\ math\ examples\n\n\ \ \ \[Tcl\ help\]:\ \ \ \n\n\ \ \ \[http://tip.tcl.tk/123%|%TIP\ #123\]:\ \ \ Adding\ an\ Exponentiation\ Operator\ to\ `expr`\n\n\ \ \ \[http://tip.tcl.tk/174%|%TIP\ #174\]:\ \ \ \[Math\ Operators\ as\ Commands\]\n\n\ \ \ \[http://tip.tcl.tk/182%|%TIP\ #182\]:\ \ \ Add\ 'expr\ bool'\ Math\ Function\n\n\ \ \ \[http://tip.tcl.tk/201%|%TIP\ #201\]:\ \ \ Add\ 'in'\ Operator\ to\ expr\n\n\ \ \ \[http://tip.tcl.tk/232%|%TIP\ #201\]:\ \ \ Creating\ New\ Math\ Functions\ for\ `expr`\ (\[tcl::mathfunc\])\n\n\ \ \ \[http://tip.tcl.tk/237%|%TIP\ #237\]:\ \ \ Arbitrary-Precision\ Integers\ for\ Tcl\n\n\ \ \ \[while\]:\ \ \ \n\n\n\n\n**\ Documentation\ **\n\n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/expr.htm%|%officieal\ reference\]:\ \ \ \n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/expr.htm%|%man\ page\]:\ \ \ \n\ \ \ \[tcl::mathfunc%|%mathfunc\]:\ \ \ \n\n\ \ \ \[tcl::mathop%|%mathop\ man\ page\]:\ \ \ \n\n\ \ \ \[tcl_precision\]:\ \ \ \n\n\ \ \ \[http://www.tcl.tk/man/tcl/TclLib/GetInt.htm%|%Tcl_GetBoolean\ man\ page\]:\ \ \ \n\n\n\n**\ Synopsis\ **\n\n'''expr'''\ ''arg''\ ?''arg\ arg\ ...''?\n\n\n\n**\ Description\ **\n\n`expr`\ \[concat%|%concatentates\]\ its\ arguments,\ evaluates\ this\ result\ as\ a\ Tcl\ \n`expr`\ implements\ a\ mini\ language\ that\ has\ a\ syntax\ separate\ from\ \[Tcl\].\ \ It\ supports\ some\ of\ the\ same\ constructs\ as\ Tcl,\ such\ as\n\[Dodekalogue%|%variable\ substitution\],\ command\ substitution,\ and\ braces.\ \ It\nadds\ additional\ syntax\ for\ mathematical\ operators\ and\ functions,\ and\ unlike\nTcl,\ does\ not\ accept\ character\ strings\ that\ are\ not\ enclosed\ in\ double\ quotes\nor\ braces.\n`expr`\ implements\ a\ \[little\ language\]\ that\ has\ a\ syntax\ separate\ from\ \[Tcl\].\nThe\ `expr`\ conditions\ of\ commands\ such\ as\ `\[if\]`\ and\ `\[while\]`\ expect\nthe\ expression\ to\ evaluate\ to\ a\ boolean,\ i.e.,\ an\ integer\ or\ one\ of\ the\nfollowing\ string\ values:\nA\ value\ recognized\ as\ boolean\ by\ `\[string\ is\]\ boolean...`\ can\ be\ used\ directly,\n\ \ \ *\ true,\ on,\ yes\nThe\ operators\ permitted\ in\ Tcl\ expressions\ include\ most\ of\ the\ operators\n\ \ \ *\ false,\ off,\ no\nFunctions\ take\ the\ form,\nAny\ of\ these\ values\ may\ be\ abbreviated,\ and\ upper-case\ spellings\ are\ also\nacceptable.\ \ See\ the\n\[http://www.tcl.tk/man/tcl/TclLib/GetInt.htm%|%Tcl_GetBoolean\ man\ page\]\n\ \ \ \ :\ \ \ ''name''`(`''argument?'')\nBoolean\ values\ such\ as\ `true`\ need\ not\ be\ enclosed\ in\ double\ quotes.\n\ \ \ \ :\ \ \ ''name''`(`''argument''`,`''argument\ ...'')`\n`expr`\ interprets\ \"bare\"\ strings\ as\ function\ names,\ e.g.,\ `cos(\$x)`,\ or\ as\nboolean\ values\ where\ context\ permits,\ and\ will\ raise\ an\ error\ if\ a\ bare\ word\ is\nencountered\ where\ a\ literal\ string\ is\ expected.\ Additionally,\ some\ operators\ (`eq`,\ `ne`,\ `in`,\ and\ `ni`)\ resemble\ bare\ strings.\n\n======\n`expr`\ \[concat%|%concatentates\]\ its\ arguments,\ evaluates\ this\ result\ as\ a\ \[Tcl\]\nexpression,\ and\ returns\ the\ value.\ The\ operators\ permitted\ in\ Tcl\ expressions\ninclude\ most\ of\ the\ operators\ permitted\ in\ \[C\]\ expressions\ and\ a\ few\ additional\nones.\ \ The\ operators\ have\ the\ same\ meaning\ and\ precedence\ as\ the\ corresponding\nC\ operators.\ Expressions\ almost\ always\ yield\ numeric\ results\ (integer\ or\nfloating-point\ values).\ For\ example,\ the\ expression,\n\nset\ val1\ 8.2\nset\ val2\ 6\nexpr\ \{\$val1\ +\ \$val2\}\nexpr\ \$val1\ +\ \$val2\n\nResult:\nreturns\ `14.2`.\n======\nUsually,\ though,\ it's\ best\ to\ \[Brace\ your\ Expr-essions%|%brace\]\ the\ argument:\nIn\ most\ cases,\ it's\ best\ to\ \[Brace\ your\ Expr-essions%|%brace\]\ or\ otherwise\nexpr\ \{\$val1+\$val2\}\n======\n\nThis\ allows\ `expr`\ to\ do\ the\ interpretation,\ rather\ than\ having\ Tcl\ interpret\nAny\ argument\ that\ can\ be\ interpreted\ in\ some\ way,\ e.g.,\ variable\ or\ a\ command\nexpansion,\ should\ normally\ be\ enclosed\ in\ brackets.\ \ This\ allows\ the\n`expr`\ command\ to\ do\ the\ interpretation,\ rather\ than\ having\ the\ caller\ninterpret\ the\ arguments\ before\ handing\ them\ off\ to\ `expr`.\ \ See\ below\ for\nmore\ details.\n`expr`\ expressions\ differ\ from\ \[C\]\ expressions\ in\ the\ way\ that\ operands\ are\n`expr`essions\ differ\ from\ C\ expressions\ in\ the\ way\ that\ operands\ are\n(comparison)\ and\ lists\ (membership).\n\n\n\n**\ Operators\ **\n\nSince\ Tcl\ 8.5,\ many\ operators\ have\ command-equivalents\ in\ the\n'''::\[tcl::mathop\]'''\ \[namespace\].\n\nIn\ spite\ of\ the\ name\ '''mathop''',\ some\ of\ the\ operators\ are\ string-oriented,\ rather\nIn\ spite\ of\ the\ name\ '''mathop''',\ some\ of\ the\ operators\ are\ string,\ rather\n\nThe\ following\ is\ a\ chart\ of\ operators,\ in\ order\ of\ precedence\ (tightest-binding\nto\ least-tight\ associativity):\nto\ least-tight\ binding):\n&|\ \[-\]\ \[+\]\ \[~\]\ \[!\]\ |\ Unary\ operators\;\ specifically\ a\ negation\ operation,\ a\ non-negation\ operation,\ a\ bit-wise\ NOT\ operation\ (every\ bit\ in\ the\ input\ value\ gets\ replaced\ by\ its\ inverse)\ and\ a\ logical\ NOT\ operation\ (non-zero\ maps\ to\ zero,\ and\ zero\ maps\ to\ one).\ |&\n&|\ \[**\]\ |\ exponential.\ From\ Tcl\ 8.5\ on.\ |&\n&|\ \[+\]\ \[-\]\ |\ Addition\ and\ subtraction.\ |&\n&|\ \[<<\]\ \[>>\]\ |\ Left\ and\ right\ shift.\ \ Equivalent\ to\ multiplying\ or\ dividing\ by\ a\ suitable\ power\ of\ two,\ and\ then\ reducing\ the\ result\ to\ the\ range\ representable\ in\ an\ integer\ on\ the\ host\ platform.\ |&\n&|\ \[<\]\ \[>\]\ \[<=\]\ \[>=\]\ |\ Ordering\ relations:\ \ less\ than,\ greater\ than,\ less\ than\ or\ equal,\ greater\ than\ or\ equal.\ \ These\ operations\ work\ on\ strings\ as\ well\ as\ numbers,\ but\ where\ string\ comparison\ is\ intended,\ it\ is\ advisable\ to\ use\ the\ dedicated\ string\ comparison\ operators\ or\ \[string\ compare\]\ or\ \[string\ equal\]\ instead,\ \ as\ those\ are\ \ more\ predictable\ in\ the\ case\ of\ a\ string\ that\ looks\ like\ a\ number.\ \ For\ example,\ \[string\ equal\]\ considers\ \"6\"\ and\ \"06\"\ to\ be\ different\ strings,\ but\ the\ `expr`'\ operator\ `==`\ considers\ them\ to\ be\ equivalent\ numbers.|&\n&|\ \[==\]\ \[!=\]\ |\ Equality\ and\ inequality.\ \ \ These\ operations\ work\ on\ strings\ as\ well\ as\ numbers,\ but\ see\ the\ description\ equality\ operators\ for\ notes\ about\ string\ comparison.\ |&\n&|\ \[eq\]\ \[ne\]\ |\ Since\ Tcl\ 8.4,\ these\ are\ string-comparison\ operators.\ \"6\"\ and\ \"06\",\ as\ well\ as\ 1\ and\ 1.0,\ will\ compare\ unequal.\ |&\n&|\ \[in\]\ \[ni\]\ |\ checks\ for\ occurrence\ of\ an\ item\ in\ a\ list.\ New\ in\ Tcl\ 8.5.\ |&\n&|\ \[**\]\ |\ exponential.\ From\ Tcl\ 8.5\ on.\ |&\n&|\ \[&\]\ |\ Bit-wise\ AND.\ \ A\ bit\ is\ set\ in\ the\ result\ when\ the\ corresponding\ bit\ is\ set\ in\ both\ the\ arguments.\ |&\n&|\ \[^\]\ |\ Bit-wise\ exclusive\ OR.\ \ A\ bit\ is\ set\ in\ the\ result\ when\ the\ corresponding\ bit\ is\ set\ in\ ''precisely\ one''\ of\ the\ arguments.\ |&\n&|\ \[<<pipe>>\]\ |\ Bit-wise\ OR.\ \ \ A\ bit\ is\ set\ in\ the\ result\ when\ the\ corresponding\ bit\ is\ set\ in\ either\ of\ the\ arguments.\ |&\n&|\ \[&&\]\ |\ Logical\ AND.\ \ \ The\ result\ is\ `1`\ when\ both\ of\ the\ arguments\ true.\ and\ `0`\ otherwise.\ \ This\ operation\ is\ a\ ''short-circuiting''\ operation,\ and\ will\ only\ evaluate\ its\ second\ argument\ when\ the\ first\ argument\ is\ non-zero.\ \ This\ includes\ the\ expansion\ of\ Tcl\ commands\ in\ square\ brackets.\ \ Where\ Tcl\ seems\ not\ to\ be\ behaving\ as\ describe\ here,\ see\ \[double\ substitution\].\ |&\n&|\ \[<<pipe>><<pipe>>\]\ |\ Logical\ OR.\ \ The\ result\ is\ `0`\ when\ both\ of\ the\ arguments\ are\ false,\ and\ `1`\ otherwise.\ \ This\ operation\ is\ a\ ''short-circuiting''\ operation,\ and\ will\ only\ evaluate\ its\ second\ argument\ when\ the\ first\ argument\ is\ zero.\ \ Where\ Tcl\ seems\ not\ to\ be\ behaving\ as\ describe\ here,\ see\ \[double\ substitution\].\ |&\n&|\ x'''?'''y''':'''z\ |\ If-then-else,\ as\ in\ \[C\].\ `x`,\ `y`,\ and\ `z`\ are\ expressions.\ \ The\ result\ is\ `y`\ if\ `x`\ is\ true,\ and\ `z`\ otherwise.\ \ This\ operation\ is\ a\ ''short-circuiting''\ operation:\ \ If\ `x`\ is\ true,\ `z`\ will\ not\ be\ evaluated,\ and\ if\ `x`\ is\ false,\ `y`\ will\ not\ be\ evaluated.\ \ Where\ Tcl\ seems\ not\ to\ be\ behaving\ as\ describe\ here,\ see\ \[double\ substitution\].\ \ `\[if\]`\ performs\ just\ as\ well\ as\ this\ construct.\ \ The\ generated\ bytecode\ is\ identical.\ |&\n\n\n\n**\ Functions\ **\n\nSee\ the\ \[http://www.tcl.tk/man/tcl/TclCmd/mathfunc.htm%|%mathfunc\ man\ page\].\n\nThe\ following\ is\ a\ list\ of\ builtin\ functions:\n\n\ \ \ '''\[abs\]'''(x):\ \ \ Absolute\ value\ (negate\ if\ negative).\n\n\ \ \ '''\[acos\]'''(x):\ \ \ Inverse\ cosine\ (result\ in\ radians).\n\n\ \ \ '''\[asin\]'''(x):\ \ \ Inverse\ sine\ (result\ in\ radians).\n\n\ \ \ '''\[atan\]'''(x):\ \ \ Inverse\ tangent\ (result\ in\ radians).\n\n\ \ \ '''\[atan2\]'''(y,x):\ \ \ Inverse\ tangent.\ \ Can\ handle\ cases\ which\ plain\ `atan()`\ can't\ (due\ to\ division\ by\ zero)\ and\ has\ a\ larger\ output\ range\ (result\ in\ radians).\n\n\ \ \ '''\[bool\]'''(x):\ \ \ Accepts\ any\ valid\ boolean\ value\ and\ returns\ the\ corresponding\ boolean\ value\ `0`\ or\ `1`.\n\n\ \ \ '''\[ceil\]'''(x):\ \ \ Ceiling\ (defined\ over\ floating\ point\ numbers.)\ \ If\ the\ input\ value\ is\ not\ a\ whole\ number,\ return\ the\ next\ ''larger''\ whole\ number.\ '''Surprise''':\ The\ return\ value\ is\ a\ float,\ not\ an\ integer.\n\n\ \ \ '''\[cos\]'''(x):\ \ \ Cosine\ (input\ in\ radians).\n\n\ \ \ '''\[cosh\ function%|%cosh\]'''(x):\ \ \ Hyperbolic\ cosine.\n\n\ \ \ '''\[double\]'''(x):\ \ \ Convert\ number\ to\ floating\ point.\n\n\ \ \ '''\[entier\]'''(x):\ \ \ Like\ `int(x)`,\ but\ there\ is\ no\ limit\ to\ the\ input\ or\ output\ value.\n\n\ \ \ '''\[exp\]'''(x):\ \ \ Exponential\ function.\ \ Returns\ ''e''\ to\ the\ power\ of\ `x`,\ where\ ''e''\ is\ the\ base\ of\ natural\ logarithms.\n\ \ \ '''\[exp\]'''(x):\ \ \ Exponential\ function.\ \ Returns\ e\ to\ the\ power\ or\ `x`,\ where\ e\ is\ the\ base\ of\ natural\ logarithms.\n\ \ \ '''\[floor\]'''(x):\ \ \ Floor\ (defined\ over\ floating-point\ numbers.)\ \ If\ the\ input\ value\ is\ not\ a\ whole\ number,\ return\ the\ next\ ''smaller''\ whole\ number\ as\ a\ floating-point\ number.\n\n\ \ \ '''\[fmod\]'''(x,\ y):\ \ \ Floating-point\ remainder\ of\ x\ divided\ by\ y.\n\n\ \ \ '''\[hypot\]'''(x,y):\ \ \ Hypotenuse\ calculator.\ \ Assumes\ boring\ old\ Euclidean\ geometry.\ \ If\ the\ projection\ of\ a\ straight\ line\ segment\ onto\ the\ X\ axis\ is\ `x`\ units\ long,\ and\ the\ projection\ of\ that\ line\ segment\ onto\ the\ Y\ axis\ is\ `y`\ units\ long,\ then\ the\ line\ segment\ is\ `hypot(x,y)`\ units\ long.\ Equivalent\ to\ `sqrt(x*x+y*y)`.\n\n\ \ \ '''\[int\]'''(x):\ \ \ Convert\ number\ to\ integer\ by\ truncation.\ \ Limited\ by\ the\ size\ of\ long\ in\ \[C\].\n\n\ \ \ '''\[isqrt\]'''(x):\ \ \ Compute\ the\ integer\ part\ of\ the\ square\ root\ of\ `x`.\n\n\ \ \ '''\[log\]'''(x):\ \ \ Natural\ logarithm.\n\n\ \ \ '''\[log10\]'''(x):\ \ \ Logarithm\ with\ respect\ to\ base\ 10.\n\n\ \ \ '''\[max\]'''(x,...):\ \ \ The\ argument\ with\ the\ greatest\ value.\n\ \ \ '''\[max\]'''(x,...):\ \ \ Return\ the\ one\ argument\ with\ the\ greatest\ value.\n\ \ \ '''\[min\]'''(x,...):\ \ \ The\ argument\ with\ the\ least\ value.\n\ \ \ '''\[min\]'''(x,...):\ \ \ Return\ the\ one\ argument\ with\ the\ least\ value.\n\ \ \ '''\[pow\]'''(x,y):\ \ \ Power\ function.\ \ `x`\ to\ the\ power\ of\ `y`.\n\n\ \ \ '''\[rand\]'''():\ \ \ Random\ number.\ \ Uses\ uniform\ distribution\ over\ the\ range\ \[0,1).\ \ ''This\ RNG\ is\ not\ suitable\ for\ cryptography.''\n\n\ \ \ '''\[round\]'''(x):\ \ \ Round\ to\ nearest\ whole\ number.\ \ ''Not\ suitable\ for\ financial\ rounding.''\n\n\ \ \ '''\[sin\]'''(x):\ \ \ Sine\ (input\ in\ radians).\n\n\ \ \ '''\[sinh\]'''(x):\ \ \ Hyperbolic\ sine.\n\n\ \ \ '''\[sqrt\]'''(x):\ \ \ Square\ root\ (well,\ the\ positive\ square\ root\ only.\ \ And\ Tcl\ doesn't\ do\ complex\ math,\ so\ the\ input\ had\ better\ be\ positive).\n\n\ \ \ '''\[srand\]'''(x):\ \ \ Seeds\ the\ random\ number\ generator\ with\ the\ given\ value.\ \ Each\ interpreter\ has\ its\ own\ random\ number\ generator,\ which\ starts\ out\ seeded\ with\ the\ current\ time.\n\n\ \ \ '''\[tan\]'''(x):\ \ \ Tangent\ (input\ in\ radians.)\n\n\ \ \ '''\[tanh\]'''(x):\ \ \ Hyperbolic\ tangent.kjh\n\n\ \ \ '''\[wide\]'''(x):\ \ \ Take\ any\ numeric\ value,\ and\ return\ the\ low\ order\ 64\ bits\ of\ the\ integer\ value\ of\ the\ argument\n\n\n\n**\ Mathematical\ Expressions\ **\n\n\nSimple\ addition:\n\n======\nset\ a\ \[expr\ \{1\ +\ 2\}\]\n======\n\nmathematical\ functions\n\n======\nset\ a\ \[expr\ \{sqrt(4)\}\]\n======\n\n\[martin\ Lemburg\]:\ The\ following\ returns\ `1`\ because\ `\"\ 2\ \"`\ will\ be\ interpreted\nas\ `2`:\nas\ to\ `2`:\n======\nset\ a\ \[expr\ \{\"\ 2\ \"\ ==\ \[string\ trim\ \"\ 2\ \"\]\}\]\n======\n\nTo\ ensure\ that\ expression\ evaluates\ to\ a\ floating\ point\ number,\ use\ `double()`\nor\ `floor()`:\n\n======\nset\ a\ 1\nset\ b\ 2\nexpr\ \{double(\$a)/\$b\}\n======\n\nor,\ to\ get\ an\ integer:\n\n======\nexpr\ \{entier(\$a/\$b)\}\n======\n\n`int()`\ would\ also\ have\ worked,\ but\ `entier()`\ is\ more\ general\n\n\n**\ Order\ of\ Precedence\ **\n\nThe\ following\ returns\ returns\ 4,\ rather\ than\ -4\ as\ some\ might\ expect:\n\n======\nset\ a\ \[expr\ \{-2**2\}\]\n======\n\nThe\ following\ returns\ `1`\ because\ `2==2`\ is\ evaluated\ first:\nreturns\ `1`\ because\ `2==2`\ is\ evaluated\ first\n======\nset\ a\ \[expr\ \{5&2==2\}\]\n======\n\n\[AMG\]:\ The\ order\ of\ bitwise\ operations\ (`|`,\ `&`,\ and\ `^`)\ may\ seem\ totally\ bogus,\ but\ it's\ inherited\ from\ \[C\],\ which\ in\ turn\ inherited\ it\ from\ an\ early\ prototype\ version\ of\ C\ which\ lacked\ separate\ logical\ operators\ (`&&`\ and\ `||`)\ \[http://cm.bell-labs.com/who/dmr/chist.html\].\ I\ wouldn't\ cry\ if\ a\ new\ language\ (not\ Tcl)\ decided\ to\ break\ compatibility\ with\ C\ in\ this\ respect.\n**\ Composing\ Expressions\ **\n\n`expr`\ tries\ to\ interpret\ operands\ as\ numeric\ values,\ but\ doesn't\ parse\ \n`expr`\ tries\ to\ interpret\ operands\ as\ numeric\ values,\ but\ it\ does\ not\ try\nto\ interpret\ variable\ values\ as\ complete\ numeric\ expressons,\ so\ a\ value\ \"2*3\"\nwill\ be\ interpreted\ as\ a\ string:\n======\nset\ y\ 2*3\;\ expr\ \{\$y\}\ \ \ \;#\ ==>\ 2*3\nset\ y\ 2*3\;\ expr\ \{\$y+2\}\ \;#\ ==>\ can't\ use\ non-numeric\ string\ as\ operand\ of\ \"+\"\n======\n\nTo\ pass\ a\ complete\ expression\ stored\ in\ a\ variable,\ omit\ the\ braces\ so\ that\ Tcl\nTo\ pass\ a\ complete\ expression\ stored\ in\ a\ variable,\ take\ advantage\ of\ \[double\ substitution\]\ by\ omitting\ braces:\n======\nset\ y\ 2*3\;\ expr\ \$y\ \;#\ \ ==>\ 6\ \nset\ y\ 2*3\;\ puts\ \[expr\ \$y+2\]\ \;#\ ==>\ 8\n======\n\nBut\ be\ careful\ not\ to\ introduce\ an\ \[injection\ attack\]\ vulnerability.\ \ See\n\[double\ substitution\].\n\n\n\n**\ Literal\ String\ Operands\ **\n\n`expr`\ implements\ a\ little\ language\ distinct\ from\ the\ language\ described\ in\ \[dodekalogue%|%the\ rules\ of\ Tcl\].\ \ One\n`expr`\ implements\ a\ little\ language\ distinct\ from\ standard\ Tcl.\ \ One\n\n======none\n%\ \ if\ \{joe\ eq\ mike\}\ \{puts\ wow\}\nsyntax\ error\ in\ expression\ \"joe\ eq\ mike\":\ variable\ references\ require\ preceding\ \$\n%\ \ if\ \{\"joe\"\ eq\ \"mike\"\}\ \{puts\ wow\}\n%\ \ if\ \{\{joe\}\ eq\ \{mike\}\}\ \{puts\ wow\}\n======\n\nTo\ insert\ a\ literal\ value\ when\ templating\ an\ expression,\ use\ an\ \[identity\nIf\ you\ prefer\ consistency,\ then\ throughout\ your\ Tcl\ program,\ always\ quote\ values\ you\ consider\ to\ be\ \"strings\".\ (\[AMG\]:\ This\ is\ a\ totally\ arbitrary\ and\ stylistic\ distinction\ because\ \[everything\ is\ a\ string\].)\ Note\ that\ at\ some\ point\ `expr`\ may\ grow\ the\ feature\ of\ accepting\ bareword\ strings.\ (\[AMG\]:\ Or\ it\ might\ choose\ to\ interpret\ barewords\ as\ variable\ substitutions.)\n\nIf\ the\ return\ value\ of\ `expr`\ is\ numeric,\ it\ is\ transformed\ into\ a\ canonical\nIf\ the\ value\ of\ an\ `expr`\ is\ numeric,\ it\ will\ transformed\ into\ a\ canonical\n\n======\nset\ val\ 0x10\nputs\ \$val\ \;#\ 0x10\nset\ val\ \[expr\ \{\$val\}\]\nputs\ \$val\ \;#\ 16\n======\n\n======\nputs\ \[expr\ \{\[join\ \{0\ x\ 1\ 0\}\ \{\}\]\}\]\ \;#\ 16\n======\n\n\nIn\ other\ words,\ `expr`\ may\ mutate\ strings\ that\ can\ be\ interpreted\ as\nnumbers,\ which\ is\ a\ potential\ \[gotcha\]\ when\ using\ string\ functionality\nnumbers,\ which\ is\ a\ potential\ gotcha\ for\ the\ programmer\ using\ string\ functions\ninterpretation.\n\n\n\n**\ The\ Octal\ Bug\ **\n**\ \[Tcl\ and\ Octal\ Numbers%|%The\ Octal\ Bug\]\ **\nSee\ \[Tcl\ and\ Octal\ Numbers\]\ for\ details.\n\n\[rjm\]:\ Why\ does\ `expr`\ return\ integers\ with\ leading\ zeroes\ as\ hex?,\ e.g.\n\n======\nexpr\ 0100\ \;#\ ->\ 64\n======\n\n\[AMG\]:\ The\ leading\ zero\ makes\ 0100\ octal.\ \ The\ 1\ is\ in\ the\ 64's\ place,\ hence\nthe\ result\ is\ 64\ in\ decimal.\ \ That's\ not\ hexadecimal.\ \ `expr`\ always\nreturns\ a\ decimal\ value\;\ you\ have\ to\ use\ `\[format\]`\ if\ you\ want\ it\ in\ some\nother\ base.\n\n\[RJM\]:\ I\ came\ around\ this\ as\ I\ was\ going\ to\ do\ calculus\ on\ a\ four-digit\nformatted\ number\ in\ an\ entry\ field.\ I\ had\ to\ apply\ `scan\ \$var\ %d`\ to\ get\ rid\nformatted\ number\ in\ an\ entry\ field.\ I\ had\ to\ apply\ ''scan\ \$var\ %d''\ to\ get\ rid\nlanguage...\n\n\n`expr`\ uses\ floating\ point\ arithmetic,\ so\ strings\ representing\ decimal\nfractions\ that\ don't\ have\ a\ precise\ floating-point\ representation\ will\ be\ given\nto\ a\ close-enough\ representation.\ \ In\ the\ following\ example,\ `36.37`\ gets\ a\nto\ a\ close-enough\ representation.\ \ In\ the\ following\ example,\ \"36.37\"\ gets\ a\n\n======\nexpr\ \{int(36.37*100)\}\n======\n\nIf\ that\ value\ is\ subsequently\ used\ as\ a\ string,\ it\ becomes\ necessary\ to\ somehow\nconvert\ it.\ \ Over\ the\ years,\ the\ default\ string\ conversion\ has\ varied.\ \ For\ Tcl\nversion\ 8.5.13,\ it\ looks\ like\n\n======none\n3636.9999999999995\n======\n\n\[RS\]\ points\ out\ that\ version\ 8.4.9\ provided\ the\ following\ results,\ and\ that\nthat\ braced\ or\ not,\ `expr`\ returns\ the\ same\ (string\ rep\ of)\ double\ as\ well\nas\ integer,\ so\ the\ issue\ of\ bracing\ one's\ expressions\ is\ not\ relevant\ to\ the\nissue\ of\ floating-point\ to\ string\ conversion.\n\n======none\n%\ expr\ 36.37*100\n3637.0\ \;#--\ good\ enough...\n%\ expr\ \{36.37*100\}\n3637.0\ \;#--\ the\ same\n%\ expr\ \{int(36.37*100)\}\n3636\ \ \ \;#--\ Hmm\n%\ expr\ int(36.37*100)\n3636\ \ \ \;#--\ the\ same\n%\ info\ pa\n8.4.9\n======\n\nOne\ way\ to\ get\ `3637`\ would\ be\ to\ use\ `round()`:\nOne\ way\ to\ get\ \"3637\"\ would\ be\ to\ use\ `round()`:\n======\nexpr\ \{round(36.37*100)\}\n======\n\n`\[format\]`\ can\ also\ be\ useful,\ but\ the\ main\ point\ is\ to\ remain\naware\ of\ the\ context\ and\ decide\ if\ and\ how\ to\ use\ floating-point\ operations.\n\n\[LV\]:\ \ My\ response\ on\ \[comp.lang.tcl\]\ was\ that\ I\ thought\ it\ was\ a\ shame\nthat\ `expr`\ (or\ perhaps\ it\ is\ Tcl)\ didn't\ use\ the\ same\ mechanism\ for\nboth\ calculations\ of\ 36.37\ *\ 100\ \;\ that\ way,\ the\ results\ would\ at\ least\nbe\ consistent.\ \ Even\ if\ they\ were\ consistently\ '''wrong''',\ one\ would\nbe\ able\ to\ at\ least\ to\ live\ within\ the\ ''law\ of\ least\ surprise''.\nAs\ it\ is,\ until\ one\ experiments,\ one\ won't\ know\ which\ way\ that\ Tcl\nis\ going\ to\ ''round''\ results.\n\n\[EPSJ\]:\ \ This\ may\ be\ a\ side\ effect\ of\ the\ IEEE\ floating\ point\ standard.\ This\ is\ndone\ in\ hardware\ to\ guarantee\ the\ convergence\ in\ the\ case\ of\ a\ series\ of\ math\nalgorithms.\ The\ rule\ is\ that\ the\ mantissa\ of\ a\ floating\ point\ number\ must\ be\nrounded\ to\ the\ nearest\ even\ number.\ As\ 36.37\ cannot\ be\ represented\ exactly\ in\nfloat\ point\ it\ ends\ up\ being\ a\ small\ fraction\ below\ the\ intended\ number.\ On\ the\nother\ side\ 36.38\ moves\ on\ the\ other\ direction.\ Look\ the\ following\ result:\n\n======none\n()\ 60\ %\ expr\ int(36.380*100)\n3638\n()\ 61\ %\ expr\ int(36.370*100)\n3636\n======\n\nx86\ floating\ point\ hardware\ allows\ this\ to\ be\ configurable\ to\ nearest\ even,\nnearest\ odd,\ and\ a\ few\ more\ options.\ But\ usually\ nearest\ even\ is\ the\ default.\nThe\ result\ may\ seem\ inconsistent,\ but\ it\ is\ intentional.\n\n\n**\ pow()\ vs\ **\n**\ pow()\ vs\ **\ **\n\[LES\]\ 2005-07-23:\n\n======none\n%\ expr\ pow(5,6)\n15625.0\n\n%\ expr\ 5**6\n15625\n======\n\nTwo\ syntaxes,\ two\ slightly\ different\ results.\ Is\ that\ intentional?\n\n\[RS\]:\ Yes.\ \ While\ `pow()`\ always\ goes\ for\ double\ logarithms,\ `**`\ tries\ to\ do\ninteger\ exponentiation\ where\ possible.\n\n\n**\ Precision\ **\n\n\[davou\]:\ What\ is\ the\ precision\ of\ functions\ in\ `expr`,\ and\ how\ can\ it\ be\nexpanded\ upon?\n\n\[Lars\ H\]:\ That's\ generally\ determined\ by\ the\ \[C\]\ library\ functions\ that\nimplement\ them.\ It\ depends\ on\ where\ (and\ against\ what)\ Tcl\ is\ compiled.\ \ For\nreal\ numbers,\ that\ means\ '''double'''s,\ which\ are\ floating-point\ numbers\ of\ntypically\ about\ 17\ decimal\ digits\ precision\ (but\ how\ many\ of\ these\ are\ correct\nvaries\ between\ functions\ and\ platforms).\ For\ integers\ Tcl\ has\ traditionally\nused\ '''long'''s,\ which\ in\ most\ cases\ means\ 32-bit\ two's\ complement\ integers\n(`\$tcl_platform(wordSize)`\ tells\ you\ the\ actual\ number\ of\ bytes),\ but\ as\ of\ Tcl\n8.5,\ it\ supports\ (almost)\ arbitrarily\ large\ integers\ (\[googol\ magnitude\]\ is\ no\nproblem\ anymore,\ whereas\ googolplex\ magnitude\ wouldn't\ fit\ in\ the\ computer\nmemory\ anyway).\ As\ for\ extending\ what\ the\ core\ provides,\ \[tcllib\]\ provides\n\[math::bignum\]\ and\ \[math::bigfloat\].\n\n\n**\ \[Nan\]\ and\ \[Inf\]\ **\n\n\nAt\ least\ as\ of\ Tcl\ 8.5,\ \[NaN\]\ and\ \[Inf\]\ are\ potential\ values\ returning\ from\n`expr`.\n\n\[Philip\ Smolen\]\ I've\ never\ seen\ expr\ return\ NaN.\ \ I\ wish\ it\ would!\n\n======\n\[phil@harvey\ ~\]\$\ tclsh8.6\ \n%\ expr\ sqrt(-1)\ndomain\ error:\ argument\ not\ in\ valid\ range\n%\ ::tcl::mathfunc::sqrt\ -1\n-NaN\n%\ info\ patchlevel\n8.6.4\n%\ expr\ \{Inf+1\}\nInf\n%\ \n======\n\n\n======\n\[phil@becca\ ~\]\$\ tclsh8.5\ \n%\ expr\ sqrt(-1)\ndomain\ error:\ argument\ not\ in\ valid\ range\n%\ ::tcl::mathfunc::sqrt\ -1\n-NaN\n%\ info\ patchlevel\n8.5.14\n%\ expr\ \{Inf+1\}\nInf\n%\ \n======\n\n**\ Interactions\ with\ \[locale\]\ **\n\n**\ Interactions\ with\ `\[locale\]`\ **\nparsing\ of\ decimals\ in\ `expr`\ may\ be\ hampered\ by\ \[locale\]\ -\ you\ might\ get\n\n\n\n\n`expr`\ concatenates\ its\ arguments\ into\ an\ expression.\ \ Consider\ the\ following\n`expr`\ resolves\ variables\ in\ the\ context\ of\ its\ caller,\ and\ each\ variable\nvalue\ becomes\ exactly\ one\ operand\ in\ the\ expression.\ \ Consider\ the\ following:\n======\nexpr\ 5\ >\ \{\}\ \;#\ ->\ missing\ operand\ at\ _@_\nset\ color2\ green\n\nexpr\ \{\$color1\}\ eq\ \{\$color2\}\ \;#\ 1\n\nConcatenated,\ the\ arguments\ form\ the\ script,\ `green\ eq\ green`,\ in\ which\ the\ two\nBut\ if\ the\ arguments\ are\ not\ bracketed,\ it\ is\ a\ syntax\ error:\nAnother\ example\ illustrating\ the\ same\ point:\n======\n#wrong\nexpr\ \$color1\ eq\ \$color2\n======\n\n======none\ninvalid\ bareword\ \"green\"\nin\ expression\ \"green\ eq\ green\"\;\nshould\ be\ \"\$green\"\ or\ \"\{green\}\"\ or\ \"green(...)\"\ or\ ...\n======\n\nThis\ is\ because\ in\ `expr`\ syntax,\ strings\ should\ be\ quoted\ or\ bracketed\n\n\n======\nset\ a\ abc\nset\ a\ \"abc\"\nexpr\ \$a\ in\ \$b\n#\ invalid\ bareword\ \"abc\"\n#\ in\ expression\ \"abc\ in\ 123\ abcd\ xyz\ lmnop\"\;\n#\ should\ be\ \"\$abc\"\ or\ \"\{abc\}\"\ or\ \"abc(...)\"\ or\ ...\n\nexpr\ \{\$a\ in\ \$b\}\ \;#->\ 0\nexpr\ \{\$a\ in\ \$b\}\n#\ 0\nexpr\ \{\$a\ ni\ \$b\}\ \;#->\ 1\nexpr\ \{\$a\ ni\ \$b\}\n#\ 1\n\n======\n%\ expr\ \$a\ eq\ \"foo\"\ ?\ true\ :\ false\n%\ expr\ \$a\ ==\ \"foo\"\ ?\ true\ :\ false\n%\ expr\ \{\$a\ eq\ \"foo\"\ ?\ true\ :\ false\}\n%\ expr\ \{\$a\ ==\ \"foo\"\ ?\ true\ :\ false\}\n======\n\n\n\nWhen\ exactly\ one\ unconcatenated\ value\ is\ passed\ to\ `expr`,\ the\ argument\ can\ be\n`expr`\ is\ much\ more\ performant\ when\ it\ has\ exactly\ one\ argument.\ \ The\nargument\ must\ either\ be\ brace-quoted\ or\ be\ a\ single\ variable\ substitution,\nsince\ this\ allows\ byte-compilation.\n\n\[AMG\]:\ More\ precisely,\ the\ argument\ must\ not\ contain\ multiple\ substitutions\ or\nbe\ the\ concatenation\ of\ substitutions\ and\ literal\ text.\ \ The\ goal\ is\ for\ there\nIf\ `expr`\ has\ to\ concatenate\ its\ arguments\ (i.e.\ it\ is\ passed\ more\ than\ one\nargument),\ or\ if\ \[Tcl\]\ has\ to\ concatenate\ the\ results\ of\ multiple\ substitutions\nand\ literal\ substrings,\ then\ the\ math\ expression\ will\ be\ in\ a\ temporary\ Tcl_Obj\nwhich\ must\ be\ regenerated\ every\ time\ `expr`\ is\ called.\n\n'''Fast:'''\n\n======\nexpr\ \{2\ +\ 2\}\ \ \ \ \ \ \ \ \ \;\ #\ Preferred\nexpr\ 2+2\ \ \ \ \ \ \ \ \ \ \ \ \ \;\ #\ Valid\ but\ lazy\ (1)\nexpr\ \"2\ +\ 2\"\ \ \ \ \ \ \ \ \ \;\ #\ Valid\ but\ not\ preferred\ (2)\nexpr\ 2\\\ +\\\ 2\ \ \ \ \ \ \ \ \ \;\ #\ Valid\ but\ ugly\ (3)\nexpr\ \$expression\ \ \ \ \ \;\ #\ Valid\nexpr\ \[expression\]\ \ \ \ \;\ #\ Valid\n======\n\n(1)\ This\ style\ is\ easy\ to\ type\ and\ is\ fine\ for\ interactive\ use,\ but\ you\ will\ lose\ performance\ (and\ correctness\ and\ security)\ if\ you\ use\ this\ notation\ in\ combination\ with\ variable\ and\ script\ substitutions.\n\n(2)\ Same\ problems\ as\ (1).\ \ Use\ braces\ instead.\n\n(3)\ Same\ problems\ as\ (1),\ plus\ you\ might\ forget\ a\ backslash\ before\ a\ space,\ thereby\ forcing\ `expr`\ to\ concatenate\ its\ arguments.\n\n'''Slow:'''\n\n======\nexpr\ 2\ +\ 2\ \ \ \ \ \ \ \ \ \ \ \;\ #\ Slow\ since\ \[expr\]\ must\ concatenate\ its\ arguments\nexpr\ 2\ +\ \$x\ \ \ \ \ \ \ \ \ \ \;\ #\ Slow\ since\ \[expr\]\ must\ concatenate\ its\ arguments,\ also\ unsafe\nexpr\ 2+\$x\ \ \ \ \ \ \ \ \ \ \ \ \;\ #\ Slow\ since\ Tcl\ must\ concatenate\ to\ determine\ argument,\ also\ unsafe\nexpr\ \"2\ +\ \$x\"\ \ \ \ \ \ \ \ \;\ #\ Slow\ since\ Tcl\ must\ concatenate\ to\ determine\ argument,\ also\ unsafe\n======\n\n\n\n\n\[AMG\]:\ The\ security\ problems\ of\ unbraced\ `expr`essions\ are\ very\ similar\ to\n\[SQL\]\ \[injection\ attack%|%injection\ attacks\].\ \ Notice\ how\ \[sqlite\]'s\ \[Tcl\]\ binding\ does\ its\ own\n\[SQL\]\ injection\ attacks.\ \ Notice\ how\ \[sqlite\]'s\ \[Tcl\]\ binding\ does\ its\ own\nthis\ problem\ as\ well\ because\ the\ default\ is\ to\ apply\ multiple\ passes\ of\ninterpretation.\n\nSee\ also\ \[double\ substitution\].\nSee\ also\ \[double\ substitution\]\n\n\n\n\[AMG\]:\ The\ above\ speed\ and\ security\ concerns\ also\ apply\ to\ `\[if\]`,\n`\[for\]`,\ and\ `\[while\]`\ since\ they\ share\ the\ expression\ engine\ with\n`expr`.\n\nAdditionally,\ `\[for\]`\ and\ `\[while\]`\ really\ do\ need\ their\ expressions\ to\nbe\ braced.\ \ In\ order\ for\ the\ loop\ to\ execute\ a\ nonzero\ but\ finite\ number\ of\ntimes,\ the\ expression's\ value\ must\ not\ be\ constant\;\ but\ if\ they're\ not\ braced,\ntheir\ value\ is\ determined\ before\ the\ loop\ can\ begin.\n\nThe\ exception\ is\ when\ the\ ''expression''\ (as\ opposed\ to\ value)\ is\ contained\ in\na\ variable,\ in\ which\ case\ it\ must\ not\ be\ brace-quoted,\ or\ else\ the\ command\nwould\ try\ to\ treat\ the\ expression\ as\ a\ (string)\ value\ and\ almost\ certainly\ fail\nto\ convert\ it\ to\ a\ boolean\ value.\n\n\[DKF\]:\ But\ even\ then,\ for\ `if`,\ `for`\ and\ `while`\ you\ must\ still\ brace\ the\ expression\ to\ avoid\ being\ stuck\ in\ the\ compilation\ slow\ lane.\ Putting\ an\ `expr`\ inside\ can\ help:\n======\nset\ ex\ \{\$f\ >\ 42\}\nwhile\ \{\[expr\ \$ex\]\}\ \{\n\ \ \ \ puts\ \"This\ is\ the\ body:\ f\ is\ now\ \[incr\ f\ -1\]\"\n\}\n======\n\n----\n\nConsider\ what\ would\ happen\ if\ this\ script\ were\ actually\ working\ with\ user\ninput:\n\n======\n#DON'T\ EXECUTE\ THIS\ SCRIPT!!!\nset\ x\ \{\[exec\ format\ C:\\\\\]\}\nset\ j\ \{\[puts\ Sucker!\]\}\n#C:\\\ get\ formatted\ in\ the\ next\ command\nset\ k\ \[expr\ \$x\ /\ \$j.\]\n======\n\nOn\ the\ other\ hand,\n\n======\nset\ k\ \[expr\ \{\ \$x\ /\ double(\$j)\ \}\]\n======\n\ngives\ a\ much\ more\ reasonable\ result:\n\n======none\nargument\ to\ math\ function\ didn't\ have\ numeric\ value\n\ \ \ while\ executing\n\"expr\ \{\ \$x\ /\ double(\$y)\ \}\"\n\ \ \ invoked\ from\ within\n\"set\ k\ \[expr\ \{\ \$x\ /\ double(\$y)\ \}\]\n\"\n\ \ \ \ (file\ \"foo.tcl\"\ line\ 3)\n\n======\n\n\n\n\nUnless\ you\ know\ exactly\ what\ you\ are\ doing,\ unbraced\ expressions\ are\ not\nrecommended.\ \ Nevertheles...\n\nWith\ unbraced\ expressions,\ `.`\ (`\\x2e`)\ can\ be\ appended\ to\ a\ variable\ to\ get\ `expr`\nWith\ unbraced\ expressions,\ a\ \".\"\ can\ be\ appended\ to\ a\ variable\ to\ get\ `expr`\n\n======\nset\ x\ 1\;\ set\ j\ 2\n\n#\ works\ (but\ don't\ do\ this)\nexpr\ \$x/\$j.\n\n#an\ accepted\ way\ to\ do\ it\nexpr\ \{double(\$x)/\$j\}\n\n#\ error:\ syntax\ error\ in\ expression\ \"\$x/\$j.\"\ \ (expr\ parser)\nexpr\ \{\$x/\$j.\}\n======\n\nIt's\ faster,\ too:\n\n======\nset\ script1\ \{\n\ \ \ set\ x\ 1\n\ \ \ set\ j\ 2\n\ \ \ set\ k\ \[expr\ \$x\ /\ \$j.\]\n\}\nset\ script2\ \{\n\ \ \ set\ x\ 1\n\ \ \ set\ j\ 2\n\ \ \ set\ k\ \[expr\ \{\ \$x\ /\ double(\$j)\ \}\]\n\}\nforeach\ v\ \{script1\ script2\}\ \{\nforeach\ v\ \{\ script1\ script2\ \}\ \{\n\}\n\n#script1:\ 38\ microseconds\ per\ iteration\n#script2:\ 9\ microseconds\ per\ iteration\n\n#\[pyk\]\ 2012-11-28:\ what\ a\ difference\ a\ few\ years\ makes\ (an\ \"old\"\ 3.06Ghz\ Intel\ Core\ 2\ Duo):\n#script1:\ 4.4767364\ microseconds\ per\ iteration\n#script2:\ 0.7374299\ microseconds\ per\ iteration\n======\n\n----\n\n\[RS\]:\ This\ was\ just\ to\ demonstrate\ the\ differences\ between\ the\ regular\ Tcl\nparser\ and\ the\ parser\ for\ `expr`',\ not\ recommended\ practice.\ Another\ example\ is\nsubstitution\ of\ operators:\n\n======\nset\ op\ +\nexpr\ 4\ \$op\ 5\n9\nexpr\ \{4\ \$op\ 5\}\nsyntax\ error\ in\ expression\ \"4\ \$op\ 5\"\n======\n\nSee\ the\ `\[for\]`\ page\ on\ a\ case\ where\ that\ helped.\n\n**\ Bytecode\ compilation\ and\ performance\ **\n\n\[AMG\]:\ When\ expr's\ argument\ is\ properly\ braced,\ the\ expression\ can\ be\ bytecoded\ for\ significant\ performance\ gains.\ However,\ the\ performance\ is\ not\ always\ quite\ as\ good\ as\ one\ would\ hope.\ Use\ \[tcl::unsupported::disassemble\]\ to\ see\ this\ in\ action:\n\n======none\n%\ tcl::unsupported::disassemble\ script\ \{expr\ \{4\ /\ 3.\ *\ acos(-1)\ *\ \$r\ **\ 3\}\}\nByteCode\ 0x00000000025FADB0,\ refCt\ 1,\ epoch\ 16,\ interp\ 0x00000000026365B0\ (epoch\ 16)\n\ \ Source\ \"expr\ \{4\ /\ 3.\ *\ acos(-1)\ *\ \$r\ **\ 3\}\"\n\ \ Cmds\ 1,\ src\ 34,\ inst\ 17,\ litObjs\ 5,\ aux\ 0,\ stkDepth\ 3,\ code/src\ 0.00\n\ \ Commands\ 1:\n\ \ \ \ \ \ 1:\ pc\ 0-15,\ src\ 0-33\n\ \ Command\ 1:\ \"expr\ \{4\ /\ 3.\ *\ acos(-1)\ *\ \$r\ **\ 3\}\"\n\ \ \ \ (0)\ push1\ 0\ \ \ \ \ \ \ \ \ #\ \"1.3333333333333333\"\n\ \ \ \ (2)\ push1\ 1\ \ \ \ \ \ \ \ \ #\ \"tcl::mathfunc::acos\"\n\ \ \ \ (4)\ push1\ 2\ \ \ \ \ \ \ \ \ #\ \"-1\"\n\ \ \ \ (6)\ invokeStk1\ 2\ \n\ \ \ \ (8)\ mult\ \n\ \ \ \ (9)\ push1\ 3\ \ \ \ \ \ \ \ \ #\ \"r\"\n\ \ \ \ (11)\ loadStk\ \n\ \ \ \ (12)\ push1\ 4\ \ \ \ \ \ \ \ \ #\ \"3\"\n\ \ \ \ (14)\ expon\ \n\ \ \ \ (15)\ mult\ \n\ \ \ \ (16)\ done\ \n======\n\nThis\ shows\ that\ `4\ /\ 3.`\ is\ precomputed\ to\ `1.3333333333333333`,\ but\ `acos(-1)`\ is\ not\ precomputed\ to\ `3.141592653589793`.\ While\ it\ would\ seem\ ideal\ to\ fold\ the\ constants\ together\ into\ `4.1887902047863905`,\ doing\ so\ would\ skip\ invoking\ `\[tcl::mathfunc\]::\[acos\]`,\ which\ might\ have\ a\ `\[trace\]`\ on\ it.\ Tcl\ optimizations\ always\ favor\ correctness\ over\ speed,\ so\ this\ shortcut\ is\ not\ available.\nThis\ shows\ that\ \"4\ /\ 3.\"\ is\ precomputed\ to\ \"1.3333333333333333\",\ but\ \"acos(-1)\"\ is\ not\ precomputed\ to\ \"3.141592653589793\".\ While\ it\ would\ seem\ ideal\ to\ fold\ the\ constants\ together\ into\ \"4.1887902047863905\",\ doing\ so\ would\ skip\ invoking\ `\[tcl::mathfunc\]::\[acos\]`,\ which\ might\ have\ a\ `\[trace\]`\ on\ it.\ Tcl\ optimizations\ always\ favor\ correctness\ over\ speed,\ so\ this\ shortcut\ is\ not\ available.\nHere's\ the\ above\ again,\ but\ with\ local\ variables\ which\ provide\ a\ large\ speed\ boost\ by\ avoiding\ looking\ up\ the\ variable\ by\ name:\n\n======none\n%\ tcl::unsupported::disassemble\ lambda\ \{\{\}\ \{expr\ \{4\ /\ 3.\ *\ acos(-1)\ *\ \$r\ **\ 3\}\}\}\nByteCode\ 0x00000000027A1080,\ refCt\ 1,\ epoch\ 16,\ interp\ 0x00000000026E65B0\ (epoch\ 16)\n\ \ Source\ \"expr\ \{4\ /\ 3.\ *\ acos(-1)\ *\ \$r\ **\ 3\}\"\n\ \ Cmds\ 1,\ src\ 34,\ inst\ 16,\ litObjs\ 4,\ aux\ 0,\ stkDepth\ 3,\ code/src\ 0.00\n\ \ Proc\ 0x00000000026A8620,\ refCt\ 1,\ args\ 0,\ compiled\ locals\ 1\n\ \ \ \ \ \ slot\ 0,\ scalar,\ \"r\"\n\ \ Commands\ 1:\n\ \ \ \ \ \ 1:\ pc\ 0-14,\ src\ 0-33\n\ \ Command\ 1:\ \"expr\ \{4\ /\ 3.\ *\ acos(-1)\ *\ \$r\ **\ 3\}\"\n\ \ \ \ (0)\ push1\ 0\ \ \ \ \ \ \ \ \ #\ \"1.3333333333333333\"\n\ \ \ \ (2)\ push1\ 1\ \ \ \ \ \ \ \ \ #\ \"tcl::mathfunc::acos\"\n\ \ \ \ (4)\ push1\ 2\ \ \ \ \ \ \ \ \ #\ \"-1\"\n\ \ \ \ (6)\ invokeStk1\ 2\ \n\ \ \ \ (8)\ mult\ \n\ \ \ \ (9)\ loadScalar1\ %v0\ \ \ \ \ \ \ \ \ #\ var\ \"r\"\n\ \ \ \ (11)\ push1\ 3\ \ \ \ \ \ \ \ \ #\ \"3\"\n\ \ \ \ (13)\ expon\ \n\ \ \ \ (14)\ mult\ \n\ \ \ \ (15)\ done\ \n======\n\n(For\ disassembly\ readouts,\ it's\ not\ necessary\ to\ list\ the\ variables\ as\ arguments\ to\ the\ lambda.\ They'll\ be\ assigned\ slots\ in\ the\ compiled\ locals\ table\ either\ way.\ You're\ not\ actually\ running\ the\ code,\ so\ it\ doesn't\ matter\ if\ the\ variable\ exists.)\n\nCommon\ subexpressions\ cannot\ be\ optimized\ because\ this\ would\ bypass\ some\ potential\ traces\ on\ variable\ access\ and\ procedure\ invocation.\ If\ `expr`\ could\ know\ in\ advance\ that\ particular\ procedures\ and\ variables\ don't\ have\ traces,\ it\ would\ have\ greater\ freedom\ to\ perform\ common\ subexpression\ elimination.\ Knowing\ that\ a\ procedure\ is\ a\ pure\ function\ (its\ result\ depends\ only\ on\ its\ arguments),\ plus\ knowing\ that\ its\ definition\ will\ not\ change\ throughout\ the\ execution\ of\ the\ program,\ would\ let\ expr\ treat\ `acos(-1)`\ as\ a\ constant.\nCommon\ subexpressions\ cannot\ be\ optimized\ because\ this\ would\ bypass\ some\ potential\ traces\ on\ variable\ access\ and\ procedure\ invocation.\ If\ expr\ could\ know\ in\ advance\ that\ particular\ procedures\ and\ variables\ don't\ have\ traces,\ it\ would\ have\ greater\ freedom\ to\ perform\ common\ subexpression\ elimination.\ Knowing\ that\ a\ procedure\ is\ a\ pure\ function\ (its\ result\ depends\ only\ on\ its\ arguments),\ plus\ knowing\ that\ its\ definition\ will\ not\ change\ throughout\ the\ execution\ of\ the\ program,\ would\ let\ expr\ treat\ acos(-1)\ as\ a\ constant.\nNow\ rearrange\ the\ expression\ to\ put\ the\ division\ at\ the\ end.\ Algebraically,\ this\ should\ produce\ an\ identical\ result.\ But\ because\ of\ potential\ floating\ point\ precision\ issues\ (non-commutativity\ of\ operations),\ Tcl\ must\ play\ it\ safe\ and\ do\ the\ operations\ in\ the\ order\ specified:\n\n======none\n%\ tcl::unsupported::disassemble\ script\ \{expr\ \{4\ *\ acos(-1)\ *\ \$r\ **\ 3\ /\ 3.\}\}\nByteCode\ 0x00000000025F91B0,\ refCt\ 1,\ epoch\ 16,\ interp\ 0x00000000026365B0\ (epoch\ 16)\n\ \ Source\ \"expr\ \{4\ *\ acos(-1)\ *\ \$r\ **\ 3\ /\ 3.\}\"\n\ \ Cmds\ 1,\ src\ 34,\ inst\ 20,\ litObjs\ 6,\ aux\ 0,\ stkDepth\ 3,\ code/src\ 0.00\n\ \ Commands\ 1:\n\ \ \ \ \ \ 1:\ pc\ 0-18,\ src\ 0-33\n\ \ Command\ 1:\ \"expr\ \{4\ *\ acos(-1)\ *\ \$r\ **\ 3\ /\ 3.\}\"\n\ \ \ \ (0)\ push1\ 0\ \ \ \ \ \ \ \ \ #\ \"4\"\n\ \ \ \ (2)\ push1\ 1\ \ \ \ \ \ \ \ \ #\ \"tcl::mathfunc::acos\"\n\ \ \ \ (4)\ push1\ 2\ \ \ \ \ \ \ \ \ #\ \"-1\"\n\ \ \ \ (6)\ invokeStk1\ 2\ \n\ \ \ \ (8)\ mult\ \n\ \ \ \ (9)\ push1\ 3\ \ \ \ \ \ \ \ \ #\ \"r\"\n\ \ \ \ (11)\ loadStk\ \n\ \ \ \ (12)\ push1\ 4\ \ \ \ \ \ \ \ \ #\ \"3\"\n\ \ \ \ (14)\ expon\ \n\ \ \ \ (15)\ mult\ \n\ \ \ \ (16)\ push1\ 5\ \ \ \ \ \ \ \ \ #\ \"3.\"\n\ \ \ \ (18)\ div\ \n\ \ \ \ (19)\ done\ \n======\n\nBack\ to\ common\ subexpression\ elimination:\ It\ may\ seem\ that\ the\ solution\ is\ for\ the\ programmer\ to\ manually\ precompute\ common\ subexpressions\ and\ reference\ their\ values\ via\ variables.\ This\ generally\ helps,\ so\ long\ as\ the\ subexpressions\ aren't\ too\ simple,\ but\ you\ must\ use\ local\ variables\ or\ else\ performance\ will\ suffer:\n\n======\n%\ proc\ a\ \{x\}\ \{expr\ \{cos(\$x\ *\ acos(-1))\ +\ sin(\$x\ *\ acos(-1))\}\}\n%\ proc\ b\ \{x\}\ \{set\ y\ \[expr\ \{\$x\ *\ acos(-1)\}\]\;\ expr\ \{cos(\$y)\ +\ sin(\$y)\}\}\n%\ proc\ c\ \{x\}\ \{set\ ::y\ \[expr\ \{\$x\ *\ acos(-1)\}\]\;\ expr\ \{cos(\$::y)\ +\ sin(\$::y)\}\}\n%\ set\ x\ 12.3\n%\ time\ \{a\ \$x\}\ 1000000\n1.536581\ microseconds\ per\ iteration\n%\ time\ \{b\ \$x\}\ 1000000\n1.333106\ microseconds\ per\ iteration\n%\ time\ \{c\ \$x\}\ 1000000\n1.994305\ microseconds\ per\ iteration\n======\n\n\n\n\nIn\ \[http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/f873d6fab9f0e304%|%Embedded\ vs.\ separate\ commands\],\ 1992-12-38,\ \[JO\]\ published\ the\ voting\ results\ 37:8\ in\ favor\ of\ embedded\ functions()\ vs.\ separate\ \[\[commands\]\]\n\n\n**\ (Tcl\ 8.4\ and\ older)\ 32-bit\ integer\ limitations\ **\n\nAddition\n\n======none\n%\ expr\ (1<<31)-1\n2147483647\n\n%\ expr\ 2147483647\ +\ 2147483647\n-2\n======\n\nMultiplication\n\n======none\n%\ expr\ sqrt((1<<31)-1)\n46340.9500011\n\nexpr\ 46341*46341\n-2147479015\n======\n\nThese\ are\ results\ of\ Tcl\ 8.4\ and\ older\ versions\ using\ a\ 32-bit\ representation\nfor\ integers.\n\nTcl\ 8.5\ features\ abritrary-precision\ integers.\ \ See\n\[http://www.tcl.tk/cgi-bin/tct/tip/237.html%|%TIP\ #237\].\n\n**\ Suggestion\ to\ reparse\ expr\ variables\ **\n\nexpressions\ in\ variable\ values\ would\ interpreted\ as\ such\n\n\[RS\]\ 2003-04-24:\ Here's\ a\ tiny\ wrapper\ for\ friends\ of\ infix\ assignment:\n\n======none\nproc\ let\ \{var\ =\ args\}\ \{\n\ \ \ \ uplevel\ 1\ set\ \$var\ \\\[expr\ \$args\\\]\n\}\ \;#RS\n======\n\n======none\n%\ let\ i\ =\ 1\n1\n%\ let\ j\ =\ \$i\ +\ 1\n2\n%\ let\ k\ =\ \{\$i\ +\ \$j\}\n3\n======\n\n======\nset\ y\ 2*3\;\ puts\ \[expr\ \$y+0\]\ \;#\ ==>\ 6\n======\n\n\[AM\]:\ The\ problem\ with\ variables\ whose\ values\ are\ actually\ expressions\ is\ that\nthey\ change\ the\ whole\ expression\ in\ which\ they\ are\ used.\ The\ performance\ gain\nfor\ caching\ the\ parsed\ expression\ will\ then\ be\ lost.\n\n\[AMG\]:\ This\ reopens\ the\ door\ to\ all\ the\ security,\ performance,\ and\ correctness\ problems\ solved\ by\ bracing\ one's\ expressions.\n**\ Unsuitability\ of\ expr\ for\ time\ offset\ calculations\ **\n\n\[Wookie\]:\ \ I\ had\ some\ trouble\ recently\ using\ `expr`\ to\ calculate\ time\noffsets.\ I\ had\ 2\ time\ stamps\ in\ the\ form\ hh:mm\n\nSo\ I\ had\ 4\ variables\ h1,\ m1,\ h2,\ m2\ and\ one\ of\ my\ `expr`\ functions\ was\n\n======\nset\ result\ \[expr\ \{\$m1\ +\ \$m2\}\]\n======\n\nAs\ many\ of\ you\ may\ be\ thinking,\ you\ fool!\ what\ about\ 08\ and\ 09,\ which\ will\ get\ntreated\ as\ invalid\ octal.\ So\ after\ some\ grumbling\ I\ thought\ okay\ so\ I\ have\ to\ntrimleft\ them.\ Bit\ verbose\ but\ who\ cares:\n\n======\nset\ m1\ \[string\ trimleft\ \$m1\ 0\]\nset\ m2\ \[string\ trimleft\ \$m2\ 0\]\nset\ result\ \[expr\ (\$m1\ +\ \$m2)\]\n======\n\nNow\ what\ could\ possibly\ go\ wrong\ with\ that...\ well\ obviously\ 00\ becomes\ the\nempty\ string,\ which\ causes\ unexpected\ closed\ parameter\ in\ the\ `expr`ession.\nSo\ now\ I\ have\ to\ check\ for\ the\ empty\ string.\ So...\n\n======\nset\ m1\ \[string\ trimleft\ \$m1\ 0\]\nif\ \{\$m1==\{\}\}\ \{set\ m1\ 0\}\n\nset\ m2\ \[string\ trimleft\ \$m2\ 0\]\nif\ \{\$m2==\{\}\}\ \{set\ m2\ 0\}\n\nset\ result\ \[expr\ \{\$m1\ +\ \$m2\}\]\n======\n\n...\ and\ then\ repeat\ it\ for\ the\ hours.\ It\ all\ seemed\ very\ clumsy.\ So\ I\ came\ up\nwith\ this,\ which\ may\ solve\ many\ of\ the\ conversion\ issues\ in\ this\ section.\n\n======\nscan\ \"\$h1:\$m1\ \$h2:\$m2\"\ \"%d:%d\ %d:%d\"\ h1\ m1\ h2\ m2\nset\ result\ \[expr\ \{\$m1\ +\ \$m2\}\]\n======\n\nAll\ the\ conversions\ to\ int\ have\ been\ done\ and\ leading\ 0's\ have\ been\ stripped\nand\ returns\ 0\ if\ the\ value\ is\ all\ 0s.\ This\ works\ for\ float\ and\ probably\ double\n(though\ I've\ not\ tried).\ Can\ anyone\ see\ any\ problems\ with\ this\ approach?\n\n\[glennj\]:\ No,\ `\[scan\]`\ is\ definitely\ the\ way\ to\ parse\ numbers\ out\ of\ dates\nand\ times.\ \ However,\ for\ date\ arithmetic,\ nothing\ beats\ `\[clock\]`.\n\n======\n#\ adding\ a\ delta\ to\ a\ time\nset\ h1\ 12\;\ set\ m1\ 45\nset\ h2\ 3\;\ set\ m2\ 30\nclock\ format\ \[clock\ add\ \[clock\ scan\ \"\$h1:\$m1\"\ -format\ \"%H:%M\"\]\ \$h2\ hours\ \$m2\ minutes\]\ -format\ %T\ \;#\ ==>\ 16:15:00\n======\n\nWhat\ are\ you\ trying\ to\ do\ with\ your\ two\ times?\n\n regexp2} CALL {my render expr `'''\[http://www.tcl.tk/man/tcl/TclCmd/expr.htm%|%expr\]'''`,\ a\ \[TclCommands%|%built-in\]\ \[Tcl\]\ command,\ evaluates\ an\ expression.\n\n\n\n**\ See\ Also\ **\n\n\ \ \ \[A\ little\ math\ language\]:\ \ \ adds\ features\ &\ sugar\ to\ `expr`\n\n\ \ \ \[A\ real\ problem\]:\ \ \ \n\n\ \ \ \[Additional\ math\ functions\]:\ \ \ \n\n\ \ \ \[Arbitrary\ precision\ math\ procedures\]:\ \ \ \n\n\ \ \ \[Brace\ your\ expr-essions\]:\ \ \ \n\n\ \ \ \[compute\]:\ \ \ more\ sugar\ for\ `expr`\n\n\ \ \ \[Converting\ numbers\ from\ arbitrary\ bases\]:\ \ \ \n\n\ \ \ \[DebuggingExprCalls\]:\ \ \ \[rwm\]\ sometimes\ it\ is\ difficult\ to\ debug\ `expr`\ calls\ where\ the\ operands\ are\ variables.\ \[DebuggingExprCalls\]\ explains\ how\ to\ wrap\ expr\ to\ help\ with\ these\ cases.\n\n\ \ \ \[double\ substitution\]:\ \ \ \n\n\ \ \ `\[cmdSplit%|%exprlex\]`\ and\ `\[cmdSplit%|%funclex\]`:\ \ \ Split\ expressions\ and\ functions\ into\ their\ lexical\ components.\n\n\ \ \ \[gotcha\]:\ \ \ where\ `expr`\ figures\ prominently\n\n\ \ \ \[Tcl\ and\ octal\ numbers\]:\ \ \ The\ Octal\ Bug\n\n\ \ \ \[expr\ problems\ with\ int\]:\ \ \ historical\ (pre-8.5)\ information\ on\ the\ limits\ of\ number\ representation\ (both\ integer\ and\ float)\ inherited\ from\ C\n\n\ \ \ \[for\]:\ \ \ \n\n\ \ \ \[How\ can\ I\ do\ math\ in\ Tcl\]:\ \ \ \n\n\ \ \ \[if\]:\ \ \ \n\n\ \ \ \[Importing\ expr\ functions\]:\ \ \ use\ `expr`'s\ functions\ without\ explicitly\ calling\ that,\ see\ \[Importing\ expr\ functions\].\n\n\ \ \ \[infix\]:\ \ \ a\ package\ to\ facilitate\ writing\ sequences\ of\ mathematical\ formulae\ in\ the\ familiar\ infix\ form\n\n\ \ \ \[Math\ function\ help\]:\ \ \ \n\n\ \ \ \[Modeling\ COND\ with\ expr\]:\ \ \ Braced\ expressions\ can\ span\ several\ lines\n\n\ \ \ \[Numerical\ Analysis\ in\ Tcl\]:\ \ \ \n\n\ \ \ \[Sample\ Math\ Programs\]:\ \ \ extremely\ simple\ math\ examples\n\n\ \ \ \[Tcl\ help\]:\ \ \ \n\n\ \ \ \[http://tip.tcl.tk/123%|%TIP\ #123\]:\ \ \ Adding\ an\ Exponentiation\ Operator\ to\ `expr`\n\n\ \ \ \[http://tip.tcl.tk/174%|%TIP\ #174\]:\ \ \ \[Math\ Operators\ as\ Commands\]\n\n\ \ \ \[http://tip.tcl.tk/182%|%TIP\ #182\]:\ \ \ Add\ 'expr\ bool'\ Math\ Function\n\n\ \ \ \[http://tip.tcl.tk/201%|%TIP\ #201\]:\ \ \ Add\ 'in'\ Operator\ to\ expr\n\n\ \ \ \[http://tip.tcl.tk/232%|%TIP\ #201\]:\ \ \ Creating\ New\ Math\ Functions\ for\ `expr`\ (\[tcl::mathfunc\])\n\n\ \ \ \[http://tip.tcl.tk/237%|%TIP\ #237\]:\ \ \ Arbitrary-Precision\ Integers\ for\ Tcl\n\n\ \ \ \[while\]:\ \ \ \n\n\n\n\n**\ Documentation\ **\n\n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/expr.htm%|%officieal\ reference\]:\ \ \ \n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/expr.htm%|%man\ page\]:\ \ \ \n\ \ \ \[tcl::mathfunc%|%mathfunc\]:\ \ \ \n\n\ \ \ \[tcl::mathop%|%mathop\ man\ page\]:\ \ \ \n\n\ \ \ \[tcl_precision\]:\ \ \ \n\n\ \ \ \[http://www.tcl.tk/man/tcl/TclLib/GetInt.htm%|%Tcl_GetBoolean\ man\ page\]:\ \ \ \n\n\n\n**\ Synopsis\ **\n\n'''expr'''\ ''arg''\ ?''arg\ arg\ ...''?\n\n\n\n**\ Description\ **\n\n`expr`\ \[concat%|%concatentates\]\ its\ arguments,\ evaluates\ this\ result\ as\ a\ Tcl\ \n`expr`\ implements\ a\ mini\ language\ that\ has\ a\ syntax\ separate\ from\ \[Tcl\].\ \ It\ supports\ some\ of\ the\ same\ constructs\ as\ Tcl,\ such\ as\n\[Dodekalogue%|%variable\ substitution\],\ command\ substitution,\ and\ braces.\ \ It\nadds\ additional\ syntax\ for\ mathematical\ operators\ and\ functions,\ and\ unlike\nTcl,\ does\ not\ accept\ character\ strings\ that\ are\ not\ enclosed\ in\ double\ quotes\nor\ braces.\n`expr`\ implements\ a\ \[little\ language\]\ that\ has\ a\ syntax\ separate\ from\ \[Tcl\].\nThe\ `expr`\ conditions\ of\ commands\ such\ as\ `\[if\]`\ and\ `\[while\]`\ expect\nthe\ expression\ to\ evaluate\ to\ a\ boolean,\ i.e.,\ an\ integer\ or\ one\ of\ the\nfollowing\ string\ values:\nA\ value\ recognized\ as\ boolean\ by\ `\[string\ is\]\ boolean...`\ can\ be\ used\ directly,\n\ \ \ *\ true,\ on,\ yes\nThe\ operators\ permitted\ in\ Tcl\ expressions\ include\ most\ of\ the\ operators\n\ \ \ *\ false,\ off,\ no\nFunctions\ take\ the\ form,\nAny\ of\ these\ values\ may\ be\ abbreviated,\ and\ upper-case\ spellings\ are\ also\nacceptable.\ \ See\ the\n\[http://www.tcl.tk/man/tcl/TclLib/GetInt.htm%|%Tcl_GetBoolean\ man\ page\]\n\ \ \ \ :\ \ \ ''name''`(`''argument?'')\nBoolean\ values\ such\ as\ `true`\ need\ not\ be\ enclosed\ in\ double\ quotes.\n\ \ \ \ :\ \ \ ''name''`(`''argument''`,`''argument\ ...'')`\n`expr`\ interprets\ \"bare\"\ strings\ as\ function\ names,\ e.g.,\ `cos(\$x)`,\ or\ as\nboolean\ values\ where\ context\ permits,\ and\ will\ raise\ an\ error\ if\ a\ bare\ word\ is\nencountered\ where\ a\ literal\ string\ is\ expected.\ Additionally,\ some\ operators\ (`eq`,\ `ne`,\ `in`,\ and\ `ni`)\ resemble\ bare\ strings.\n\n======\n`expr`\ \[concat%|%concatentates\]\ its\ arguments,\ evaluates\ this\ result\ as\ a\ \[Tcl\]\nexpression,\ and\ returns\ the\ value.\ The\ operators\ permitted\ in\ Tcl\ expressions\ninclude\ most\ of\ the\ operators\ permitted\ in\ \[C\]\ expressions\ and\ a\ few\ additional\nones.\ \ The\ operators\ have\ the\ same\ meaning\ and\ precedence\ as\ the\ corresponding\nC\ operators.\ Expressions\ almost\ always\ yield\ numeric\ results\ (integer\ or\nfloating-point\ values).\ For\ example,\ the\ expression,\n\nset\ val1\ 8.2\nset\ val2\ 6\nexpr\ \{\$val1\ +\ \$val2\}\nexpr\ \$val1\ +\ \$val2\n\nResult:\nreturns\ `14.2`.\n======\nUsually,\ though,\ it's\ best\ to\ \[Brace\ your\ Expr-essions%|%brace\]\ the\ argument:\nIn\ most\ cases,\ it's\ best\ to\ \[Brace\ your\ Expr-essions%|%brace\]\ or\ otherwise\nexpr\ \{\$val1+\$val2\}\n======\n\nThis\ allows\ `expr`\ to\ do\ the\ interpretation,\ rather\ than\ having\ Tcl\ interpret\nAny\ argument\ that\ can\ be\ interpreted\ in\ some\ way,\ e.g.,\ variable\ or\ a\ command\nexpansion,\ should\ normally\ be\ enclosed\ in\ brackets.\ \ This\ allows\ the\n`expr`\ command\ to\ do\ the\ interpretation,\ rather\ than\ having\ the\ caller\ninterpret\ the\ arguments\ before\ handing\ them\ off\ to\ `expr`.\ \ See\ below\ for\nmore\ details.\n`expr`\ expressions\ differ\ from\ \[C\]\ expressions\ in\ the\ way\ that\ operands\ are\n`expr`essions\ differ\ from\ C\ expressions\ in\ the\ way\ that\ operands\ are\n(comparison)\ and\ lists\ (membership).\n\n\n\n**\ Operators\ **\n\nSince\ Tcl\ 8.5,\ many\ operators\ have\ command-equivalents\ in\ the\n'''::\[tcl::mathop\]'''\ \[namespace\].\n\nIn\ spite\ of\ the\ name\ '''mathop''',\ some\ of\ the\ operators\ are\ string-oriented,\ rather\nIn\ spite\ of\ the\ name\ '''mathop''',\ some\ of\ the\ operators\ are\ string,\ rather\n\nThe\ following\ is\ a\ chart\ of\ operators,\ in\ order\ of\ precedence\ (tightest-binding\nto\ least-tight\ associativity):\nto\ least-tight\ binding):\n&|\ \[-\]\ \[+\]\ \[~\]\ \[!\]\ |\ Unary\ operators\;\ specifically\ a\ negation\ operation,\ a\ non-negation\ operation,\ a\ bit-wise\ NOT\ operation\ (every\ bit\ in\ the\ input\ value\ gets\ replaced\ by\ its\ inverse)\ and\ a\ logical\ NOT\ operation\ (non-zero\ maps\ to\ zero,\ and\ zero\ maps\ to\ one).\ |&\n&|\ \[**\]\ |\ exponential.\ From\ Tcl\ 8.5\ on.\ |&\n&|\ \[+\]\ \[-\]\ |\ Addition\ and\ subtraction.\ |&\n&|\ \[<<\]\ \[>>\]\ |\ Left\ and\ right\ shift.\ \ Equivalent\ to\ multiplying\ or\ dividing\ by\ a\ suitable\ power\ of\ two,\ and\ then\ reducing\ the\ result\ to\ the\ range\ representable\ in\ an\ integer\ on\ the\ host\ platform.\ |&\n&|\ \[<\]\ \[>\]\ \[<=\]\ \[>=\]\ |\ Ordering\ relations:\ \ less\ than,\ greater\ than,\ less\ than\ or\ equal,\ greater\ than\ or\ equal.\ \ These\ operations\ work\ on\ strings\ as\ well\ as\ numbers,\ but\ where\ string\ comparison\ is\ intended,\ it\ is\ advisable\ to\ use\ the\ dedicated\ string\ comparison\ operators\ or\ \[string\ compare\]\ or\ \[string\ equal\]\ instead,\ \ as\ those\ are\ \ more\ predictable\ in\ the\ case\ of\ a\ string\ that\ looks\ like\ a\ number.\ \ For\ example,\ \[string\ equal\]\ considers\ \"6\"\ and\ \"06\"\ to\ be\ different\ strings,\ but\ the\ `expr`'\ operator\ `==`\ considers\ them\ to\ be\ equivalent\ numbers.|&\n&|\ \[==\]\ \[!=\]\ |\ Equality\ and\ inequality.\ \ \ These\ operations\ work\ on\ strings\ as\ well\ as\ numbers,\ but\ see\ the\ description\ equality\ operators\ for\ notes\ about\ string\ comparison.\ |&\n&|\ \[eq\]\ \[ne\]\ |\ Since\ Tcl\ 8.4,\ these\ are\ string-comparison\ operators.\ \"6\"\ and\ \"06\",\ as\ well\ as\ 1\ and\ 1.0,\ will\ compare\ unequal.\ |&\n&|\ \[in\]\ \[ni\]\ |\ checks\ for\ occurrence\ of\ an\ item\ in\ a\ list.\ New\ in\ Tcl\ 8.5.\ |&\n&|\ \[**\]\ |\ exponential.\ From\ Tcl\ 8.5\ on.\ |&\n&|\ \[&\]\ |\ Bit-wise\ AND.\ \ A\ bit\ is\ set\ in\ the\ result\ when\ the\ corresponding\ bit\ is\ set\ in\ both\ the\ arguments.\ |&\n&|\ \[^\]\ |\ Bit-wise\ exclusive\ OR.\ \ A\ bit\ is\ set\ in\ the\ result\ when\ the\ corresponding\ bit\ is\ set\ in\ ''precisely\ one''\ of\ the\ arguments.\ |&\n&|\ \[<<pipe>>\]\ |\ Bit-wise\ OR.\ \ \ A\ bit\ is\ set\ in\ the\ result\ when\ the\ corresponding\ bit\ is\ set\ in\ either\ of\ the\ arguments.\ |&\n&|\ \[&&\]\ |\ Logical\ AND.\ \ \ The\ result\ is\ `1`\ when\ both\ of\ the\ arguments\ true.\ and\ `0`\ otherwise.\ \ This\ operation\ is\ a\ ''short-circuiting''\ operation,\ and\ will\ only\ evaluate\ its\ second\ argument\ when\ the\ first\ argument\ is\ non-zero.\ \ This\ includes\ the\ expansion\ of\ Tcl\ commands\ in\ square\ brackets.\ \ Where\ Tcl\ seems\ not\ to\ be\ behaving\ as\ describe\ here,\ see\ \[double\ substitution\].\ |&\n&|\ \[<<pipe>><<pipe>>\]\ |\ Logical\ OR.\ \ The\ result\ is\ `0`\ when\ both\ of\ the\ arguments\ are\ false,\ and\ `1`\ otherwise.\ \ This\ operation\ is\ a\ ''short-circuiting''\ operation,\ and\ will\ only\ evaluate\ its\ second\ argument\ when\ the\ first\ argument\ is\ zero.\ \ Where\ Tcl\ seems\ not\ to\ be\ behaving\ as\ describe\ here,\ see\ \[double\ substitution\].\ |&\n&|\ x'''?'''y''':'''z\ |\ If-then-else,\ as\ in\ \[C\].\ `x`,\ `y`,\ and\ `z`\ are\ expressions.\ \ The\ result\ is\ `y`\ if\ `x`\ is\ true,\ and\ `z`\ otherwise.\ \ This\ operation\ is\ a\ ''short-circuiting''\ operation:\ \ If\ `x`\ is\ true,\ `z`\ will\ not\ be\ evaluated,\ and\ if\ `x`\ is\ false,\ `y`\ will\ not\ be\ evaluated.\ \ Where\ Tcl\ seems\ not\ to\ be\ behaving\ as\ describe\ here,\ see\ \[double\ substitution\].\ \ `\[if\]`\ performs\ just\ as\ well\ as\ this\ construct.\ \ The\ generated\ bytecode\ is\ identical.\ |&\n\n\n\n**\ Functions\ **\n\nSee\ the\ \[http://www.tcl.tk/man/tcl/TclCmd/mathfunc.htm%|%mathfunc\ man\ page\].\n\nThe\ following\ is\ a\ list\ of\ builtin\ functions:\n\n\ \ \ '''\[abs\]'''(x):\ \ \ Absolute\ value\ (negate\ if\ negative).\n\n\ \ \ '''\[acos\]'''(x):\ \ \ Inverse\ cosine\ (result\ in\ radians).\n\n\ \ \ '''\[asin\]'''(x):\ \ \ Inverse\ sine\ (result\ in\ radians).\n\n\ \ \ '''\[atan\]'''(x):\ \ \ Inverse\ tangent\ (result\ in\ radians).\n\n\ \ \ '''\[atan2\]'''(y,x):\ \ \ Inverse\ tangent.\ \ Can\ handle\ cases\ which\ plain\ `atan()`\ can't\ (due\ to\ division\ by\ zero)\ and\ has\ a\ larger\ output\ range\ (result\ in\ radians).\n\n\ \ \ '''\[bool\]'''(x):\ \ \ Accepts\ any\ valid\ boolean\ value\ and\ returns\ the\ corresponding\ boolean\ value\ `0`\ or\ `1`.\n\n\ \ \ '''\[ceil\]'''(x):\ \ \ Ceiling\ (defined\ over\ floating\ point\ numbers.)\ \ If\ the\ input\ value\ is\ not\ a\ whole\ number,\ return\ the\ next\ ''larger''\ whole\ number.\ '''Surprise''':\ The\ return\ value\ is\ a\ float,\ not\ an\ integer.\n\n\ \ \ '''\[cos\]'''(x):\ \ \ Cosine\ (input\ in\ radians).\n\n\ \ \ '''\[cosh\ function%|%cosh\]'''(x):\ \ \ Hyperbolic\ cosine.\n\n\ \ \ '''\[double\]'''(x):\ \ \ Convert\ number\ to\ floating\ point.\n\n\ \ \ '''\[entier\]'''(x):\ \ \ Like\ `int(x)`,\ but\ there\ is\ no\ limit\ to\ the\ input\ or\ output\ value.\n\n\ \ \ '''\[exp\]'''(x):\ \ \ Exponential\ function.\ \ Returns\ ''e''\ to\ the\ power\ of\ `x`,\ where\ ''e''\ is\ the\ base\ of\ natural\ logarithms.\n\ \ \ '''\[exp\]'''(x):\ \ \ Exponential\ function.\ \ Returns\ e\ to\ the\ power\ or\ `x`,\ where\ e\ is\ the\ base\ of\ natural\ logarithms.\n\ \ \ '''\[floor\]'''(x):\ \ \ Floor\ (defined\ over\ floating-point\ numbers.)\ \ If\ the\ input\ value\ is\ not\ a\ whole\ number,\ return\ the\ next\ ''smaller''\ whole\ number\ as\ a\ floating-point\ number.\n\n\ \ \ '''\[fmod\]'''(x,\ y):\ \ \ Floating-point\ remainder\ of\ x\ divided\ by\ y.\n\n\ \ \ '''\[hypot\]'''(x,y):\ \ \ Hypotenuse\ calculator.\ \ Assumes\ boring\ old\ Euclidean\ geometry.\ \ If\ the\ projection\ of\ a\ straight\ line\ segment\ onto\ the\ X\ axis\ is\ `x`\ units\ long,\ and\ the\ projection\ of\ that\ line\ segment\ onto\ the\ Y\ axis\ is\ `y`\ units\ long,\ then\ the\ line\ segment\ is\ `hypot(x,y)`\ units\ long.\ Equivalent\ to\ `sqrt(x*x+y*y)`.\n\n\ \ \ '''\[int\]'''(x):\ \ \ Convert\ number\ to\ integer\ by\ truncation.\ \ Limited\ by\ the\ size\ of\ long\ in\ \[C\].\n\n\ \ \ '''\[isqrt\]'''(x):\ \ \ Compute\ the\ integer\ part\ of\ the\ square\ root\ of\ `x`.\n\n\ \ \ '''\[log\]'''(x):\ \ \ Natural\ logarithm.\n\n\ \ \ '''\[log10\]'''(x):\ \ \ Logarithm\ with\ respect\ to\ base\ 10.\n\n\ \ \ '''\[max\]'''(x,...):\ \ \ The\ argument\ with\ the\ greatest\ value.\n\ \ \ '''\[max\]'''(x,...):\ \ \ Return\ the\ one\ argument\ with\ the\ greatest\ value.\n\ \ \ '''\[min\]'''(x,...):\ \ \ The\ argument\ with\ the\ least\ value.\n\ \ \ '''\[min\]'''(x,...):\ \ \ Return\ the\ one\ argument\ with\ the\ least\ value.\n\ \ \ '''\[pow\]'''(x,y):\ \ \ Power\ function.\ \ `x`\ to\ the\ power\ of\ `y`.\n\n\ \ \ '''\[rand\]'''():\ \ \ Random\ number.\ \ Uses\ uniform\ distribution\ over\ the\ range\ \[0,1).\ \ ''This\ RNG\ is\ not\ suitable\ for\ cryptography.''\n\n\ \ \ '''\[round\]'''(x):\ \ \ Round\ to\ nearest\ whole\ number.\ \ ''Not\ suitable\ for\ financial\ rounding.''\n\n\ \ \ '''\[sin\]'''(x):\ \ \ Sine\ (input\ in\ radians).\n\n\ \ \ '''\[sinh\]'''(x):\ \ \ Hyperbolic\ sine.\n\n\ \ \ '''\[sqrt\]'''(x):\ \ \ Square\ root\ (well,\ the\ positive\ square\ root\ only.\ \ And\ Tcl\ doesn't\ do\ complex\ math,\ so\ the\ input\ had\ better\ be\ positive).\n\n\ \ \ '''\[srand\]'''(x):\ \ \ Seeds\ the\ random\ number\ generator\ with\ the\ given\ value.\ \ Each\ interpreter\ has\ its\ own\ random\ number\ generator,\ which\ starts\ out\ seeded\ with\ the\ current\ time.\n\n\ \ \ '''\[tan\]'''(x):\ \ \ Tangent\ (input\ in\ radians.)\n\n\ \ \ '''\[tanh\]'''(x):\ \ \ Hyperbolic\ tangent.kjh\n\n\ \ \ '''\[wide\]'''(x):\ \ \ Take\ any\ numeric\ value,\ and\ return\ the\ low\ order\ 64\ bits\ of\ the\ integer\ value\ of\ the\ argument\n\n\n\n**\ Mathematical\ Expressions\ **\n\n\nSimple\ addition:\n\n======\nset\ a\ \[expr\ \{1\ +\ 2\}\]\n======\n\nmathematical\ functions\n\n======\nset\ a\ \[expr\ \{sqrt(4)\}\]\n======\n\n\[martin\ Lemburg\]:\ The\ following\ returns\ `1`\ because\ `\"\ 2\ \"`\ will\ be\ interpreted\nas\ `2`:\nas\ to\ `2`:\n======\nset\ a\ \[expr\ \{\"\ 2\ \"\ ==\ \[string\ trim\ \"\ 2\ \"\]\}\]\n======\n\nTo\ ensure\ that\ expression\ evaluates\ to\ a\ floating\ point\ number,\ use\ `double()`\nor\ `floor()`:\n\n======\nset\ a\ 1\nset\ b\ 2\nexpr\ \{double(\$a)/\$b\}\n======\n\nor,\ to\ get\ an\ integer:\n\n======\nexpr\ \{entier(\$a/\$b)\}\n======\n\n`int()`\ would\ also\ have\ worked,\ but\ `entier()`\ is\ more\ general\n\n\n**\ Order\ of\ Precedence\ **\n\nThe\ following\ returns\ returns\ 4,\ rather\ than\ -4\ as\ some\ might\ expect:\n\n======\nset\ a\ \[expr\ \{-2**2\}\]\n======\n\nThe\ following\ returns\ `1`\ because\ `2==2`\ is\ evaluated\ first:\nreturns\ `1`\ because\ `2==2`\ is\ evaluated\ first\n======\nset\ a\ \[expr\ \{5&2==2\}\]\n======\n\n\[AMG\]:\ The\ order\ of\ bitwise\ operations\ (`|`,\ `&`,\ and\ `^`)\ may\ seem\ totally\ bogus,\ but\ it's\ inherited\ from\ \[C\],\ which\ in\ turn\ inherited\ it\ from\ an\ early\ prototype\ version\ of\ C\ which\ lacked\ separate\ logical\ operators\ (`&&`\ and\ `||`)\ \[http://cm.bell-labs.com/who/dmr/chist.html\].\ I\ wouldn't\ cry\ if\ a\ new\ language\ (not\ Tcl)\ decided\ to\ break\ compatibility\ with\ C\ in\ this\ respect.\n**\ Composing\ Expressions\ **\n\n`expr`\ tries\ to\ interpret\ operands\ as\ numeric\ values,\ but\ doesn't\ parse\ \n`expr`\ tries\ to\ interpret\ operands\ as\ numeric\ values,\ but\ it\ does\ not\ try\nto\ interpret\ variable\ values\ as\ complete\ numeric\ expressons,\ so\ a\ value\ \"2*3\"\nwill\ be\ interpreted\ as\ a\ string:\n======\nset\ y\ 2*3\;\ expr\ \{\$y\}\ \ \ \;#\ ==>\ 2*3\nset\ y\ 2*3\;\ expr\ \{\$y+2\}\ \;#\ ==>\ can't\ use\ non-numeric\ string\ as\ operand\ of\ \"+\"\n======\n\nTo\ pass\ a\ complete\ expression\ stored\ in\ a\ variable,\ omit\ the\ braces\ so\ that\ Tcl\nTo\ pass\ a\ complete\ expression\ stored\ in\ a\ variable,\ take\ advantage\ of\ \[double\ substitution\]\ by\ omitting\ braces:\n======\nset\ y\ 2*3\;\ expr\ \$y\ \;#\ \ ==>\ 6\ \nset\ y\ 2*3\;\ puts\ \[expr\ \$y+2\]\ \;#\ ==>\ 8\n======\n\nBut\ be\ careful\ not\ to\ introduce\ an\ \[injection\ attack\]\ vulnerability.\ \ See\n\[double\ substitution\].\n\n\n\n**\ Literal\ String\ Operands\ **\n\n`expr`\ implements\ a\ little\ language\ distinct\ from\ the\ language\ described\ in\ \[dodekalogue%|%the\ rules\ of\ Tcl\].\ \ One\n`expr`\ implements\ a\ little\ language\ distinct\ from\ standard\ Tcl.\ \ One\n\n======none\n%\ \ if\ \{joe\ eq\ mike\}\ \{puts\ wow\}\nsyntax\ error\ in\ expression\ \"joe\ eq\ mike\":\ variable\ references\ require\ preceding\ \$\n%\ \ if\ \{\"joe\"\ eq\ \"mike\"\}\ \{puts\ wow\}\n%\ \ if\ \{\{joe\}\ eq\ \{mike\}\}\ \{puts\ wow\}\n======\n\nTo\ insert\ a\ literal\ value\ when\ templating\ an\ expression,\ use\ an\ \[identity\nIf\ you\ prefer\ consistency,\ then\ throughout\ your\ Tcl\ program,\ always\ quote\ values\ you\ consider\ to\ be\ \"strings\".\ (\[AMG\]:\ This\ is\ a\ totally\ arbitrary\ and\ stylistic\ distinction\ because\ \[everything\ is\ a\ string\].)\ Note\ that\ at\ some\ point\ `expr`\ may\ grow\ the\ feature\ of\ accepting\ bareword\ strings.\ (\[AMG\]:\ Or\ it\ might\ choose\ to\ interpret\ barewords\ as\ variable\ substitutions.)\n\nIf\ the\ return\ value\ of\ `expr`\ is\ numeric,\ it\ is\ transformed\ into\ a\ canonical\nIf\ the\ value\ of\ an\ `expr`\ is\ numeric,\ it\ will\ transformed\ into\ a\ canonical\n\n======\nset\ val\ 0x10\nputs\ \$val\ \;#\ 0x10\nset\ val\ \[expr\ \{\$val\}\]\nputs\ \$val\ \;#\ 16\n======\n\n======\nputs\ \[expr\ \{\[join\ \{0\ x\ 1\ 0\}\ \{\}\]\}\]\ \;#\ 16\n======\n\n\nIn\ other\ words,\ `expr`\ may\ mutate\ strings\ that\ can\ be\ interpreted\ as\nnumbers,\ which\ is\ a\ potential\ \[gotcha\]\ when\ using\ string\ functionality\nnumbers,\ which\ is\ a\ potential\ gotcha\ for\ the\ programmer\ using\ string\ functions\ninterpretation.\n\n\n\n**\ The\ Octal\ Bug\ **\n**\ \[Tcl\ and\ Octal\ Numbers%|%The\ Octal\ Bug\]\ **\nSee\ \[Tcl\ and\ Octal\ Numbers\]\ for\ details.\n\n\[rjm\]:\ Why\ does\ `expr`\ return\ integers\ with\ leading\ zeroes\ as\ hex?,\ e.g.\n\n======\nexpr\ 0100\ \;#\ ->\ 64\n======\n\n\[AMG\]:\ The\ leading\ zero\ makes\ 0100\ octal.\ \ The\ 1\ is\ in\ the\ 64's\ place,\ hence\nthe\ result\ is\ 64\ in\ decimal.\ \ That's\ not\ hexadecimal.\ \ `expr`\ always\nreturns\ a\ decimal\ value\;\ you\ have\ to\ use\ `\[format\]`\ if\ you\ want\ it\ in\ some\nother\ base.\n\n\[RJM\]:\ I\ came\ around\ this\ as\ I\ was\ going\ to\ do\ calculus\ on\ a\ four-digit\nformatted\ number\ in\ an\ entry\ field.\ I\ had\ to\ apply\ `scan\ \$var\ %d`\ to\ get\ rid\nformatted\ number\ in\ an\ entry\ field.\ I\ had\ to\ apply\ ''scan\ \$var\ %d''\ to\ get\ rid\nlanguage...\n\n\n`expr`\ uses\ floating\ point\ arithmetic,\ so\ strings\ representing\ decimal\nfractions\ that\ don't\ have\ a\ precise\ floating-point\ representation\ will\ be\ given\nto\ a\ close-enough\ representation.\ \ In\ the\ following\ example,\ `36.37`\ gets\ a\nto\ a\ close-enough\ representation.\ \ In\ the\ following\ example,\ \"36.37\"\ gets\ a\n\n======\nexpr\ \{int(36.37*100)\}\n======\n\nIf\ that\ value\ is\ subsequently\ used\ as\ a\ string,\ it\ becomes\ necessary\ to\ somehow\nconvert\ it.\ \ Over\ the\ years,\ the\ default\ string\ conversion\ has\ varied.\ \ For\ Tcl\nversion\ 8.5.13,\ it\ looks\ like\n\n======none\n3636.9999999999995\n======\n\n\[RS\]\ points\ out\ that\ version\ 8.4.9\ provided\ the\ following\ results,\ and\ that\nthat\ braced\ or\ not,\ `expr`\ returns\ the\ same\ (string\ rep\ of)\ double\ as\ well\nas\ integer,\ so\ the\ issue\ of\ bracing\ one's\ expressions\ is\ not\ relevant\ to\ the\nissue\ of\ floating-point\ to\ string\ conversion.\n\n======none\n%\ expr\ 36.37*100\n3637.0\ \;#--\ good\ enough...\n%\ expr\ \{36.37*100\}\n3637.0\ \;#--\ the\ same\n%\ expr\ \{int(36.37*100)\}\n3636\ \ \ \;#--\ Hmm\n%\ expr\ int(36.37*100)\n3636\ \ \ \;#--\ the\ same\n%\ info\ pa\n8.4.9\n======\n\nOne\ way\ to\ get\ `3637`\ would\ be\ to\ use\ `round()`:\nOne\ way\ to\ get\ \"3637\"\ would\ be\ to\ use\ `round()`:\n======\nexpr\ \{round(36.37*100)\}\n======\n\n`\[format\]`\ can\ also\ be\ useful,\ but\ the\ main\ point\ is\ to\ remain\naware\ of\ the\ context\ and\ decide\ if\ and\ how\ to\ use\ floating-point\ operations.\n\n\[LV\]:\ \ My\ response\ on\ \[comp.lang.tcl\]\ was\ that\ I\ thought\ it\ was\ a\ shame\nthat\ `expr`\ (or\ perhaps\ it\ is\ Tcl)\ didn't\ use\ the\ same\ mechanism\ for\nboth\ calculations\ of\ 36.37\ *\ 100\ \;\ that\ way,\ the\ results\ would\ at\ least\nbe\ consistent.\ \ Even\ if\ they\ were\ consistently\ '''wrong''',\ one\ would\nbe\ able\ to\ at\ least\ to\ live\ within\ the\ ''law\ of\ least\ surprise''.\nAs\ it\ is,\ until\ one\ experiments,\ one\ won't\ know\ which\ way\ that\ Tcl\nis\ going\ to\ ''round''\ results.\n\n\[EPSJ\]:\ \ This\ may\ be\ a\ side\ effect\ of\ the\ IEEE\ floating\ point\ standard.\ This\ is\ndone\ in\ hardware\ to\ guarantee\ the\ convergence\ in\ the\ case\ of\ a\ series\ of\ math\nalgorithms.\ The\ rule\ is\ that\ the\ mantissa\ of\ a\ floating\ point\ number\ must\ be\nrounded\ to\ the\ nearest\ even\ number.\ As\ 36.37\ cannot\ be\ represented\ exactly\ in\nfloat\ point\ it\ ends\ up\ being\ a\ small\ fraction\ below\ the\ intended\ number.\ On\ the\nother\ side\ 36.38\ moves\ on\ the\ other\ direction.\ Look\ the\ following\ result:\n\n======none\n()\ 60\ %\ expr\ int(36.380*100)\n3638\n()\ 61\ %\ expr\ int(36.370*100)\n3636\n======\n\nx86\ floating\ point\ hardware\ allows\ this\ to\ be\ configurable\ to\ nearest\ even,\nnearest\ odd,\ and\ a\ few\ more\ options.\ But\ usually\ nearest\ even\ is\ the\ default.\nThe\ result\ may\ seem\ inconsistent,\ but\ it\ is\ intentional.\n\n\n**\ pow()\ vs\ **\n**\ pow()\ vs\ **\ **\n\[LES\]\ 2005-07-23:\n\n======none\n%\ expr\ pow(5,6)\n15625.0\n\n%\ expr\ 5**6\n15625\n======\n\nTwo\ syntaxes,\ two\ slightly\ different\ results.\ Is\ that\ intentional?\n\n\[RS\]:\ Yes.\ \ While\ `pow()`\ always\ goes\ for\ double\ logarithms,\ `**`\ tries\ to\ do\ninteger\ exponentiation\ where\ possible.\n\n\n**\ Precision\ **\n\n\[davou\]:\ What\ is\ the\ precision\ of\ functions\ in\ `expr`,\ and\ how\ can\ it\ be\nexpanded\ upon?\n\n\[Lars\ H\]:\ That's\ generally\ determined\ by\ the\ \[C\]\ library\ functions\ that\nimplement\ them.\ It\ depends\ on\ where\ (and\ against\ what)\ Tcl\ is\ compiled.\ \ For\nreal\ numbers,\ that\ means\ '''double'''s,\ which\ are\ floating-point\ numbers\ of\ntypically\ about\ 17\ decimal\ digits\ precision\ (but\ how\ many\ of\ these\ are\ correct\nvaries\ between\ functions\ and\ platforms).\ For\ integers\ Tcl\ has\ traditionally\nused\ '''long'''s,\ which\ in\ most\ cases\ means\ 32-bit\ two's\ complement\ integers\n(`\$tcl_platform(wordSize)`\ tells\ you\ the\ actual\ number\ of\ bytes),\ but\ as\ of\ Tcl\n8.5,\ it\ supports\ (almost)\ arbitrarily\ large\ integers\ (\[googol\ magnitude\]\ is\ no\nproblem\ anymore,\ whereas\ googolplex\ magnitude\ wouldn't\ fit\ in\ the\ computer\nmemory\ anyway).\ As\ for\ extending\ what\ the\ core\ provides,\ \[tcllib\]\ provides\n\[math::bignum\]\ and\ \[math::bigfloat\].\n\n\n**\ \[Nan\]\ and\ \[Inf\]\ **\n\n\nAt\ least\ as\ of\ Tcl\ 8.5,\ \[NaN\]\ and\ \[Inf\]\ are\ potential\ values\ returning\ from\n`expr`.\n\n\[Philip\ Smolen\]\ I've\ never\ seen\ expr\ return\ NaN.\ \ I\ wish\ it\ would!\n\n======\n\[phil@harvey\ ~\]\$\ tclsh8.6\ \n%\ expr\ sqrt(-1)\ndomain\ error:\ argument\ not\ in\ valid\ range\n%\ ::tcl::mathfunc::sqrt\ -1\n-NaN\n%\ info\ patchlevel\n8.6.4\n%\ expr\ \{Inf+1\}\nInf\n%\ \n======\n\n\n======\n\[phil@becca\ ~\]\$\ tclsh8.5\ \n%\ expr\ sqrt(-1)\ndomain\ error:\ argument\ not\ in\ valid\ range\n%\ ::tcl::mathfunc::sqrt\ -1\n-NaN\n%\ info\ patchlevel\n8.5.14\n%\ expr\ \{Inf+1\}\nInf\n%\ \n======\n\n**\ Interactions\ with\ \[locale\]\ **\n\n**\ Interactions\ with\ `\[locale\]`\ **\nparsing\ of\ decimals\ in\ `expr`\ may\ be\ hampered\ by\ \[locale\]\ -\ you\ might\ get\n\n\n\n\n`expr`\ concatenates\ its\ arguments\ into\ an\ expression.\ \ Consider\ the\ following\n`expr`\ resolves\ variables\ in\ the\ context\ of\ its\ caller,\ and\ each\ variable\nvalue\ becomes\ exactly\ one\ operand\ in\ the\ expression.\ \ Consider\ the\ following:\n======\nexpr\ 5\ >\ \{\}\ \;#\ ->\ missing\ operand\ at\ _@_\nset\ color2\ green\n\nexpr\ \{\$color1\}\ eq\ \{\$color2\}\ \;#\ 1\n\nConcatenated,\ the\ arguments\ form\ the\ script,\ `green\ eq\ green`,\ in\ which\ the\ two\nBut\ if\ the\ arguments\ are\ not\ bracketed,\ it\ is\ a\ syntax\ error:\nAnother\ example\ illustrating\ the\ same\ point:\n======\n#wrong\nexpr\ \$color1\ eq\ \$color2\n======\n\n======none\ninvalid\ bareword\ \"green\"\nin\ expression\ \"green\ eq\ green\"\;\nshould\ be\ \"\$green\"\ or\ \"\{green\}\"\ or\ \"green(...)\"\ or\ ...\n======\n\nThis\ is\ because\ in\ `expr`\ syntax,\ strings\ should\ be\ quoted\ or\ bracketed\n\n\n======\nset\ a\ abc\nset\ a\ \"abc\"\nexpr\ \$a\ in\ \$b\n#\ invalid\ bareword\ \"abc\"\n#\ in\ expression\ \"abc\ in\ 123\ abcd\ xyz\ lmnop\"\;\n#\ should\ be\ \"\$abc\"\ or\ \"\{abc\}\"\ or\ \"abc(...)\"\ or\ ...\n\nexpr\ \{\$a\ in\ \$b\}\ \;#->\ 0\nexpr\ \{\$a\ in\ \$b\}\n#\ 0\nexpr\ \{\$a\ ni\ \$b\}\ \;#->\ 1\nexpr\ \{\$a\ ni\ \$b\}\n#\ 1\n\n======\n%\ expr\ \$a\ eq\ \"foo\"\ ?\ true\ :\ false\n%\ expr\ \$a\ ==\ \"foo\"\ ?\ true\ :\ false\n%\ expr\ \{\$a\ eq\ \"foo\"\ ?\ true\ :\ false\}\n%\ expr\ \{\$a\ ==\ \"foo\"\ ?\ true\ :\ false\}\n======\n\n\n\nWhen\ exactly\ one\ unconcatenated\ value\ is\ passed\ to\ `expr`,\ the\ argument\ can\ be\n`expr`\ is\ much\ more\ performant\ when\ it\ has\ exactly\ one\ argument.\ \ The\nargument\ must\ either\ be\ brace-quoted\ or\ be\ a\ single\ variable\ substitution,\nsince\ this\ allows\ byte-compilation.\n\n\[AMG\]:\ More\ precisely,\ the\ argument\ must\ not\ contain\ multiple\ substitutions\ or\nbe\ the\ concatenation\ of\ substitutions\ and\ literal\ text.\ \ The\ goal\ is\ for\ there\nIf\ `expr`\ has\ to\ concatenate\ its\ arguments\ (i.e.\ it\ is\ passed\ more\ than\ one\nargument),\ or\ if\ \[Tcl\]\ has\ to\ concatenate\ the\ results\ of\ multiple\ substitutions\nand\ literal\ substrings,\ then\ the\ math\ expression\ will\ be\ in\ a\ temporary\ Tcl_Obj\nwhich\ must\ be\ regenerated\ every\ time\ `expr`\ is\ called.\n\n'''Fast:'''\n\n======\nexpr\ \{2\ +\ 2\}\ \ \ \ \ \ \ \ \ \;\ #\ Preferred\nexpr\ 2+2\ \ \ \ \ \ \ \ \ \ \ \ \ \;\ #\ Valid\ but\ lazy\ (1)\nexpr\ \"2\ +\ 2\"\ \ \ \ \ \ \ \ \ \;\ #\ Valid\ but\ not\ preferred\ (2)\nexpr\ 2\\\ +\\\ 2\ \ \ \ \ \ \ \ \ \;\ #\ Valid\ but\ ugly\ (3)\nexpr\ \$expression\ \ \ \ \ \;\ #\ Valid\nexpr\ \[expression\]\ \ \ \ \;\ #\ Valid\n======\n\n(1)\ This\ style\ is\ easy\ to\ type\ and\ is\ fine\ for\ interactive\ use,\ but\ you\ will\ lose\ performance\ (and\ correctness\ and\ security)\ if\ you\ use\ this\ notation\ in\ combination\ with\ variable\ and\ script\ substitutions.\n\n(2)\ Same\ problems\ as\ (1).\ \ Use\ braces\ instead.\n\n(3)\ Same\ problems\ as\ (1),\ plus\ you\ might\ forget\ a\ backslash\ before\ a\ space,\ thereby\ forcing\ `expr`\ to\ concatenate\ its\ arguments.\n\n'''Slow:'''\n\n======\nexpr\ 2\ +\ 2\ \ \ \ \ \ \ \ \ \ \ \;\ #\ Slow\ since\ \[expr\]\ must\ concatenate\ its\ arguments\nexpr\ 2\ +\ \$x\ \ \ \ \ \ \ \ \ \ \;\ #\ Slow\ since\ \[expr\]\ must\ concatenate\ its\ arguments,\ also\ unsafe\nexpr\ 2+\$x\ \ \ \ \ \ \ \ \ \ \ \ \;\ #\ Slow\ since\ Tcl\ must\ concatenate\ to\ determine\ argument,\ also\ unsafe\nexpr\ \"2\ +\ \$x\"\ \ \ \ \ \ \ \ \;\ #\ Slow\ since\ Tcl\ must\ concatenate\ to\ determine\ argument,\ also\ unsafe\n======\n\n\n\n\n\[AMG\]:\ The\ security\ problems\ of\ unbraced\ `expr`essions\ are\ very\ similar\ to\n\[SQL\]\ \[injection\ attack%|%injection\ attacks\].\ \ Notice\ how\ \[sqlite\]'s\ \[Tcl\]\ binding\ does\ its\ own\n\[SQL\]\ injection\ attacks.\ \ Notice\ how\ \[sqlite\]'s\ \[Tcl\]\ binding\ does\ its\ own\nthis\ problem\ as\ well\ because\ the\ default\ is\ to\ apply\ multiple\ passes\ of\ninterpretation.\n\nSee\ also\ \[double\ substitution\].\nSee\ also\ \[double\ substitution\]\n\n\n\n\[AMG\]:\ The\ above\ speed\ and\ security\ concerns\ also\ apply\ to\ `\[if\]`,\n`\[for\]`,\ and\ `\[while\]`\ since\ they\ share\ the\ expression\ engine\ with\n`expr`.\n\nAdditionally,\ `\[for\]`\ and\ `\[while\]`\ really\ do\ need\ their\ expressions\ to\nbe\ braced.\ \ In\ order\ for\ the\ loop\ to\ execute\ a\ nonzero\ but\ finite\ number\ of\ntimes,\ the\ expression's\ value\ must\ not\ be\ constant\;\ but\ if\ they're\ not\ braced,\ntheir\ value\ is\ determined\ before\ the\ loop\ can\ begin.\n\nThe\ exception\ is\ when\ the\ ''expression''\ (as\ opposed\ to\ value)\ is\ contained\ in\na\ variable,\ in\ which\ case\ it\ must\ not\ be\ brace-quoted,\ or\ else\ the\ command\nwould\ try\ to\ treat\ the\ expression\ as\ a\ (string)\ value\ and\ almost\ certainly\ fail\nto\ convert\ it\ to\ a\ boolean\ value.\n\n\[DKF\]:\ But\ even\ then,\ for\ `if`,\ `for`\ and\ `while`\ you\ must\ still\ brace\ the\ expression\ to\ avoid\ being\ stuck\ in\ the\ compilation\ slow\ lane.\ Putting\ an\ `expr`\ inside\ can\ help:\n======\nset\ ex\ \{\$f\ >\ 42\}\nwhile\ \{\[expr\ \$ex\]\}\ \{\n\ \ \ \ puts\ \"This\ is\ the\ body:\ f\ is\ now\ \[incr\ f\ -1\]\"\n\}\n======\n\n----\n\nConsider\ what\ would\ happen\ if\ this\ script\ were\ actually\ working\ with\ user\ninput:\n\n======\n#DON'T\ EXECUTE\ THIS\ SCRIPT!!!\nset\ x\ \{\[exec\ format\ C:\\\\\]\}\nset\ j\ \{\[puts\ Sucker!\]\}\n#C:\\\ get\ formatted\ in\ the\ next\ command\nset\ k\ \[expr\ \$x\ /\ \$j.\]\n======\n\nOn\ the\ other\ hand,\n\n======\nset\ k\ \[expr\ \{\ \$x\ /\ double(\$j)\ \}\]\n======\n\ngives\ a\ much\ more\ reasonable\ result:\n\n======none\nargument\ to\ math\ function\ didn't\ have\ numeric\ value\n\ \ \ while\ executing\n\"expr\ \{\ \$x\ /\ double(\$y)\ \}\"\n\ \ \ invoked\ from\ within\n\"set\ k\ \[expr\ \{\ \$x\ /\ double(\$y)\ \}\]\n\"\n\ \ \ \ (file\ \"foo.tcl\"\ line\ 3)\n\n======\n\n\n\n\nUnless\ you\ know\ exactly\ what\ you\ are\ doing,\ unbraced\ expressions\ are\ not\nrecommended.\ \ Nevertheles...\n\nWith\ unbraced\ expressions,\ `.`\ (`\\x2e`)\ can\ be\ appended\ to\ a\ variable\ to\ get\ `expr`\nWith\ unbraced\ expressions,\ a\ \".\"\ can\ be\ appended\ to\ a\ variable\ to\ get\ `expr`\n\n======\nset\ x\ 1\;\ set\ j\ 2\n\n#\ works\ (but\ don't\ do\ this)\nexpr\ \$x/\$j.\n\n#an\ accepted\ way\ to\ do\ it\nexpr\ \{double(\$x)/\$j\}\n\n#\ error:\ syntax\ error\ in\ expression\ \"\$x/\$j.\"\ \ (expr\ parser)\nexpr\ \{\$x/\$j.\}\n======\n\nIt's\ faster,\ too:\n\n======\nset\ script1\ \{\n\ \ \ set\ x\ 1\n\ \ \ set\ j\ 2\n\ \ \ set\ k\ \[expr\ \$x\ /\ \$j.\]\n\}\nset\ script2\ \{\n\ \ \ set\ x\ 1\n\ \ \ set\ j\ 2\n\ \ \ set\ k\ \[expr\ \{\ \$x\ /\ double(\$j)\ \}\]\n\}\nforeach\ v\ \{script1\ script2\}\ \{\nforeach\ v\ \{\ script1\ script2\ \}\ \{\n\}\n\n#script1:\ 38\ microseconds\ per\ iteration\n#script2:\ 9\ microseconds\ per\ iteration\n\n#\[pyk\]\ 2012-11-28:\ what\ a\ difference\ a\ few\ years\ makes\ (an\ \"old\"\ 3.06Ghz\ Intel\ Core\ 2\ Duo):\n#script1:\ 4.4767364\ microseconds\ per\ iteration\n#script2:\ 0.7374299\ microseconds\ per\ iteration\n======\n\n----\n\n\[RS\]:\ This\ was\ just\ to\ demonstrate\ the\ differences\ between\ the\ regular\ Tcl\nparser\ and\ the\ parser\ for\ `expr`',\ not\ recommended\ practice.\ Another\ example\ is\nsubstitution\ of\ operators:\n\n======\nset\ op\ +\nexpr\ 4\ \$op\ 5\n9\nexpr\ \{4\ \$op\ 5\}\nsyntax\ error\ in\ expression\ \"4\ \$op\ 5\"\n======\n\nSee\ the\ `\[for\]`\ page\ on\ a\ case\ where\ that\ helped.\n\n**\ Bytecode\ compilation\ and\ performance\ **\n\n\[AMG\]:\ When\ expr's\ argument\ is\ properly\ braced,\ the\ expression\ can\ be\ bytecoded\ for\ significant\ performance\ gains.\ However,\ the\ performance\ is\ not\ always\ quite\ as\ good\ as\ one\ would\ hope.\ Use\ \[tcl::unsupported::disassemble\]\ to\ see\ this\ in\ action:\n\n======none\n%\ tcl::unsupported::disassemble\ script\ \{expr\ \{4\ /\ 3.\ *\ acos(-1)\ *\ \$r\ **\ 3\}\}\nByteCode\ 0x00000000025FADB0,\ refCt\ 1,\ epoch\ 16,\ interp\ 0x00000000026365B0\ (epoch\ 16)\n\ \ Source\ \"expr\ \{4\ /\ 3.\ *\ acos(-1)\ *\ \$r\ **\ 3\}\"\n\ \ Cmds\ 1,\ src\ 34,\ inst\ 17,\ litObjs\ 5,\ aux\ 0,\ stkDepth\ 3,\ code/src\ 0.00\n\ \ Commands\ 1:\n\ \ \ \ \ \ 1:\ pc\ 0-15,\ src\ 0-33\n\ \ Command\ 1:\ \"expr\ \{4\ /\ 3.\ *\ acos(-1)\ *\ \$r\ **\ 3\}\"\n\ \ \ \ (0)\ push1\ 0\ \ \ \ \ \ \ \ \ #\ \"1.3333333333333333\"\n\ \ \ \ (2)\ push1\ 1\ \ \ \ \ \ \ \ \ #\ \"tcl::mathfunc::acos\"\n\ \ \ \ (4)\ push1\ 2\ \ \ \ \ \ \ \ \ #\ \"-1\"\n\ \ \ \ (6)\ invokeStk1\ 2\ \n\ \ \ \ (8)\ mult\ \n\ \ \ \ (9)\ push1\ 3\ \ \ \ \ \ \ \ \ #\ \"r\"\n\ \ \ \ (11)\ loadStk\ \n\ \ \ \ (12)\ push1\ 4\ \ \ \ \ \ \ \ \ #\ \"3\"\n\ \ \ \ (14)\ expon\ \n\ \ \ \ (15)\ mult\ \n\ \ \ \ (16)\ done\ \n======\n\nThis\ shows\ that\ `4\ /\ 3.`\ is\ precomputed\ to\ `1.3333333333333333`,\ but\ `acos(-1)`\ is\ not\ precomputed\ to\ `3.141592653589793`.\ While\ it\ would\ seem\ ideal\ to\ fold\ the\ constants\ together\ into\ `4.1887902047863905`,\ doing\ so\ would\ skip\ invoking\ `\[tcl::mathfunc\]::\[acos\]`,\ which\ might\ have\ a\ `\[trace\]`\ on\ it.\ Tcl\ optimizations\ always\ favor\ correctness\ over\ speed,\ so\ this\ shortcut\ is\ not\ available.\nThis\ shows\ that\ \"4\ /\ 3.\"\ is\ precomputed\ to\ \"1.3333333333333333\",\ but\ \"acos(-1)\"\ is\ not\ precomputed\ to\ \"3.141592653589793\".\ While\ it\ would\ seem\ ideal\ to\ fold\ the\ constants\ together\ into\ \"4.1887902047863905\",\ doing\ so\ would\ skip\ invoking\ `\[tcl::mathfunc\]::\[acos\]`,\ which\ might\ have\ a\ `\[trace\]`\ on\ it.\ Tcl\ optimizations\ always\ favor\ correctness\ over\ speed,\ so\ this\ shortcut\ is\ not\ available.\nHere's\ the\ above\ again,\ but\ with\ local\ variables\ which\ provide\ a\ large\ speed\ boost\ by\ avoiding\ looking\ up\ the\ variable\ by\ name:\n\n======none\n%\ tcl::unsupported::disassemble\ lambda\ \{\{\}\ \{expr\ \{4\ /\ 3.\ *\ acos(-1)\ *\ \$r\ **\ 3\}\}\}\nByteCode\ 0x00000000027A1080,\ refCt\ 1,\ epoch\ 16,\ interp\ 0x00000000026E65B0\ (epoch\ 16)\n\ \ Source\ \"expr\ \{4\ /\ 3.\ *\ acos(-1)\ *\ \$r\ **\ 3\}\"\n\ \ Cmds\ 1,\ src\ 34,\ inst\ 16,\ litObjs\ 4,\ aux\ 0,\ stkDepth\ 3,\ code/src\ 0.00\n\ \ Proc\ 0x00000000026A8620,\ refCt\ 1,\ args\ 0,\ compiled\ locals\ 1\n\ \ \ \ \ \ slot\ 0,\ scalar,\ \"r\"\n\ \ Commands\ 1:\n\ \ \ \ \ \ 1:\ pc\ 0-14,\ src\ 0-33\n\ \ Command\ 1:\ \"expr\ \{4\ /\ 3.\ *\ acos(-1)\ *\ \$r\ **\ 3\}\"\n\ \ \ \ (0)\ push1\ 0\ \ \ \ \ \ \ \ \ #\ \"1.3333333333333333\"\n\ \ \ \ (2)\ push1\ 1\ \ \ \ \ \ \ \ \ #\ \"tcl::mathfunc::acos\"\n\ \ \ \ (4)\ push1\ 2\ \ \ \ \ \ \ \ \ #\ \"-1\"\n\ \ \ \ (6)\ invokeStk1\ 2\ \n\ \ \ \ (8)\ mult\ \n\ \ \ \ (9)\ loadScalar1\ %v0\ \ \ \ \ \ \ \ \ #\ var\ \"r\"\n\ \ \ \ (11)\ push1\ 3\ \ \ \ \ \ \ \ \ #\ \"3\"\n\ \ \ \ (13)\ expon\ \n\ \ \ \ (14)\ mult\ \n\ \ \ \ (15)\ done\ \n======\n\n(For\ disassembly\ readouts,\ it's\ not\ necessary\ to\ list\ the\ variables\ as\ arguments\ to\ the\ lambda.\ They'll\ be\ assigned\ slots\ in\ the\ compiled\ locals\ table\ either\ way.\ You're\ not\ actually\ running\ the\ code,\ so\ it\ doesn't\ matter\ if\ the\ variable\ exists.)\n\nCommon\ subexpressions\ cannot\ be\ optimized\ because\ this\ would\ bypass\ some\ potential\ traces\ on\ variable\ access\ and\ procedure\ invocation.\ If\ `expr`\ could\ know\ in\ advance\ that\ particular\ procedures\ and\ variables\ don't\ have\ traces,\ it\ would\ have\ greater\ freedom\ to\ perform\ common\ subexpression\ elimination.\ Knowing\ that\ a\ procedure\ is\ a\ pure\ function\ (its\ result\ depends\ only\ on\ its\ arguments),\ plus\ knowing\ that\ its\ definition\ will\ not\ change\ throughout\ the\ execution\ of\ the\ program,\ would\ let\ expr\ treat\ `acos(-1)`\ as\ a\ constant.\nCommon\ subexpressions\ cannot\ be\ optimized\ because\ this\ would\ bypass\ some\ potential\ traces\ on\ variable\ access\ and\ procedure\ invocation.\ If\ expr\ could\ know\ in\ advance\ that\ particular\ procedures\ and\ variables\ don't\ have\ traces,\ it\ would\ have\ greater\ freedom\ to\ perform\ common\ subexpression\ elimination.\ Knowing\ that\ a\ procedure\ is\ a\ pure\ function\ (its\ result\ depends\ only\ on\ its\ arguments),\ plus\ knowing\ that\ its\ definition\ will\ not\ change\ throughout\ the\ execution\ of\ the\ program,\ would\ let\ expr\ treat\ acos(-1)\ as\ a\ constant.\nNow\ rearrange\ the\ expression\ to\ put\ the\ division\ at\ the\ end.\ Algebraically,\ this\ should\ produce\ an\ identical\ result.\ But\ because\ of\ potential\ floating\ point\ precision\ issues\ (non-commutativity\ of\ operations),\ Tcl\ must\ play\ it\ safe\ and\ do\ the\ operations\ in\ the\ order\ specified:\n\n======none\n%\ tcl::unsupported::disassemble\ script\ \{expr\ \{4\ *\ acos(-1)\ *\ \$r\ **\ 3\ /\ 3.\}\}\nByteCode\ 0x00000000025F91B0,\ refCt\ 1,\ epoch\ 16,\ interp\ 0x00000000026365B0\ (epoch\ 16)\n\ \ Source\ \"expr\ \{4\ *\ acos(-1)\ *\ \$r\ **\ 3\ /\ 3.\}\"\n\ \ Cmds\ 1,\ src\ 34,\ inst\ 20,\ litObjs\ 6,\ aux\ 0,\ stkDepth\ 3,\ code/src\ 0.00\n\ \ Commands\ 1:\n\ \ \ \ \ \ 1:\ pc\ 0-18,\ src\ 0-33\n\ \ Command\ 1:\ \"expr\ \{4\ *\ acos(-1)\ *\ \$r\ **\ 3\ /\ 3.\}\"\n\ \ \ \ (0)\ push1\ 0\ \ \ \ \ \ \ \ \ #\ \"4\"\n\ \ \ \ (2)\ push1\ 1\ \ \ \ \ \ \ \ \ #\ \"tcl::mathfunc::acos\"\n\ \ \ \ (4)\ push1\ 2\ \ \ \ \ \ \ \ \ #\ \"-1\"\n\ \ \ \ (6)\ invokeStk1\ 2\ \n\ \ \ \ (8)\ mult\ \n\ \ \ \ (9)\ push1\ 3\ \ \ \ \ \ \ \ \ #\ \"r\"\n\ \ \ \ (11)\ loadStk\ \n\ \ \ \ (12)\ push1\ 4\ \ \ \ \ \ \ \ \ #\ \"3\"\n\ \ \ \ (14)\ expon\ \n\ \ \ \ (15)\ mult\ \n\ \ \ \ (16)\ push1\ 5\ \ \ \ \ \ \ \ \ #\ \"3.\"\n\ \ \ \ (18)\ div\ \n\ \ \ \ (19)\ done\ \n======\n\nBack\ to\ common\ subexpression\ elimination:\ It\ may\ seem\ that\ the\ solution\ is\ for\ the\ programmer\ to\ manually\ precompute\ common\ subexpressions\ and\ reference\ their\ values\ via\ variables.\ This\ generally\ helps,\ so\ long\ as\ the\ subexpressions\ aren't\ too\ simple,\ but\ you\ must\ use\ local\ variables\ or\ else\ performance\ will\ suffer:\n\n======\n%\ proc\ a\ \{x\}\ \{expr\ \{cos(\$x\ *\ acos(-1))\ +\ sin(\$x\ *\ acos(-1))\}\}\n%\ proc\ b\ \{x\}\ \{set\ y\ \[expr\ \{\$x\ *\ acos(-1)\}\]\;\ expr\ \{cos(\$y)\ +\ sin(\$y)\}\}\n%\ proc\ c\ \{x\}\ \{set\ ::y\ \[expr\ \{\$x\ *\ acos(-1)\}\]\;\ expr\ \{cos(\$::y)\ +\ sin(\$::y)\}\}\n%\ set\ x\ 12.3\n%\ time\ \{a\ \$x\}\ 1000000\n1.536581\ microseconds\ per\ iteration\n%\ time\ \{b\ \$x\}\ 1000000\n1.333106\ microseconds\ per\ iteration\n%\ time\ \{c\ \$x\}\ 1000000\n1.994305\ microseconds\ per\ iteration\n======\n\n\n\n\nIn\ \[http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/f873d6fab9f0e304%|%Embedded\ vs.\ separate\ commands\],\ 1992-12-38,\ \[JO\]\ published\ the\ voting\ results\ 37:8\ in\ favor\ of\ embedded\ functions()\ vs.\ separate\ \[\[commands\]\]\n\n\n**\ (Tcl\ 8.4\ and\ older)\ 32-bit\ integer\ limitations\ **\n\nAddition\n\n======none\n%\ expr\ (1<<31)-1\n2147483647\n\n%\ expr\ 2147483647\ +\ 2147483647\n-2\n======\n\nMultiplication\n\n======none\n%\ expr\ sqrt((1<<31)-1)\n46340.9500011\n\nexpr\ 46341*46341\n-2147479015\n======\n\nThese\ are\ results\ of\ Tcl\ 8.4\ and\ older\ versions\ using\ a\ 32-bit\ representation\nfor\ integers.\n\nTcl\ 8.5\ features\ abritrary-precision\ integers.\ \ See\n\[http://www.tcl.tk/cgi-bin/tct/tip/237.html%|%TIP\ #237\].\n\n**\ Suggestion\ to\ reparse\ expr\ variables\ **\n\nexpressions\ in\ variable\ values\ would\ interpreted\ as\ such\n\n\[RS\]\ 2003-04-24:\ Here's\ a\ tiny\ wrapper\ for\ friends\ of\ infix\ assignment:\n\n======none\nproc\ let\ \{var\ =\ args\}\ \{\n\ \ \ \ uplevel\ 1\ set\ \$var\ \\\[expr\ \$args\\\]\n\}\ \;#RS\n======\n\n======none\n%\ let\ i\ =\ 1\n1\n%\ let\ j\ =\ \$i\ +\ 1\n2\n%\ let\ k\ =\ \{\$i\ +\ \$j\}\n3\n======\n\n======\nset\ y\ 2*3\;\ puts\ \[expr\ \$y+0\]\ \;#\ ==>\ 6\n======\n\n\[AM\]:\ The\ problem\ with\ variables\ whose\ values\ are\ actually\ expressions\ is\ that\nthey\ change\ the\ whole\ expression\ in\ which\ they\ are\ used.\ The\ performance\ gain\nfor\ caching\ the\ parsed\ expression\ will\ then\ be\ lost.\n\n\[AMG\]:\ This\ reopens\ the\ door\ to\ all\ the\ security,\ performance,\ and\ correctness\ problems\ solved\ by\ bracing\ one's\ expressions.\n**\ Unsuitability\ of\ expr\ for\ time\ offset\ calculations\ **\n\n\[Wookie\]:\ \ I\ had\ some\ trouble\ recently\ using\ `expr`\ to\ calculate\ time\noffsets.\ I\ had\ 2\ time\ stamps\ in\ the\ form\ hh:mm\n\nSo\ I\ had\ 4\ variables\ h1,\ m1,\ h2,\ m2\ and\ one\ of\ my\ `expr`\ functions\ was\n\n======\nset\ result\ \[expr\ \{\$m1\ +\ \$m2\}\]\n======\n\nAs\ many\ of\ you\ may\ be\ thinking,\ you\ fool!\ what\ about\ 08\ and\ 09,\ which\ will\ get\ntreated\ as\ invalid\ octal.\ So\ after\ some\ grumbling\ I\ thought\ okay\ so\ I\ have\ to\ntrimleft\ them.\ Bit\ verbose\ but\ who\ cares:\n\n======\nset\ m1\ \[string\ trimleft\ \$m1\ 0\]\nset\ m2\ \[string\ trimleft\ \$m2\ 0\]\nset\ result\ \[expr\ (\$m1\ +\ \$m2)\]\n======\n\nNow\ what\ could\ possibly\ go\ wrong\ with\ that...\ well\ obviously\ 00\ becomes\ the\nempty\ string,\ which\ causes\ unexpected\ closed\ parameter\ in\ the\ `expr`ession.\nSo\ now\ I\ have\ to\ check\ for\ the\ empty\ string.\ So...\n\n======\nset\ m1\ \[string\ trimleft\ \$m1\ 0\]\nif\ \{\$m1==\{\}\}\ \{set\ m1\ 0\}\n\nset\ m2\ \[string\ trimleft\ \$m2\ 0\]\nif\ \{\$m2==\{\}\}\ \{set\ m2\ 0\}\n\nset\ result\ \[expr\ \{\$m1\ +\ \$m2\}\]\n======\n\n...\ and\ then\ repeat\ it\ for\ the\ hours.\ It\ all\ seemed\ very\ clumsy.\ So\ I\ came\ up\nwith\ this,\ which\ may\ solve\ many\ of\ the\ conversion\ issues\ in\ this\ section.\n\n======\nscan\ \"\$h1:\$m1\ \$h2:\$m2\"\ \"%d:%d\ %d:%d\"\ h1\ m1\ h2\ m2\nset\ result\ \[expr\ \{\$m1\ +\ \$m2\}\]\n======\n\nAll\ the\ conversions\ to\ int\ have\ been\ done\ and\ leading\ 0's\ have\ been\ stripped\nand\ returns\ 0\ if\ the\ value\ is\ all\ 0s.\ This\ works\ for\ float\ and\ probably\ double\n(though\ I've\ not\ tried).\ Can\ anyone\ see\ any\ problems\ with\ this\ approach?\n\n\[glennj\]:\ No,\ `\[scan\]`\ is\ definitely\ the\ way\ to\ parse\ numbers\ out\ of\ dates\nand\ times.\ \ However,\ for\ date\ arithmetic,\ nothing\ beats\ `\[clock\]`.\n\n======\n#\ adding\ a\ delta\ to\ a\ time\nset\ h1\ 12\;\ set\ m1\ 45\nset\ h2\ 3\;\ set\ m2\ 30\nclock\ format\ \[clock\ add\ \[clock\ scan\ \"\$h1:\$m1\"\ -format\ \"%H:%M\"\]\ \$h2\ hours\ \$m2\ minutes\]\ -format\ %T\ \;#\ ==>\ 16:15:00\n======\n\nWhat\ are\ you\ trying\ to\ do\ with\ your\ two\ times?\n\n} CALL {my revision expr} CALL {::oo::Obj1196143 process revision/expr} CALL {::oo::Obj1196141 process}

-errorcode

NONE

-errorinfo

Unknow state transition: LINE -> END
    while executing
"error $msg"
    (class "::Wiki" method "render_wikit" line 6)
    invoked from within
"my render_$default_markup $N $C $mkup_rendering_engine"
    (class "::Wiki" method "render" line 8)
    invoked from within
"my render $name $C"
    (class "::Wiki" method "revision" line 31)
    invoked from within
"my revision $page"
    (class "::Wiki" method "process" line 56)
    invoked from within
"$server process [string trim $uri /]"

-errorline

4