Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/Brace+your+expr-essions?V=31
QUERY_STRINGV=31
CONTENT_TYPE
DOCUMENT_URI/revision/Brace+your+expr-essions
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.69.58.78
REMOTE_PORT60416
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR3.149.241.186
HTTP_CF_RAY88d9a6d8398a10ee-ORD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTMozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
HTTP_REFERERhttps://tcl.wiki/revision/Brace+your+expr%2Dessions?V=31
HTTP_CF_CONNECTING_IP3.149.241.186
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 {Brace your expr-essions} **\ Description\ **\n\n\[KBK\]\ closed\ a\ follow-up\ to\ \[the\ comp.lang.tcl\ newsgroup\]\ with\ the\ advice\ that,\n\"Also,\ it's\ important\ always,\ always\ to\ brace\ your\ \[expr\]essions.\ \ Don't\ do\n\n======\nset\ a\ \[expr\ \$b\ /\ \$c\]\n======\n\nbut\ rather\n\n======\nset\ a\ \[expr\ \{\ \$b\ /\ \$c\ \}\]\n======\n\nOtherwise,\ your\ variables\ may\ undergo\ unexpected\ conversions\nnumeric\ ->\ string\ ->\ numeric,\ you\ can\ lose\ precision,\ your\nexpressions\ will\ be\ much\ slower,\ and\ you\ can\ even\ have\ security\nproblems:\n\n======\n#\ don't\ run\nset\ x\ \{\ \[format\ C:\\\]\ \}\n#\ the\ following\ line\ would\ execute\ format\ c:\\\n#\ set\ y\ \[expr\ \$x\ +\ 3\]\n======\n\n**\ Security\ Implications\ **\n\n\[AMG\]:\ The\ security\ problems\ of\ unbraced\ \[expr\]\ expressions\ are\ very\ similar\ to\ \[SQL\]\ injection\ attacks.\ \ Notice\ how\ \[sqlite\]'s\ \[Tcl\]\ binding\ does\ its\ own\ variable\ expansion\ to\ avoid\ this\ very\ problem.\ \ Many,\ many\ \[sh\]\ scripts\ have\ this\ problem\ as\ well\ because\ the\ default\ is\ to\ apply\ multiple\ passes\ of\ interpretation.\n\n**\ The\ Art\ of\ Unbraced\ Expressions\ **\n\n\[RS\]:\ In\ the\ following\ cases\ braced\ expressions\ don't\ work:\n\n\ \ \ *\ operator\ in\ variable\ (which\ in\ most\ languages\ is\ impossible,\ but\ Tcl\ can\ do):\n\n======\nset\ op\ +\nexpr\ \$x\ \$op\ \$y\n======\n\n\ \ \ *\ (parts\ of)\ expression\ generated\ by\ string\ manipulation:\n\ expr\ \[join\ \$intlist\ +\]\n\ \ \ *\ \[GM\]\ function\ name\ is\ specified\ in\ a\ variable\n\n======\n\ set\ op\ sin\nexpr\ \$\{op\}(\$x)\n======\n\n\[MJ\]:\ In\ 8.5\ this\ can\ be\ done\ faster\ and\ safer\ like:\n\n======\nset\ op\ ::tcl::mathop::+\n\$op\ \$x\ \$y\n======\n\nand\n\ \n\ \$op\ \{*\}\$intlist\n\nIn\ response\ to\ question\ on\ 2007-06-27\ \[GWM\]\ Why\ does\ bracketing\ this\ not\ work:\n\n======\nset\ sign\ -\nset\ valu\ 1.234\nexpr\ \{\$sign\$valu\}\n======\nwhen\ these\ do?\n\n======\nexpr\ \$sign\$valu\nexpr\ \{-\$valu\}\n======\n\n\[Lars\ H\]:\ It\ is\ because\ of\ the\ role\ of\ variable\ substitution\ in\ the\ expr\ little\nlanguage\ --\ a\ \$varname\ is\ always\ an\ operand,\ never\ an\ operation.\ Having\ it\ this\nway\ is\ essential\ for\ byte-compilation\ to\ work\ --\ consider\ what\ happens\ to\n\n======\nexpr\ \{2\ +\ \$a\ *\ \[someProc\]\}\n======\n\nif\ substitution\ on\ \$a\ is\ allowed\ to\ insert\ things\ like\n\n======none\n(-2)\ ?\ 0\ :\ 3\n======\n\ninto\ the\ expression.\n\nOne\ can\ achieve\ more\ Tclish\ substitution\ behaviour\ by\ using\ double\ quotes\ in\ the\ expression\;\n\n======\nset\ sign\ -\nset\ valu\ 1.234\nexpr\ \{\"\$sign\$valu\"\ +\ 1\}\n#\ -0.234\ \n======\n\n\[GWM\]\ this\ also\ works:\n======\nexpr\ \{\[subst\ \$sign\$valu\]\ +\ 1\}\n======\n\nI\ think\ the\ very\ short\ answer\ is\ that\ the\ byte\ code\ compiler\ will\ need\ to\ncompile\ the\ expression\ differently\ if\ the\ operator\ is\ changed,\ so\ operators\ncannot\ be\ in\ variables\ unless\ you\ disable\ the\ compiler\ (by\ omitting\ the\ \{\}).\n\nI\ think\ confusion\ arises\ as\ numerical\ values\ can\ be\ braced\;\ anything\ else\ cannot.\n\n======\nset\ x\ 1.2\nset\ y\ .3\nexpr\ \{\$x+\$y\}\n======\n\nis\ ok\ provided\ x\ &\ y\ are\ numbers.\ If\ \n======\nset\ x\ 1+.2\nset\ y\ .3\n======\n\nthen\ the\ above\ expr\ doesn't\ compile\ although\ expr\ \$x+\$y\ expands\ to\ expr\ 1+.2+.3\ (=\ 1.5)\ which\ appears\ reasonable\ but\ x\ is\ not\ a\ number.\n\nAnother\ example\ (extracted\ from\ \[Ask,\ and\ it\ shall\ be\ given\ #\ 8\]:\n======\nproc\ sqr\ \{a\}\ \{return\ \[expr\ \{sqrt(\$a)\}\]\}\nproc\ tn\ \{a\}\ \{\ return\ \"2*tan(\[sqr\ \$a\])\"\}\n======\nsqr\ 8\ \;#\ 2.8284271247461903\ntn\ 2\ \;#\ 2*tan(1.4142135623730951)\nexpr\ \{\[\[sqr\ 8\]\]\}\ \;#\ 2.8284271247461903\ntn\ 2\ \;#\ 2*tan(1.4142135623730951)\n\n#However:\nexpr\ \[tn\ 2\]\ \;#\ 12.668238334084391\nexpr\ \{\[tn\ 2\]\}\ \;#\ 2*tan(1.4142135623730951)\n======\n\nWith\ thanks\ to\ Lars\ for\ discussions.\ I\ have\ been\ playing\ with\ computer\ algebra\ for\ matrices,\ where\ the\ above\ problems\ occurred\ when\ creating\ Euler\ rotation\ matrices\ \[Euler\ Angles\].\ My\ solution\ elsewhere\ has\ been\ to\ create\ dynamically\ a\ proc,\ something\ like:\n\ \ proc\ myexpr\ \{\}\ \[subst\ \"expr\ \{\$x+\$y\}\"\]\nwhich\ generates\ a\ compilable\ statement.\n\n\[AMG\]:\ If\ you\ want\ expr\ to\ interpret\ its\ variables\ as\ math\ expressions\ rather\ than\ literal\ numerics,\ ask\ expr\ to\ recursively\ invoke\ itself:\n\n======\nset\ x\ 1+.2\nset\ y\ .3\nexpr\ \{\[expr\ \$x\]*\[expr\ \$y\]\}\n======\n\nThis\ gives\ you\ correct\ order\ of\ operations\ (replace\ the\ third\ line\ with\ `expr\n\$x*\$y`\ to\ see\ the\ problem),\ and\ you\ can\ be\ selective\ about\ which\ variables\ are\nexpressions\ and\ which\ are\ numerics.\n\nAlso,\ check\ this\ out:\n\n======\nset\ x\ 1+.2\nexpr\ \$x\ \ \ \ \ \ \;#\ returns\ 1.2\nexpr\ \{\$x\}\ \ \ \ \;#\ returns\ 1+.2\n======\n\nThe\ argument\ to\ the\ first\ expr\ is\ '''`1+.2`''',\ and\ the\ argument\ to\ the\ second\nexpr\ is\ '''`\$x`'''.\ \ In\ both\ cases\ it\ evaluates\ the\ expression,\ except\ that\nthese\ two\ expressions\ are\ as\ different\ as\ night\ and\ day.\ \ In\ the\ second\ case,\nthe\ expression\ evaluates\ to\ a\ non-numeric\ string.\ \ Unlike\ you\ and\ me,\ expr\nneither\ notices\ nor\ cares\ that\ this\ non-numeric\ string\ is\ itself\ a\ well-formed\nmath\ expression.\n\n----\n\n\[KPV\]:\ Braced\ expressions\ also\ don't\ work\ when\ you\ do\nnegation\ in\ the\ lazy\ way:\n\n======\nset\ n1\ -3\nset\ n2\ -\$n1\nexpr\ \{2\ +\ \$n2\}\ \;#\ error\nexpr\ 2\ +\ \$n2\ \ \ \;#\ ok\n======\n\n----\n\[aricb\]\ Dec.\ 10\ 2005\ --\ As\ a\ bonus,\ braced\ expressions\ are\ generally\ ''much''\ faster\ than\ their\ non-braced\ counterparts.\ \ Here's\ an\ attempt\ to\ illustrate\ the\ difference:\n\n======\nproc\ time_braces\ \{\}\ \{\n\n\ \ \ \ set\ expressions\ \{\n\ \ \ \ \ \ \ \ \{1\ +\ 1\}\n\ \ \ \ \ \ \ \ \{16\ -\ 7\}\n\ \ \ \ \ \ \ \ \{(16\ -\ 7)\}\n\ \ \ \ \ \ \ \ \{7\ *\ 12\}\n\ \ \ \ \ \ \ \ \{81\ /\ 3\}\n\ \ \ \ \ \ \ \ \{81\ /\ 5\}\n\ \ \ \ \ \ \ \ \{16224308\ +\ 123580329\}\n\ \ \ \ \ \ \ \ \{6.3\ +\ 1.2\}\n\ \ \ \ \ \ \ \ \{6.3\ -\ 1.2\}\n\ \ \ \ \ \ \ \ \{6.3\ *\ 1.2\}\n\ \ \ \ \ \ \ \ \{6.3\ /\ 1.2\}\n\ \ \ \ \ \ \ \ \{log(765)\ *\ 3\}\n\ \ \ \ \ \ \ \ \{(log(765)\ *\ 3)\ /\ 8.23\}\n\ \ \ \ \}\n\n\ \ \ \ puts\ \[format\ \"\ %-22s\ \ %-8s\ \ %-8s\ \ %-8s\ \ %-5s\"\ \"Expression\"\ \"-braces\"\ \"+braces\"\ \"ratio\"\ \"%\ speedup\"\]\n\ \ \ \ puts\ \"\ \[string\ repeat\ -\ 22\]\ \ \[string\ repeat\ -\ 8\]\ \ \[string\ repeat\ -\ 8\]\ \ \[string\ repeat\ -\ 8\]\ \ \[string\ repeat\ -\ 5\]\"\n\n\ \ \ \ foreach\ expression\ \$expressions\ \{\n\ \ \ \ \ \ \ \ set\ time1\ \[lindex\ \[time\ \"expr\ \$expression\"\ 100000\]\ 0\]\n\ \ \ \ \ \ \ \ set\ time2\ \[lindex\ \[time\ \[list\ expr\ \$expression\]\ 100000\]\ 0\]\n\ \ \ \ \ \ \ \ set\ ratio\ \[expr\ \{\$time1\ /\ \$time2\}\]\n\ \ \ \ \ \ \ \ set\ percent\ \[expr\ \{100\ *\ (1\ -\ (\$time2\ /\ \$time1))\}\]\n\ \ \ \ \ \ \ \ puts\ \[format\ \"\ %-22s\ \ %8.6f\ \ %8.6f\ \ %6.3f:1\ \ %5.2f\"\ \$expression\ \$time1\ \$time2\ \$ratio\ \$percent\]\n\ \ \ \ \}\n\n\ \ \ \ puts\ \"\\n\ -braces\ and\ +braces\ are\ in\ microseconds\ per\ iteration\"\n\}\n======\n\nResults:\n\n======none\nExpression\ \ \ \ \ \ \ \ \ \ \ \ \ \ -braces\ \ \ +braces\ \ \ ratio\ \ \ \ \ %\ speedup\n----------------------\ \ --------\ \ --------\ \ --------\ \ -----\n1\ +\ 1\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2.334690\ \ 0.366480\ \ \ 6.371:1\ \ 84.30\n16\ -\ 7\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2.388280\ \ 0.359960\ \ \ 6.635:1\ \ 84.93\n(16\ -\ 7)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.748160\ \ 0.356120\ \ 10.525:1\ \ 90.50\n7\ *\ 12\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2.438530\ \ 0.368200\ \ \ 6.623:1\ \ 84.90\n81\ /\ 3\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2.456060\ \ 0.395680\ \ \ 6.207:1\ \ 83.89\n81\ /\ 5\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2.518490\ \ 0.397380\ \ \ 6.338:1\ \ 84.22\n16224308\ +\ 123580329\ \ \ \ 2.726690\ \ 0.369530\ \ \ 7.379:1\ \ 86.45\n6.3\ +\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.237970\ \ 0.497100\ \ \ 6.514:1\ \ 84.65\n6.3\ -\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.199230\ \ 0.486350\ \ \ 6.578:1\ \ 84.80\n6.3\ *\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.279100\ \ 0.480630\ \ \ 6.823:1\ \ 85.34\n6.3\ /\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.257540\ \ 0.494340\ \ \ 6.590:1\ \ 84.82\nlog(765)\ *\ 3\ \ \ \ \ \ \ \ \ \ \ \ 6.202120\ \ 0.975590\ \ \ 6.357:1\ \ 84.27\n(log(765)\ *\ 3)\ /\ 8.23\ \ \ 7.951270\ \ 1.142210\ \ \ 6.961:1\ \ 85.63\n======\n\n\ -braces\ and\ +braces\ are\ in\ microseconds\ per\ iteration\n----\n\[RS\]\ 2007-01-09:\ These\ results\ puzzle\ me:\ the\ expressions\ contain\ no\ variable\ references,\ all\ constants.\ I\ thought\ the\ time\ advantage\ of\ braced\ expressions\ was\ because\ they\ could\ retrieve\ the\ numeric\ value\ of\ variables\ directly,\ without\ having\ to\ parse\ string\ reps\ -\ but\ in\ the\ above\ cases,\ the\ strings\ would\ have\ to\ be\ parsed\ either\ way...\n\n\[AM\]\ The\ numeric\ value\ of\ the\ strings\ is\ cached\ in\ the\ data\ structure\ that\ \[\[expr\]\]\ builds\ up\ during\ the\ parsing.\nSo\ there\ is\ no\ real\ difference\ between\ numeric\ constants\ and\ variables\ with\ numeric\ values\n\n\[RS\]\ Well,\ but\ the\ only\ difference\ braces\ make,\ in\ my\ opinion,\ is\ that\ \$,\ \\,\ or\ \[\[...\]\]\ substitutions\ don't\ take\ place.\ If\ there\ are\ none,\n\n======\nexpr\ 1+1\n======\n\nshould\ be\ totally\ equivalent\ (in\ the\ eyes\ of\ \[expr\])\ to\n======\nexpr\ \{1+1\}\n======\n\n\[LV\]\ It\ should\ be\ simple\ enough\ to\ enhance\ the\ above\ benchmark\ to\ include\ some\nvariable\ uses\ to\ compare\ numeric\ strings\ vs\ numeric\ variables.\ -\ \[RS\]\ Sure,\ but\nmy\ point\ was:\ how\ can\ \"bracing\"\ of\ constant\ strings\ lead\ to\ factors\ 0f\ 6..10?\n\n\[LV\]\ Ask\ \[JH\]\ or\ \[AK\]\ for\ certain,\ but\ I\ suspect\ that\ the\ bracing\ puts\ the\nstrings\ into\ a\ cache,\ with\ a\ Tcl\ object\ allocated\ for\ it,\ so\ that\ it\ doesn't\nneed\ to\ be\ reparsed.\n\n\[NEM\]:\ I\ think\ it\ is\ the\ grouping\ that\ makes\ the\ difference.\ With\ braces,\ \[expr\]\ gets\ a\nsingle\ argument\ and\ so\ can\ cache\ the\ parsed\ expression\ in\ that\ Tcl_Obj.\ Without\ the\ braces,\nit\ would\ have\ no\ Tcl_Obj\ available\ that\ represents\ the\ entire\ expression,\ so\ no\ good\ place\nto\ store\ the\ cache.\ This\ is\ a\ guess,\ but\ is\ backed\ up\ by\ augmenting\ the\ benchmark\ to\ also\ndisplay\ the\ times\ for\ quote-grouped\ expressions.\ Add\ the\ following\ line\ to\ the\ benchmark:\n\n======\nset\ time3\ \[lindex\ \[time\ \"expr\ \\\"\$expression\\\"\"\ 100000\]\ 0\]\n======\n\nand\ adjusting\ the\ output\ to\ display\ this\ too,\ we\ get:\n\n======none\nExpression\ \ \ \ \ \ \ \ \ \ \ \ \ \ -braces\ \ \ +braces\ \ \ +quotes\ \ \ ratio\ \ \ \ \ %\ speedup\n----------------------\ \ --------\ \ --------\ \ --------\ \ --------\ \ -----\n1\ +\ 1\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.290665\ \ 0.341749\ \ 0.340983\ \ \ 9.629:1\ \ 89.61\n16\ -\ 7\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.392816\ \ 0.337900\ \ 0.340074\ \ 10.041:1\ \ 90.04\n(16\ -\ 7)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.486216\ \ 0.342534\ \ 0.337474\ \ 10.178:1\ \ 90.17\n7\ *\ 12\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.315694\ \ 0.339483\ \ 0.331504\ \ \ 9.767:1\ \ 89.76\n81\ /\ 3\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.370662\ \ 0.357784\ \ 0.347305\ \ \ 9.421:1\ \ 89.39\n81\ /\ 5\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.376001\ \ 0.354991\ \ 0.351884\ \ \ 9.510:1\ \ 89.48\n16224308\ +\ 123580329\ \ \ \ 4.481029\ \ 0.341851\ \ 0.339320\ \ 13.108:1\ \ 92.37\n6.3\ +\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.446636\ \ 0.349055\ \ 0.354368\ \ \ 9.874:1\ \ 89.87\n6.3\ -\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.511427\ \ 0.351007\ \ 0.346844\ \ 10.004:1\ \ 90.00\n6.3\ *\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.420894\ \ 0.348808\ \ 0.343441\ \ \ 9.807:1\ \ 89.80\n6.3\ /\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.471898\ \ 0.353067\ \ 0.358395\ \ \ 9.834:1\ \ 89.83\nlog(765)\ *\ 3\ \ \ \ \ \ \ \ \ \ \ \ 6.598790\ \ 0.759914\ \ 0.756337\ \ \ 8.684:1\ \ 88.48\n(log(765)\ *\ 3)\ /\ 8.23\ \ \ 7.775013\ \ 0.829403\ \ 0.841776\ \ \ 9.374:1\ \ 89.33\n======\n\nSo\ clearly\ the\ speed\ is\ mainly\ due\ to\ the\ grouping\ rather\ than\ braces\ avoiding\ substitition.\n(I\ also\ changed\ the\ braces\ line\ to\ ''time\ \"expr\ \{\$expression\}\"''\ to\ avoid\ any\ possible\neffects\ of\ pure-list\ optimisations,\ but\ this\ made\ negligible\ impact).\n\n\[AMG\]:\ This\ is\ indeed\ the\ case,\ as\ shown\ by\ '''tclCmdAH.C'''.\n\n======c\n743\ Tcl_ExprObjCmd(dummy,\ interp,\ objc,\ objv)\n748\ \{\n758\ \ \ \ \ objPtr\ =\ Tcl_ConcatObj(objc-1,\ objv+1)\;\n759\ \ \ \ \ Tcl_IncrRefCount(objPtr)\;\n760\ \ \ \ \ result\ =\ Tcl_ExprObj(interp,\ objPtr,\ &resultPtr)\;\n761\ \ \ \ \ Tcl_DecrRefCount(objPtr)\;\n768\ \ \ \ \ return\ result\;\n769\ \}\n======\n\nIf\ there's\ only\ one\ argument\ to\ \[\[\[expr\]\]\],\ then\ Tcl_ConcatObj()\ can\ return\nthat\ object\ without\ having\ to\ make\ a\ temporary\ that\ dies\ on\ line\ 761.\nTcl_ExprObj()\ will\ \"shimmer\"\ the\ object\ to\ an\ expression\ type.\ \ If\ this\nconversion\ is\ done\ on\ the\ object\ passed\ by\ the\ caller\ (instead\ of\ on\ a\ntemporary\ object),\ it\ will\ be\ cached\ inside\ the\ caller's\ Tcl_Obj\ for\ the\ next\ntime\ it\ is\ passed\ to\ \[\[expr\]\].\n\n\[RS\]\ In\ other\ words,\ \"if\ you\ don't\ want\ to\ brace,\ don't\ space\"\ :^)\ \n\n======\nexpr\ 1+1\n======\n\nwould\ be\ faster\ than\ (the\ normally\ preferable\ style)\n\n======\nexpr\ 1\ +\ 1\n======\n\nBut\ of\ course,\ most\ meaningful\ calls\ to\ \[expr\]\ involve\ at\ least\ one\ variable\nreference,\ so\ the\ advantage\ of\ bracing\ isn't\ really\ challenged.\n\n\[slebetman\]:\ Indeed.\ I\ did\ the\ following\ modification\ to\ the\ test:\n======\nproc\ time_braces\ \{\}\ \{\n\ \n\ \ \ \ set\ x\ 55\n\ \ \ \ set\ y\ 1.5\n\ \n\ \ \ \ set\ expressions\ \{\n\ \ \ \ \ \ \ \ \{1\ +\ 1\}\n\ \ \ \ \ \ \ \ \{16\ -\ 7\}\n\ \ \ \ \ \ \ \ \{(16\ -\ 7)\}\n\ \ \ \ \ \ \ \ \{7\ *\ 12\}\n\ \ \ \ \ \ \ \ \{81\ /\ 3\}\n\ \ \ \ \ \ \ \ \{81\ /\ 5\}\n\ \ \ \ \ \ \ \ \{16224308\ +\ 123580329\}\n\ \ \ \ \ \ \ \ \{\$x\ +\ \$y\}\n\ \ \ \ \ \ \ \ \{\$x\ -\ \$y\}\n\ \ \ \ \ \ \ \ \{\$x\ *\ \$y\}\n\ \ \ \ \ \ \ \ \{\$x\ /\ \$y\}\n\ \ \ \ \ \ \ \ \{log(\$x)\ *\ \$y\}\n\ \ \ \ \ \ \ \ \{(log(\$x)\ *\ \$y)\ /\ 8.23\}\n\ \ \ \ \}\n\ \n\ \ \ \ puts\ \[format\ \"\ %-22s\ \ %-8s\ \ %-8s\ \ %-8s\ \ %-8s\ \ %-5s\"\ \"Expression\"\ \"-braces\"\ \"+braces\"\ \"quotes\"\ \"ratio\"\ \"%\ speedup\"\]\n\ \ \ \ puts\ \"\ \[string\ repeat\ -\ 22\]\ \[string\ repeat\ -\ 8\]\ \[string\ repeat\ -\ 8\]\ \ \[string\ repeat\ -\ 8\]\ \ \[string\ repeat\ -\ 8\]\ \ \[string\ repeat\ -\ 5\]\"\n\ \n\ \ \ \ foreach\ expression\ \$expressions\ \{\n\ \ \ \ \ \ \ \ set\ time1\ \[lindex\ \[time\ \"expr\ \$expression\"\ 100000\]\ 0\]\n\ \ \ \ \ \ \ \ set\ time2\ \[lindex\ \[time\ \[list\ expr\ \$expression\]\ 100000\]\ 0\]\n\ \ \ \ \ \ \ \ set\ time3\ \[lindex\ \[time\ \"expr\ \\\"\$expression\\\"\"\ 100000\]\ 0\]\n\ \ \ \ \ \ \ \ set\ ratio\ \[expr\ \{\$time1\ /\ \$time2\}\]\n\ \ \ \ \ \ \ \ set\ percent\ \[expr\ \{100\ *\ (1\ -\ (\$time2\ /\ \$time1))\}\]\n\ \ \ \ \ \ \ \ puts\ \[format\ \"\ %-22s\ \ %8.6f\ \ %8.6f\ \ %8.6f\ \ %6.3f:1\ \ %5.2f\"\ \$expression\ \$time1\ \$time2\ \$time3\ \$ratio\ \$percent\]\n\ \ \ \ \}\n\ \n\ \ \ \ puts\ \"\\n\ -braces,\ +braces\ and\ quotes\ are\ in\ microseconds\ per\ iteration\"\n\}\n======\n\nand\ got\ the\ following\ result:\n\n======none\n\ Expression\ \ \ \ \ \ \ \ \ \ \ \ \ \ -braces\ \ \ +braces\ \ \ quotes\ \ \ \ ratio\ \ \ \ \ %\ speedup\n\ -----------------------\ --------\ \ --------\ \ --------\ \ --------\ \ -----\n\ 1\ +\ 1\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2.883460\ \ 0.344300\ \ 0.330900\ \ \ 8.375:1\ \ 88.06\n\ 16\ -\ 7\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.158980\ \ 0.353570\ \ 0.358150\ \ \ 8.935:1\ \ 88.81\n\ (16\ -\ 7)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 5.992560\ \ 0.350260\ \ 0.352260\ \ 17.109:1\ \ 94.16\n\ 7\ *\ 12\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.099940\ \ 0.349550\ \ 0.364370\ \ \ 8.868:1\ \ 88.72\n\ 81\ /\ 3\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.163450\ \ 0.369680\ \ 0.384460\ \ \ 8.557:1\ \ 88.31\n\ 81\ /\ 5\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.186310\ \ 0.407560\ \ 0.394200\ \ \ 7.818:1\ \ 87.21\n\ 16224308\ +\ 123580329\ \ \ \ 3.966440\ \ 0.343470\ \ 0.345680\ \ 11.548:1\ \ 91.34\n\ \$x\ +\ \$y\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 4.658480\ \ 0.511210\ \ 4.512600\ \ \ 9.113:1\ \ 89.03\n\ \$x\ -\ \$y\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 4.634080\ \ 0.507070\ \ 4.548150\ \ \ 9.139:1\ \ 89.06\n\ \$x\ *\ \$y\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 4.634230\ \ 0.507840\ \ 4.615830\ \ \ 9.125:1\ \ 89.04\n\ \$x\ /\ \$y\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 4.706090\ \ 0.543070\ \ 4.610930\ \ \ 8.666:1\ \ 88.46\n\ log(\$x)\ *\ \$y\ \ \ \ \ \ \ \ \ \ \ \ 6.318600\ \ 0.700440\ \ 5.936520\ \ \ 9.021:1\ \ 88.91\n\ (log(\$x)\ *\ \$y)\ /\ 8.23\ \ \ 9.505550\ \ 0.856280\ 10.454150\ \ 11.101:1\ \ 90.99\n======\n\n\ -braces,\ +braces\ and\ quotes\ are\ in\ microseconds\ per\ iteration\nSo\ the\ lesson\ is\ unless\ you're\ doing\ something\ trivial\ like\ '''(123*1024)''',\nalways\ \[brace\ your\ expr-essions\]!\ \ The\ second\ lesson\ is\ be\ careful\ how\ you\nwrite\ your\ benchmark,\ lest\ you\ accidentally\ test\ for\ something\ other\ than\ what\nyou\ intended\ to\ test.\n\n----\n\[AMG\]:\ Even\ in\ this\ bold\ era\ of\ \[bytecode\]'ing,\ bracing\ expressions\ is\ critical\ for\ performance.\ \ Check\ this\ out:\n\n======\n%\ tcl::unsupported::disassemble\ script\ \{expr\ \{2\ +\ 2\}\}\nByteCode\ 0x02845A10,\ refCt\ 1,\ epoch\ 5,\ interp\ 0x02725500\ (epoch\ 5)\n\ \ Source\ \"expr\ \{2\ +\ 2\}\"\n\ \ Cmds\ 1,\ src\ 12,\ inst\ 3,\ litObjs\ 1,\ aux\ 0,\ stkDepth\ 1,\ code/src\ 0.00\n\ \ Commands\ 1:\n\ \ \ \ \ \ 1:\ pc\ 0-1,\ src\ 0-11\n\ \ Command\ 1:\ \"expr\ \{2\ +\ 2\}\"\n\ \ \ \ (0)\ push1\ 0\ \ \ \ \ \ \ \ \ #\ \"4\"\n\ \ \ \ (2)\ done\ \n\n%\ tcl::unsupported::disassemble\ script\ \{expr\ 2\ +\ 2\}\nByteCode\ 0x02846D10,\ refCt\ 1,\ epoch\ 5,\ interp\ 0x02725500\ (epoch\ 5)\n\ \ Source\ \"expr\ 2\ +\ 2\"\n\ \ Cmds\ 1,\ src\ 10,\ inst\ 14,\ litObjs\ 3,\ aux\ 0,\ stkDepth\ 5,\ code/src\ 0.00\n\ \ Commands\ 1:\n\ \ \ \ \ \ 1:\ pc\ 0-12,\ src\ 0-9\n\ \ Command\ 1:\ \"expr\ 2\ +\ 2\"\n\ \ \ \ (0)\ push1\ 0\ \ \ \ \ \ \ \ \ #\ \"2\"\n\ \ \ \ (2)\ push1\ 1\ \ \ \ \ \ \ \ \ #\ \"\ \"\n\ \ \ \ (4)\ push1\ 2\ \ \ \ \ \ \ \ \ #\ \"+\"\n\ \ \ \ (6)\ push1\ 1\ \ \ \ \ \ \ \ \ #\ \"\ \"\n\ \ \ \ (8)\ push1\ 0\ \ \ \ \ \ \ \ \ #\ \"2\"\n\ \ \ \ (10)\ concat1\ 5\ \n\ \ \ \ (12)\ exprStk\ \n\ \ \ \ (13)\ done\ \n======\n\n<<categories>>\ Arts\ and\ crafts\ of\ Tcl-Tk\ programming\ |\ Security\ |\ Performance regexp2} CALL {my render {Brace your expr-essions} **\ Description\ **\n\n\[KBK\]\ closed\ a\ follow-up\ to\ \[the\ comp.lang.tcl\ newsgroup\]\ with\ the\ advice\ that,\n\"Also,\ it's\ important\ always,\ always\ to\ brace\ your\ \[expr\]essions.\ \ Don't\ do\n\n======\nset\ a\ \[expr\ \$b\ /\ \$c\]\n======\n\nbut\ rather\n\n======\nset\ a\ \[expr\ \{\ \$b\ /\ \$c\ \}\]\n======\n\nOtherwise,\ your\ variables\ may\ undergo\ unexpected\ conversions\nnumeric\ ->\ string\ ->\ numeric,\ you\ can\ lose\ precision,\ your\nexpressions\ will\ be\ much\ slower,\ and\ you\ can\ even\ have\ security\nproblems:\n\n======\n#\ don't\ run\nset\ x\ \{\ \[format\ C:\\\]\ \}\n#\ the\ following\ line\ would\ execute\ format\ c:\\\n#\ set\ y\ \[expr\ \$x\ +\ 3\]\n======\n\n**\ Security\ Implications\ **\n\n\[AMG\]:\ The\ security\ problems\ of\ unbraced\ \[expr\]\ expressions\ are\ very\ similar\ to\ \[SQL\]\ injection\ attacks.\ \ Notice\ how\ \[sqlite\]'s\ \[Tcl\]\ binding\ does\ its\ own\ variable\ expansion\ to\ avoid\ this\ very\ problem.\ \ Many,\ many\ \[sh\]\ scripts\ have\ this\ problem\ as\ well\ because\ the\ default\ is\ to\ apply\ multiple\ passes\ of\ interpretation.\n\n**\ The\ Art\ of\ Unbraced\ Expressions\ **\n\n\[RS\]:\ In\ the\ following\ cases\ braced\ expressions\ don't\ work:\n\n\ \ \ *\ operator\ in\ variable\ (which\ in\ most\ languages\ is\ impossible,\ but\ Tcl\ can\ do):\n\n======\nset\ op\ +\nexpr\ \$x\ \$op\ \$y\n======\n\n\ \ \ *\ (parts\ of)\ expression\ generated\ by\ string\ manipulation:\n\ expr\ \[join\ \$intlist\ +\]\n\ \ \ *\ \[GM\]\ function\ name\ is\ specified\ in\ a\ variable\n\n======\n\ set\ op\ sin\nexpr\ \$\{op\}(\$x)\n======\n\n\[MJ\]:\ In\ 8.5\ this\ can\ be\ done\ faster\ and\ safer\ like:\n\n======\nset\ op\ ::tcl::mathop::+\n\$op\ \$x\ \$y\n======\n\nand\n\ \n\ \$op\ \{*\}\$intlist\n\nIn\ response\ to\ question\ on\ 2007-06-27\ \[GWM\]\ Why\ does\ bracketing\ this\ not\ work:\n\n======\nset\ sign\ -\nset\ valu\ 1.234\nexpr\ \{\$sign\$valu\}\n======\nwhen\ these\ do?\n\n======\nexpr\ \$sign\$valu\nexpr\ \{-\$valu\}\n======\n\n\[Lars\ H\]:\ It\ is\ because\ of\ the\ role\ of\ variable\ substitution\ in\ the\ expr\ little\nlanguage\ --\ a\ \$varname\ is\ always\ an\ operand,\ never\ an\ operation.\ Having\ it\ this\nway\ is\ essential\ for\ byte-compilation\ to\ work\ --\ consider\ what\ happens\ to\n\n======\nexpr\ \{2\ +\ \$a\ *\ \[someProc\]\}\n======\n\nif\ substitution\ on\ \$a\ is\ allowed\ to\ insert\ things\ like\n\n======none\n(-2)\ ?\ 0\ :\ 3\n======\n\ninto\ the\ expression.\n\nOne\ can\ achieve\ more\ Tclish\ substitution\ behaviour\ by\ using\ double\ quotes\ in\ the\ expression\;\n\n======\nset\ sign\ -\nset\ valu\ 1.234\nexpr\ \{\"\$sign\$valu\"\ +\ 1\}\n#\ -0.234\ \n======\n\n\[GWM\]\ this\ also\ works:\n======\nexpr\ \{\[subst\ \$sign\$valu\]\ +\ 1\}\n======\n\nI\ think\ the\ very\ short\ answer\ is\ that\ the\ byte\ code\ compiler\ will\ need\ to\ncompile\ the\ expression\ differently\ if\ the\ operator\ is\ changed,\ so\ operators\ncannot\ be\ in\ variables\ unless\ you\ disable\ the\ compiler\ (by\ omitting\ the\ \{\}).\n\nI\ think\ confusion\ arises\ as\ numerical\ values\ can\ be\ braced\;\ anything\ else\ cannot.\n\n======\nset\ x\ 1.2\nset\ y\ .3\nexpr\ \{\$x+\$y\}\n======\n\nis\ ok\ provided\ x\ &\ y\ are\ numbers.\ If\ \n======\nset\ x\ 1+.2\nset\ y\ .3\n======\n\nthen\ the\ above\ expr\ doesn't\ compile\ although\ expr\ \$x+\$y\ expands\ to\ expr\ 1+.2+.3\ (=\ 1.5)\ which\ appears\ reasonable\ but\ x\ is\ not\ a\ number.\n\nAnother\ example\ (extracted\ from\ \[Ask,\ and\ it\ shall\ be\ given\ #\ 8\]:\n======\nproc\ sqr\ \{a\}\ \{return\ \[expr\ \{sqrt(\$a)\}\]\}\nproc\ tn\ \{a\}\ \{\ return\ \"2*tan(\[sqr\ \$a\])\"\}\n======\nsqr\ 8\ \;#\ 2.8284271247461903\ntn\ 2\ \;#\ 2*tan(1.4142135623730951)\nexpr\ \{\[\[sqr\ 8\]\]\}\ \;#\ 2.8284271247461903\ntn\ 2\ \;#\ 2*tan(1.4142135623730951)\n\n#However:\nexpr\ \[tn\ 2\]\ \;#\ 12.668238334084391\nexpr\ \{\[tn\ 2\]\}\ \;#\ 2*tan(1.4142135623730951)\n======\n\nWith\ thanks\ to\ Lars\ for\ discussions.\ I\ have\ been\ playing\ with\ computer\ algebra\ for\ matrices,\ where\ the\ above\ problems\ occurred\ when\ creating\ Euler\ rotation\ matrices\ \[Euler\ Angles\].\ My\ solution\ elsewhere\ has\ been\ to\ create\ dynamically\ a\ proc,\ something\ like:\n\ \ proc\ myexpr\ \{\}\ \[subst\ \"expr\ \{\$x+\$y\}\"\]\nwhich\ generates\ a\ compilable\ statement.\n\n\[AMG\]:\ If\ you\ want\ expr\ to\ interpret\ its\ variables\ as\ math\ expressions\ rather\ than\ literal\ numerics,\ ask\ expr\ to\ recursively\ invoke\ itself:\n\n======\nset\ x\ 1+.2\nset\ y\ .3\nexpr\ \{\[expr\ \$x\]*\[expr\ \$y\]\}\n======\n\nThis\ gives\ you\ correct\ order\ of\ operations\ (replace\ the\ third\ line\ with\ `expr\n\$x*\$y`\ to\ see\ the\ problem),\ and\ you\ can\ be\ selective\ about\ which\ variables\ are\nexpressions\ and\ which\ are\ numerics.\n\nAlso,\ check\ this\ out:\n\n======\nset\ x\ 1+.2\nexpr\ \$x\ \ \ \ \ \ \;#\ returns\ 1.2\nexpr\ \{\$x\}\ \ \ \ \;#\ returns\ 1+.2\n======\n\nThe\ argument\ to\ the\ first\ expr\ is\ '''`1+.2`''',\ and\ the\ argument\ to\ the\ second\nexpr\ is\ '''`\$x`'''.\ \ In\ both\ cases\ it\ evaluates\ the\ expression,\ except\ that\nthese\ two\ expressions\ are\ as\ different\ as\ night\ and\ day.\ \ In\ the\ second\ case,\nthe\ expression\ evaluates\ to\ a\ non-numeric\ string.\ \ Unlike\ you\ and\ me,\ expr\nneither\ notices\ nor\ cares\ that\ this\ non-numeric\ string\ is\ itself\ a\ well-formed\nmath\ expression.\n\n----\n\n\[KPV\]:\ Braced\ expressions\ also\ don't\ work\ when\ you\ do\nnegation\ in\ the\ lazy\ way:\n\n======\nset\ n1\ -3\nset\ n2\ -\$n1\nexpr\ \{2\ +\ \$n2\}\ \;#\ error\nexpr\ 2\ +\ \$n2\ \ \ \;#\ ok\n======\n\n----\n\[aricb\]\ Dec.\ 10\ 2005\ --\ As\ a\ bonus,\ braced\ expressions\ are\ generally\ ''much''\ faster\ than\ their\ non-braced\ counterparts.\ \ Here's\ an\ attempt\ to\ illustrate\ the\ difference:\n\n======\nproc\ time_braces\ \{\}\ \{\n\n\ \ \ \ set\ expressions\ \{\n\ \ \ \ \ \ \ \ \{1\ +\ 1\}\n\ \ \ \ \ \ \ \ \{16\ -\ 7\}\n\ \ \ \ \ \ \ \ \{(16\ -\ 7)\}\n\ \ \ \ \ \ \ \ \{7\ *\ 12\}\n\ \ \ \ \ \ \ \ \{81\ /\ 3\}\n\ \ \ \ \ \ \ \ \{81\ /\ 5\}\n\ \ \ \ \ \ \ \ \{16224308\ +\ 123580329\}\n\ \ \ \ \ \ \ \ \{6.3\ +\ 1.2\}\n\ \ \ \ \ \ \ \ \{6.3\ -\ 1.2\}\n\ \ \ \ \ \ \ \ \{6.3\ *\ 1.2\}\n\ \ \ \ \ \ \ \ \{6.3\ /\ 1.2\}\n\ \ \ \ \ \ \ \ \{log(765)\ *\ 3\}\n\ \ \ \ \ \ \ \ \{(log(765)\ *\ 3)\ /\ 8.23\}\n\ \ \ \ \}\n\n\ \ \ \ puts\ \[format\ \"\ %-22s\ \ %-8s\ \ %-8s\ \ %-8s\ \ %-5s\"\ \"Expression\"\ \"-braces\"\ \"+braces\"\ \"ratio\"\ \"%\ speedup\"\]\n\ \ \ \ puts\ \"\ \[string\ repeat\ -\ 22\]\ \ \[string\ repeat\ -\ 8\]\ \ \[string\ repeat\ -\ 8\]\ \ \[string\ repeat\ -\ 8\]\ \ \[string\ repeat\ -\ 5\]\"\n\n\ \ \ \ foreach\ expression\ \$expressions\ \{\n\ \ \ \ \ \ \ \ set\ time1\ \[lindex\ \[time\ \"expr\ \$expression\"\ 100000\]\ 0\]\n\ \ \ \ \ \ \ \ set\ time2\ \[lindex\ \[time\ \[list\ expr\ \$expression\]\ 100000\]\ 0\]\n\ \ \ \ \ \ \ \ set\ ratio\ \[expr\ \{\$time1\ /\ \$time2\}\]\n\ \ \ \ \ \ \ \ set\ percent\ \[expr\ \{100\ *\ (1\ -\ (\$time2\ /\ \$time1))\}\]\n\ \ \ \ \ \ \ \ puts\ \[format\ \"\ %-22s\ \ %8.6f\ \ %8.6f\ \ %6.3f:1\ \ %5.2f\"\ \$expression\ \$time1\ \$time2\ \$ratio\ \$percent\]\n\ \ \ \ \}\n\n\ \ \ \ puts\ \"\\n\ -braces\ and\ +braces\ are\ in\ microseconds\ per\ iteration\"\n\}\n======\n\nResults:\n\n======none\nExpression\ \ \ \ \ \ \ \ \ \ \ \ \ \ -braces\ \ \ +braces\ \ \ ratio\ \ \ \ \ %\ speedup\n----------------------\ \ --------\ \ --------\ \ --------\ \ -----\n1\ +\ 1\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2.334690\ \ 0.366480\ \ \ 6.371:1\ \ 84.30\n16\ -\ 7\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2.388280\ \ 0.359960\ \ \ 6.635:1\ \ 84.93\n(16\ -\ 7)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.748160\ \ 0.356120\ \ 10.525:1\ \ 90.50\n7\ *\ 12\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2.438530\ \ 0.368200\ \ \ 6.623:1\ \ 84.90\n81\ /\ 3\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2.456060\ \ 0.395680\ \ \ 6.207:1\ \ 83.89\n81\ /\ 5\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2.518490\ \ 0.397380\ \ \ 6.338:1\ \ 84.22\n16224308\ +\ 123580329\ \ \ \ 2.726690\ \ 0.369530\ \ \ 7.379:1\ \ 86.45\n6.3\ +\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.237970\ \ 0.497100\ \ \ 6.514:1\ \ 84.65\n6.3\ -\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.199230\ \ 0.486350\ \ \ 6.578:1\ \ 84.80\n6.3\ *\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.279100\ \ 0.480630\ \ \ 6.823:1\ \ 85.34\n6.3\ /\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.257540\ \ 0.494340\ \ \ 6.590:1\ \ 84.82\nlog(765)\ *\ 3\ \ \ \ \ \ \ \ \ \ \ \ 6.202120\ \ 0.975590\ \ \ 6.357:1\ \ 84.27\n(log(765)\ *\ 3)\ /\ 8.23\ \ \ 7.951270\ \ 1.142210\ \ \ 6.961:1\ \ 85.63\n======\n\n\ -braces\ and\ +braces\ are\ in\ microseconds\ per\ iteration\n----\n\[RS\]\ 2007-01-09:\ These\ results\ puzzle\ me:\ the\ expressions\ contain\ no\ variable\ references,\ all\ constants.\ I\ thought\ the\ time\ advantage\ of\ braced\ expressions\ was\ because\ they\ could\ retrieve\ the\ numeric\ value\ of\ variables\ directly,\ without\ having\ to\ parse\ string\ reps\ -\ but\ in\ the\ above\ cases,\ the\ strings\ would\ have\ to\ be\ parsed\ either\ way...\n\n\[AM\]\ The\ numeric\ value\ of\ the\ strings\ is\ cached\ in\ the\ data\ structure\ that\ \[\[expr\]\]\ builds\ up\ during\ the\ parsing.\nSo\ there\ is\ no\ real\ difference\ between\ numeric\ constants\ and\ variables\ with\ numeric\ values\n\n\[RS\]\ Well,\ but\ the\ only\ difference\ braces\ make,\ in\ my\ opinion,\ is\ that\ \$,\ \\,\ or\ \[\[...\]\]\ substitutions\ don't\ take\ place.\ If\ there\ are\ none,\n\n======\nexpr\ 1+1\n======\n\nshould\ be\ totally\ equivalent\ (in\ the\ eyes\ of\ \[expr\])\ to\n======\nexpr\ \{1+1\}\n======\n\n\[LV\]\ It\ should\ be\ simple\ enough\ to\ enhance\ the\ above\ benchmark\ to\ include\ some\nvariable\ uses\ to\ compare\ numeric\ strings\ vs\ numeric\ variables.\ -\ \[RS\]\ Sure,\ but\nmy\ point\ was:\ how\ can\ \"bracing\"\ of\ constant\ strings\ lead\ to\ factors\ 0f\ 6..10?\n\n\[LV\]\ Ask\ \[JH\]\ or\ \[AK\]\ for\ certain,\ but\ I\ suspect\ that\ the\ bracing\ puts\ the\nstrings\ into\ a\ cache,\ with\ a\ Tcl\ object\ allocated\ for\ it,\ so\ that\ it\ doesn't\nneed\ to\ be\ reparsed.\n\n\[NEM\]:\ I\ think\ it\ is\ the\ grouping\ that\ makes\ the\ difference.\ With\ braces,\ \[expr\]\ gets\ a\nsingle\ argument\ and\ so\ can\ cache\ the\ parsed\ expression\ in\ that\ Tcl_Obj.\ Without\ the\ braces,\nit\ would\ have\ no\ Tcl_Obj\ available\ that\ represents\ the\ entire\ expression,\ so\ no\ good\ place\nto\ store\ the\ cache.\ This\ is\ a\ guess,\ but\ is\ backed\ up\ by\ augmenting\ the\ benchmark\ to\ also\ndisplay\ the\ times\ for\ quote-grouped\ expressions.\ Add\ the\ following\ line\ to\ the\ benchmark:\n\n======\nset\ time3\ \[lindex\ \[time\ \"expr\ \\\"\$expression\\\"\"\ 100000\]\ 0\]\n======\n\nand\ adjusting\ the\ output\ to\ display\ this\ too,\ we\ get:\n\n======none\nExpression\ \ \ \ \ \ \ \ \ \ \ \ \ \ -braces\ \ \ +braces\ \ \ +quotes\ \ \ ratio\ \ \ \ \ %\ speedup\n----------------------\ \ --------\ \ --------\ \ --------\ \ --------\ \ -----\n1\ +\ 1\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.290665\ \ 0.341749\ \ 0.340983\ \ \ 9.629:1\ \ 89.61\n16\ -\ 7\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.392816\ \ 0.337900\ \ 0.340074\ \ 10.041:1\ \ 90.04\n(16\ -\ 7)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.486216\ \ 0.342534\ \ 0.337474\ \ 10.178:1\ \ 90.17\n7\ *\ 12\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.315694\ \ 0.339483\ \ 0.331504\ \ \ 9.767:1\ \ 89.76\n81\ /\ 3\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.370662\ \ 0.357784\ \ 0.347305\ \ \ 9.421:1\ \ 89.39\n81\ /\ 5\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.376001\ \ 0.354991\ \ 0.351884\ \ \ 9.510:1\ \ 89.48\n16224308\ +\ 123580329\ \ \ \ 4.481029\ \ 0.341851\ \ 0.339320\ \ 13.108:1\ \ 92.37\n6.3\ +\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.446636\ \ 0.349055\ \ 0.354368\ \ \ 9.874:1\ \ 89.87\n6.3\ -\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.511427\ \ 0.351007\ \ 0.346844\ \ 10.004:1\ \ 90.00\n6.3\ *\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.420894\ \ 0.348808\ \ 0.343441\ \ \ 9.807:1\ \ 89.80\n6.3\ /\ 1.2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.471898\ \ 0.353067\ \ 0.358395\ \ \ 9.834:1\ \ 89.83\nlog(765)\ *\ 3\ \ \ \ \ \ \ \ \ \ \ \ 6.598790\ \ 0.759914\ \ 0.756337\ \ \ 8.684:1\ \ 88.48\n(log(765)\ *\ 3)\ /\ 8.23\ \ \ 7.775013\ \ 0.829403\ \ 0.841776\ \ \ 9.374:1\ \ 89.33\n======\n\nSo\ clearly\ the\ speed\ is\ mainly\ due\ to\ the\ grouping\ rather\ than\ braces\ avoiding\ substitition.\n(I\ also\ changed\ the\ braces\ line\ to\ ''time\ \"expr\ \{\$expression\}\"''\ to\ avoid\ any\ possible\neffects\ of\ pure-list\ optimisations,\ but\ this\ made\ negligible\ impact).\n\n\[AMG\]:\ This\ is\ indeed\ the\ case,\ as\ shown\ by\ '''tclCmdAH.C'''.\n\n======c\n743\ Tcl_ExprObjCmd(dummy,\ interp,\ objc,\ objv)\n748\ \{\n758\ \ \ \ \ objPtr\ =\ Tcl_ConcatObj(objc-1,\ objv+1)\;\n759\ \ \ \ \ Tcl_IncrRefCount(objPtr)\;\n760\ \ \ \ \ result\ =\ Tcl_ExprObj(interp,\ objPtr,\ &resultPtr)\;\n761\ \ \ \ \ Tcl_DecrRefCount(objPtr)\;\n768\ \ \ \ \ return\ result\;\n769\ \}\n======\n\nIf\ there's\ only\ one\ argument\ to\ \[\[\[expr\]\]\],\ then\ Tcl_ConcatObj()\ can\ return\nthat\ object\ without\ having\ to\ make\ a\ temporary\ that\ dies\ on\ line\ 761.\nTcl_ExprObj()\ will\ \"shimmer\"\ the\ object\ to\ an\ expression\ type.\ \ If\ this\nconversion\ is\ done\ on\ the\ object\ passed\ by\ the\ caller\ (instead\ of\ on\ a\ntemporary\ object),\ it\ will\ be\ cached\ inside\ the\ caller's\ Tcl_Obj\ for\ the\ next\ntime\ it\ is\ passed\ to\ \[\[expr\]\].\n\n\[RS\]\ In\ other\ words,\ \"if\ you\ don't\ want\ to\ brace,\ don't\ space\"\ :^)\ \n\n======\nexpr\ 1+1\n======\n\nwould\ be\ faster\ than\ (the\ normally\ preferable\ style)\n\n======\nexpr\ 1\ +\ 1\n======\n\nBut\ of\ course,\ most\ meaningful\ calls\ to\ \[expr\]\ involve\ at\ least\ one\ variable\nreference,\ so\ the\ advantage\ of\ bracing\ isn't\ really\ challenged.\n\n\[slebetman\]:\ Indeed.\ I\ did\ the\ following\ modification\ to\ the\ test:\n======\nproc\ time_braces\ \{\}\ \{\n\ \n\ \ \ \ set\ x\ 55\n\ \ \ \ set\ y\ 1.5\n\ \n\ \ \ \ set\ expressions\ \{\n\ \ \ \ \ \ \ \ \{1\ +\ 1\}\n\ \ \ \ \ \ \ \ \{16\ -\ 7\}\n\ \ \ \ \ \ \ \ \{(16\ -\ 7)\}\n\ \ \ \ \ \ \ \ \{7\ *\ 12\}\n\ \ \ \ \ \ \ \ \{81\ /\ 3\}\n\ \ \ \ \ \ \ \ \{81\ /\ 5\}\n\ \ \ \ \ \ \ \ \{16224308\ +\ 123580329\}\n\ \ \ \ \ \ \ \ \{\$x\ +\ \$y\}\n\ \ \ \ \ \ \ \ \{\$x\ -\ \$y\}\n\ \ \ \ \ \ \ \ \{\$x\ *\ \$y\}\n\ \ \ \ \ \ \ \ \{\$x\ /\ \$y\}\n\ \ \ \ \ \ \ \ \{log(\$x)\ *\ \$y\}\n\ \ \ \ \ \ \ \ \{(log(\$x)\ *\ \$y)\ /\ 8.23\}\n\ \ \ \ \}\n\ \n\ \ \ \ puts\ \[format\ \"\ %-22s\ \ %-8s\ \ %-8s\ \ %-8s\ \ %-8s\ \ %-5s\"\ \"Expression\"\ \"-braces\"\ \"+braces\"\ \"quotes\"\ \"ratio\"\ \"%\ speedup\"\]\n\ \ \ \ puts\ \"\ \[string\ repeat\ -\ 22\]\ \[string\ repeat\ -\ 8\]\ \[string\ repeat\ -\ 8\]\ \ \[string\ repeat\ -\ 8\]\ \ \[string\ repeat\ -\ 8\]\ \ \[string\ repeat\ -\ 5\]\"\n\ \n\ \ \ \ foreach\ expression\ \$expressions\ \{\n\ \ \ \ \ \ \ \ set\ time1\ \[lindex\ \[time\ \"expr\ \$expression\"\ 100000\]\ 0\]\n\ \ \ \ \ \ \ \ set\ time2\ \[lindex\ \[time\ \[list\ expr\ \$expression\]\ 100000\]\ 0\]\n\ \ \ \ \ \ \ \ set\ time3\ \[lindex\ \[time\ \"expr\ \\\"\$expression\\\"\"\ 100000\]\ 0\]\n\ \ \ \ \ \ \ \ set\ ratio\ \[expr\ \{\$time1\ /\ \$time2\}\]\n\ \ \ \ \ \ \ \ set\ percent\ \[expr\ \{100\ *\ (1\ -\ (\$time2\ /\ \$time1))\}\]\n\ \ \ \ \ \ \ \ puts\ \[format\ \"\ %-22s\ \ %8.6f\ \ %8.6f\ \ %8.6f\ \ %6.3f:1\ \ %5.2f\"\ \$expression\ \$time1\ \$time2\ \$time3\ \$ratio\ \$percent\]\n\ \ \ \ \}\n\ \n\ \ \ \ puts\ \"\\n\ -braces,\ +braces\ and\ quotes\ are\ in\ microseconds\ per\ iteration\"\n\}\n======\n\nand\ got\ the\ following\ result:\n\n======none\n\ Expression\ \ \ \ \ \ \ \ \ \ \ \ \ \ -braces\ \ \ +braces\ \ \ quotes\ \ \ \ ratio\ \ \ \ \ %\ speedup\n\ -----------------------\ --------\ \ --------\ \ --------\ \ --------\ \ -----\n\ 1\ +\ 1\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2.883460\ \ 0.344300\ \ 0.330900\ \ \ 8.375:1\ \ 88.06\n\ 16\ -\ 7\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.158980\ \ 0.353570\ \ 0.358150\ \ \ 8.935:1\ \ 88.81\n\ (16\ -\ 7)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 5.992560\ \ 0.350260\ \ 0.352260\ \ 17.109:1\ \ 94.16\n\ 7\ *\ 12\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.099940\ \ 0.349550\ \ 0.364370\ \ \ 8.868:1\ \ 88.72\n\ 81\ /\ 3\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.163450\ \ 0.369680\ \ 0.384460\ \ \ 8.557:1\ \ 88.31\n\ 81\ /\ 5\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 3.186310\ \ 0.407560\ \ 0.394200\ \ \ 7.818:1\ \ 87.21\n\ 16224308\ +\ 123580329\ \ \ \ 3.966440\ \ 0.343470\ \ 0.345680\ \ 11.548:1\ \ 91.34\n\ \$x\ +\ \$y\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 4.658480\ \ 0.511210\ \ 4.512600\ \ \ 9.113:1\ \ 89.03\n\ \$x\ -\ \$y\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 4.634080\ \ 0.507070\ \ 4.548150\ \ \ 9.139:1\ \ 89.06\n\ \$x\ *\ \$y\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 4.634230\ \ 0.507840\ \ 4.615830\ \ \ 9.125:1\ \ 89.04\n\ \$x\ /\ \$y\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 4.706090\ \ 0.543070\ \ 4.610930\ \ \ 8.666:1\ \ 88.46\n\ log(\$x)\ *\ \$y\ \ \ \ \ \ \ \ \ \ \ \ 6.318600\ \ 0.700440\ \ 5.936520\ \ \ 9.021:1\ \ 88.91\n\ (log(\$x)\ *\ \$y)\ /\ 8.23\ \ \ 9.505550\ \ 0.856280\ 10.454150\ \ 11.101:1\ \ 90.99\n======\n\n\ -braces,\ +braces\ and\ quotes\ are\ in\ microseconds\ per\ iteration\nSo\ the\ lesson\ is\ unless\ you're\ doing\ something\ trivial\ like\ '''(123*1024)''',\nalways\ \[brace\ your\ expr-essions\]!\ \ The\ second\ lesson\ is\ be\ careful\ how\ you\nwrite\ your\ benchmark,\ lest\ you\ accidentally\ test\ for\ something\ other\ than\ what\nyou\ intended\ to\ test.\n\n----\n\[AMG\]:\ Even\ in\ this\ bold\ era\ of\ \[bytecode\]'ing,\ bracing\ expressions\ is\ critical\ for\ performance.\ \ Check\ this\ out:\n\n======\n%\ tcl::unsupported::disassemble\ script\ \{expr\ \{2\ +\ 2\}\}\nByteCode\ 0x02845A10,\ refCt\ 1,\ epoch\ 5,\ interp\ 0x02725500\ (epoch\ 5)\n\ \ Source\ \"expr\ \{2\ +\ 2\}\"\n\ \ Cmds\ 1,\ src\ 12,\ inst\ 3,\ litObjs\ 1,\ aux\ 0,\ stkDepth\ 1,\ code/src\ 0.00\n\ \ Commands\ 1:\n\ \ \ \ \ \ 1:\ pc\ 0-1,\ src\ 0-11\n\ \ Command\ 1:\ \"expr\ \{2\ +\ 2\}\"\n\ \ \ \ (0)\ push1\ 0\ \ \ \ \ \ \ \ \ #\ \"4\"\n\ \ \ \ (2)\ done\ \n\n%\ tcl::unsupported::disassemble\ script\ \{expr\ 2\ +\ 2\}\nByteCode\ 0x02846D10,\ refCt\ 1,\ epoch\ 5,\ interp\ 0x02725500\ (epoch\ 5)\n\ \ Source\ \"expr\ 2\ +\ 2\"\n\ \ Cmds\ 1,\ src\ 10,\ inst\ 14,\ litObjs\ 3,\ aux\ 0,\ stkDepth\ 5,\ code/src\ 0.00\n\ \ Commands\ 1:\n\ \ \ \ \ \ 1:\ pc\ 0-12,\ src\ 0-9\n\ \ Command\ 1:\ \"expr\ 2\ +\ 2\"\n\ \ \ \ (0)\ push1\ 0\ \ \ \ \ \ \ \ \ #\ \"2\"\n\ \ \ \ (2)\ push1\ 1\ \ \ \ \ \ \ \ \ #\ \"\ \"\n\ \ \ \ (4)\ push1\ 2\ \ \ \ \ \ \ \ \ #\ \"+\"\n\ \ \ \ (6)\ push1\ 1\ \ \ \ \ \ \ \ \ #\ \"\ \"\n\ \ \ \ (8)\ push1\ 0\ \ \ \ \ \ \ \ \ #\ \"2\"\n\ \ \ \ (10)\ concat1\ 5\ \n\ \ \ \ (12)\ exprStk\ \n\ \ \ \ (13)\ done\ \n======\n\n<<categories>>\ Arts\ and\ crafts\ of\ Tcl-Tk\ programming\ |\ Security\ |\ Performance} CALL {my revision {Brace your expr-essions}} CALL {::oo::Obj1696199 process revision/Brace+your+expr-essions} CALL {::oo::Obj1696197 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