Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/eval?V=73
QUERY_STRINGV=73
CONTENT_TYPE
DOCUMENT_URI/revision/eval
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.70.100.175
REMOTE_PORT36238
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR3.133.121.160
HTTP_CF_RAY87d41ea58b301b67-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_CF_CONNECTING_IP3.133.121.160
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 eval **\ Summary\ **\n\nInterprets\ data\ as\ a\ a\ Tcl\ script\ and\ evaluates\ it.\n**\ Synopsis\ **\n\n\n\ \ \ \ :\ \ \ '''eval'''\ ''arg''\ ?''arg\ ...''?\ \ \n\n\n\n\n\ \ \ \[Injection\ Attack\]:\ \ \ \n\ \ \ \[introspection\]:\ \ \ \n\ \ \ \[Introspection\]:\ \ \ \n\ \ \ \[Many\ Ways\ to\ eval\]:\ \ \ \n\n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/eval.htm%|%official\ reference\]:\ \ \ \n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/eval.htm%|%man\ page\]:\ \ \ \n\n\n**\ Usage\ **\n\n`\[\[\[if\]\ 1\ ...\]`,\ which\ is\ byte-compiled,\ is\ an\ efficient\ replacement\ for\n`\[\[\[eval\]\]`\ in\ all\ cases.\ \ Thus,\ modern\ Tcl\ code\ has\ zero\ use\ for\ `\[\[eval\]`.\n\nTo\ avoid\ the\ caveats\ of\ `\[\[eval\]`\ the\ rule\ of\ thumb\ is\ to\ pass\ only\ one\nargument\ to\ `\[\[eval\]`.\ \ Passing\ a\ single\ script,\ rather\ than\ relying\ on\nimplicit\ concatenation\ helps\ to\ avoid\ dumb\ mistakes\ such\ as\ passing\ a\ string\nwhich\ contains\ newlines.\n\n\n\n'''`eval`'''\ concatenates\ its\ arguments\ in\ the\ same\ fashion\ as\n'''`\[\[eval\]`'''\ concatenates\ its\ arguments\ in\ the\ same\ fashion\ as\n`\[\[\[concat\]\]`,\ and\ hands\ them\ to\ the\ interpreter\ to\ be\ evaluated\ as\ a\ Tcl\nscript.\ \ It\ then\ returns\ the\ result\ of\ that\ evaluation\ or\ any\ error\ generated\nby\ it.\n`eval`\ is\ an\ old,\ old\ command\ that's\ been\ in\ \[Tcl\]\ from\ the\ beginning.\n`\[\[\[eval\]\]`\ is\ an\ old,\ old\ command,\ that's\ been\ in\ \[Tcl\]\ from\ the\ beginning.\n`eval`\ is\ useful\ when\ one\ wishes\ to\ generate\ a\ script\ and\ then\ interpret\ it.\n`\[\[eval\]`\ is\ useful\ when\ one\ wishes\ to\ generate\ a\ script\ and\ then\ interpret\ it.\nIn\ modern\ Tcl,\ `\[\[eval\]`\ is\ merely\ an\ abbreviation\ for\ `\[\[\[uplevel\]\ 0\]`.\ \ This\n'''self-modifying\ programs''',\ and\ related\ esoterica.\n\"self-modifying\ programs\",\ and\ related\ esoterica.\n`\[if\]\ 1\ ...`,\ which\ may\ be\ \[bytecode%|%byte-compiled\],\ is\ an\ efficient\n`eval`\ is\ used\ by\ \ all\ the\ commands\ --\ `\[bind\]`,\ everything\ with\n`\[\[eval\]`\ is\ used\ by\ \ all\ the\ commands\ --\ `\[\[\[bind\]\]`,\ everything\ with\n\nWhen\ using\ `eval`,\ it\ is\ very\ easy\ to\ leave\ holes\ which\ can\ be\ exploited\ to\nWhen\ using\ `\[\[eval\]`,\ it\ is\ very\ easy\ to\ leave\ holes\ which\ can\ be\ exploited\ to\ninject\ malicious\ code,\ so\ it\ is\ best\ to\ exercise\ extreme\ care\ with\ it\ until\ one\n\n`eval`\ can\ often\ be\ avoided,\ particularly\ with\ more\ modern\ recent\ versions\ of\n`\[\[eval\]`\ can\ often\ be\ avoided,\ particulary\ with\ more\ modern\ recent\ versions\ of\n\n\n\n**\ Is\ `\[\[eval\]`\ Evil?\ **\nShort\ answer:\ No.\ \ Like\ many\ commands\ in\ Tcl,\ `eval`\ can\ lead\ to\ \[double\nShort\ answer:\ No.\ \ Like\ many\ commands\ in\ Tcl,\ `\[\[eval\]`\ can\ lead\ to\ \[double\nskilled\ Tcl\ programmer\ knows\ how\ to\ wield\ \[double\ substitution\].\nskilled\ Tcl\ programmer\ learns\ how\ to\ wield\ \[double\ substitution\].\nHistorically,\ `eval`\ was\ often\ used\ with\ exec,\ to\ flatten\ lists,\ allowing\n\nHistorically,\ `\[\[\[eval\]\]`\ was\ often\ used\ with\ exec,\ to\ flatten\ lists,\ allowing\na\ single\ list\ to\ provide\ multiple\ arguments\ to\ a\ command:\ \n======\n#warning:\ no-longer\ recommended\neval\ exec\ grep\ foo\ \$filelist\n======\n\nbecause\ otherwise\ ''grep''\ would\ receive\ filelist\ as\ one\ long\ filename\ with\ embedded\ blanks.\nIn\ modern\ Tcl,\ the\ following\ is\ preferred:\nIn\ modern\ Tcl,\ the\ following\ is\ preferred\ for\ reasons\ of\ efficiency\ and\ safety:\nexec\ grep\ foo\ \{*\}\$filelist\n======\n\nOr,\ if\ you\ want\ to\ append\ one\ list's\ elements\ to\ another,\ and\ you're\ willing\ to\ assume\ that\ the\ variable\ containing\ the\ new\ elements\ doesn't\ embed\ any\ unquoted\ semicolons\ or\ newlines:\nembedded\ blanks.\ Or,\ if\ you\ want\ to\ append\ one\ list's\ elements\ to\ another:\n======\neval\ lappend\ thislist\ \$thatlist\nset\ thislist\ \[concat\ \$thislist\ \$thatlist\]\ \;#\ can\ also\ be\ done\ as\n======\n\nThough\ the\ following\ two\ options\ are\ safer\ and\ faster:\nstring)\ and\ finally\ calling\n\n======\neval\ \$script\n======\n\nWhen\ the\ script\ contains\ only\ one\ command,\ \[argument\ expansion\]\ is\ preferred:\n\n======\n\{*\}\$cmd\n======\n\n**\ Expanding\ Lists\ with\ `eval`\ **\n**\ Expanding\ Lists\ with\ `\[\[eval\]`\ **\nPrior\ to\ Tcl\ version\ 8.5,\ one\ use\ case\ for\ `eval`\ was\ to\ expand\ lists.\nPrior\ to\ Tcl\ version\ 8.5,\ one\ use\ case\ for\ `\[\[eval\]`\ was\ to\ expand\ lists.\nThere\ is\ no\ longer\ any\ reason\ to\ do\ this.\ \ Use\ `\[\{*\}\]`\ instead.\nSee\ \[Argument\ expansion\].\n\n----\nInstead\ of:\n\n\n======\n#warning:\ not\ recommended\neval\ pack\ \[winfo\ children\ .\]\n======\n\nuse:\n\n======\npack\ \{*\}\[winfo\ children\ .\]\n======\n\n----\n\nAnd\ instead\ of:\n\n======\n#warning:\ this\ is\ not\ recommended\nset\ filepath\ \[list\ path\ to\ the\ file\]\neval\ file\ join\ \$filepath\n======\n\nuse:\n\n======\nset\ filepath\ \[list\ path\ to\ the\ file\]\nfile\ join\ \{*\}\$filepath\n======\n\n----\nAnother\ similar\ example\n\n\n======\n#the\ old\ (bad)\ way\nset\ f\ \[glob\ *.tcl\]\neval\ \[linsert\ \$f\ 0\ exec\ lp\]\n======\n\n======\n#the\ shiny\ new\ way\nexec\ lp\ \{*\}\$f\n======\n\n\n***\ Historical\ ***\n\nThe\ following\ describes\ the\ situation\ before\ the\ advent\ of\ \[\{*\}\]:\n\nNaive\ code\ might\ look\ like\ this\ (an\ actual\ example\ from\ BWidget's\nentry.tcl:97):\n\n======\n#warning:\ bad\ code\ ahead!\neval\ entry\ \$path\ \$maps(:cmd)\n======\n\nAn\ unsuccessful\ attempt\ to\ fix\ the\ problem:\nAn\ unsuccesful\ attempt\ to\ fix\ the\ problem:\n======\n#warning:\ bad\ code\ ahead!\neval\ entry\ \[list\ \$path\]\ \$maps(:cmd)\n======\n\nBut\ `\$maps(:cmd)`\ might\ be\ a\ string\ with\ newlines:\n\n======\nset\ maps(:cmd)\ \{\n\ \ \ \ -opt1\ val1\n\ \ \ \ -opt2\ val2\n\}\n======\n\nIt's\ necessary\ to\ first\ convert\ `\$maps(:cmd)`\ to\ a\ proper\ list\ using\ one\ of\ the\nlist\ commands:\n\n======\neval\ \[linsert\ \$maps(:cmd)\ 0\ entry\ \$path\]\n======\n\n***\ See\ Also\ ***\n\n\ \ \ \[http://code.activestate.com/lists/tcl-core/414/%|%RE:\ TCLCORE\ Re:\ CFV:\ TIPs\ #156\ and\ #157\],\ \[Jeff\ Hobbs\],\ \[Tcl\ Core\ Team%|%tcl-core\ mailing\ list\],\ 2003-10-12:\ \ \ \[AMG\]:\ Text\ repeated\ below,\ please\ read\ it\ until\ you\ understand\ what\ trouble\ \[\[eval\]\]\ buys\ you\ and\ how\ helpful\ \[\{*\}\]\ is.\n\ \ \ \[http://web.archive.org/web/20060325121839/http://aspn.activestate.com/ASPN/Mail/Message/tcl-core/1748289%|%TCLCORE\ TIP\ #144:\ Argument\ Expansion\ Syntax\],\ by\ \[tclguy\]:\ \ \ \n\ \ \ \[http://web.archive.org/web/20060325121839/http://aspn.activestate.com/ASPN/Mail/Message/tcl-core/1748289%|%TCLCORE\ TIP\ #144:\ Argument\ Expansion\ Syntax\],\ \[Jeff\ Hobbs\],\ \[Tcl\ Core\ Team%|%tcl-core\ mailing\ list\],\ 2003-07-26:\ \ \ \n\ \ \ \[http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/c3d6651005e12629/a9dc3e05d95b0f12?hl=en&ie=UTF-8&q=argument+expansion+apply+variadic+group:comp.lang.tcl*#%|%eval\ is\ evil\ (for\ spreading\ list-arguments)\]\ ,\[comp.lang.tcl\]\ ,2003-03-11:\ \ \ \n****\ Re:\ CFV:\ TIPs\ #156\ and\ #157\ ****\n\n\nThe\ arguments\ to\ `eval`\ are\ concatenated\ into\ a\ string\ to\ be\ interpreted,\ but\nThe\ arguments\ to\ \[\[eval\]\ are\ concatenated\ into\ a\ string\ to\ be\ interpreted,\ but\n(i.e.,\ one\ conforming\ to\ the\ Tcl\ parsing\ rules\ as\ laid\ out\ in\ the\ Tcl\ manual\npage).\n\nThe\ following\ script\ breaks\ because\ the\ concatenation\ keeps\ the\ newlines\ from\nthe\ list's\ string\ representation,\ making\ `eval`\ interpret\ the\ second\ element\nthe\ list's\ string\ representation,\ making\ \[\[eval\]\]\ interpret\ the\ second\ element\n\n======none\n%\ set\ arg\ \{a\nb\nc\n\}\na\nb\nc\n%\ eval\ list\ \$arg\nambiguous\ command\ name\ \"b\":\ bgerror\ binary\ break\n======\n\nTo\ solve\ this,\ construct\ the\ argument\ using\ list\ primitives\ like\ `\[lappend\]`,\nTo\ solve\ this,\ construct\ the\ argument\ using\ list\ primitives\ like\ \[lappend\],\n\[list\],\ etc.\ \ DKF\ says:\ \ \"list\ and\ eval\ are\ truly\ made\ for\ each\ other.\"\nAnother\ solution\ is\ to\ use\ the\ following\ idiom:\n\n======none\n%\ eval\ \[linsert\ \$arg\ 0\ list\]\na\ b\ c\n======\n\n`\[linsert\]`\ converts\ its\ list\ argument\ to\ a\ well-formed\ list\ with\ single\n`\[\[\[linsert\]\]`\ converts\ its\ list\ argument\ to\ a\ well-formed\ list\ with\ single\nof\ these\ elements\ contain\ newlines,\ they\ remain\ in\ the\ resulting\ string).\n\nIt's\ important\ to\ remember\ that\ `eval`\ works\ on\ '''strings''',\ not\ lists,\nIt's\ important\ to\ remember\ that\ `\[\[\[eval\]\]`\ works\ on\ '''strings''',\ not\ lists,\nfor\ interpreting\ a\ string\ as\ a\ script.\n\n\n**\ Verbose\ Evaluation\ **\n\n\[LV\]:\ I\ just\ had\ to\ copy\ this\ over\ to\ the\ wiki\ -\ it\ is\ so\ neat!\n\nFrom\ comp.lang.tcl,\ \[Bob\ Techentin\]\ writes\ in\ response\ to\ a\ poster:\n\nIt\ sounds\ like\ you're\ looking\ for\ something\ similar\ to\ /bin/sh\ \"set\ -v\"\ command\nwhich\ prints\ shell\ input\ lines\ as\ they\ are\ read,\ and\ \"set\ -x\"\ which\ prints\nexpanded\ commands.\ \ Kind\ of\ like\ a\ verbose\ mode.\n\nNope.\ \ Nothing\ like\ that.\ \ But\ you\ wouldn't\ have\ to\ write\ your\ own\ shell.\ \ You\ncould\ walk\ through\ a\ script\ (a\ list\ of\ lines),\ and\ use\ `\[info\ complete\]`\ to\ncould\ walk\ through\ a\ script\ (a\ list\ of\ lines),\ and\ use\ `\[\[\[info\ complete\]\]`\ to\ncommand\ and\ the\ command's\ results.\ \ This\ seems\ to\ work.\n\n======\nproc\ verbose_eval\ \{script\}\ \{\n\ \ \ \ set\ cmd\ \{\}\ \n\ \ \ \ set\ cmd\ \"\"\n\ \ \ \ if\ \{\$line\ eq\ \{\}\}\ \{continue\}\n\ \ \ \ if\ \{\$line\ eq\ \"\"\}\ \{continue\}\n\ \ \ \ \ \ \ \ if\ \{\[info\ complete\ \$cmd\]\}\ \{\n\ \ \ \ \ \ \ \ if\ \{\ \[info\ complete\ \$cmd\]\ \}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ puts\ -nonewline\ \[uplevel\ 1\ \$cmd\]\n\ \ \ \ \ \ \ \ \ \ \ \ set\ cmd\ \"\"\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\}\n\nset\ script\ \{\n\ \ \ \ puts\ hello\n\ \ \ \ expr\ \{2.2\ *\ 3\}\n\ \ \ \ expr\ 2.2*3\n\nverbose_eval\ \$script\ \n======\n\n\[LV\]:\ This\ proc\ is\ so\ slick!\ I\ love\ it!\n\[LV\]\ This\ proc\ is\ so\ slick!\ I\ love\ it!\n\[Lars\ H\]:\ \ Another\ approach\ to\ this\ (which\ also\ can\ see\ individual\ commands\ in\n`\[if\]`\ branches,\ loop\ bodies,\ etc.)\ is\ to\ use\ `\[trace\]`s.\ Do\ we\ have\ that\ written\n\[if\]\ branches,\ loop\ bodies,\ etc.)\ is\ to\ use\ \[trace\]s.\ Do\ we\ have\ that\ written\n\n\[AR\]\ Here\ is\ my\ proposal\ with\ traces.\ Rem:\ the\ \"noop\"\ string\ is\ some\ kind\ of\ magic\ cookie.\n\n\n\[wtracy\]\ 2008-06-23:\ I\ want\ the\ commands\ I\ run\ in\ eval\ to\ have\ their\ own\ set\ of\nvariables\ independently\ of\ the\ calling\ script.\ Is\ there\ some\ way\ I\ can\ hand\neval\ a\ context\ (maybe\ as\ an\ associative\ array?).\n\n\[Lars\ H\]:\ Sounds\ like\ you\ want\ a\ \[lambda\]\ (or\ possibly\ a\ \[closure\],\ which\ is\nmore\ difficult).\ If\ you're\ using\ Tcl\ 8.5,\ then\ have\ a\ look\ at\ `\[apply\]`.\nmore\ difficult).\ If\ you're\ using\ Tcl\ 8.5,\ then\ have\ a\ look\ at\ `\[\[\[apply\]\]`.\n\[RS\]:\ Long\ before\ 8.5,\ you\ could\ always\ write\ a\ little\ proc\ to\ hide\ its\ local\nvariables\ (x\ in\ this\ example):\n\n======none\n%\ eval\ \{proc\ \{\}\ x\ \{expr\ \{\$x*\$x\}\}\;\ \{\}\ 5\}\n%\ eval\ \{proc\ \{\}\ x\ \{expr\ \$x*\$x\}\;\ \{\}\ 5\}\n======\n\n\[wtracy\]:\ Thanks.\ It\ looks\ like\ `\[apply\]`\ is\ the\ closest\ Tcl\ feature\ to\ what\n\[wtracy\]:\ Thanks.\ It\ looks\ like\ `\[\[\[apply\]\]`\ is\ the\ closest\ Tcl\ feature\ to\ what\n\n\[wtracy\]:\ Actually,\ it\ looks\ like\ what\ I\ *really*\ want\ is\ to\ nest\ `eval`\n\[wtracy\]:\ Actually,\ it\ looks\ like\ what\ I\ *really*\ want\ is\ to\ nest\ `\[\[eval\]`\ninside\ of\ a\ `\[\[\[namespace\ eval\]\]`\ block.\n\[wtracy\]:\ Okay,\ for\ the\ sake\ of\ any\ lost\ soul\ that\ comes\ along\ after\ me,\ this\nis\ what\ I\ really\ wanted\ to\ do\ all\ along:\n\n======none\n\$\ set\ cmd\ \{puts\ FOO\}\n>\ set\ cmd\ \{puts\ FOO\}\n\$\ namespace\ eval\ MyNameSpace\ \$cmd\n>\ namespace\ eval\ MyNameSpace\ \$cmd\n======\n\n\[NEM\]:\ As\ mentioned,\ `\[apply\]`\ is\ probably\ a\ better\ choice\ in\ this\ case\ as\ it\n\[NEM\]\ As\ mentioned,\ `\[\[\[apply\]\]`\ is\ probably\ a\ better\ choice\ in\ this\ case\ as\ it\n\[dangers\ of\ creative\ writing\]\ for\ some\ related\ discussion.\ The\ `\[apply\]`\ version\ is:\n\[dangers\ of\ creative\ writing\]\ for\ some\ related\ discussion.\ The\ apply\ version\ is:\n======\napply\ \{\{\}\ \{puts\ FOO\}\ ::MyNameSpace\}\napply\ \{\{\}\ \{\ puts\ FOO\ \}\ ::MyNameSpace\}\n\nThis\ has\ the\ benefit\ of\ evaluating\ the\ code\ within\ a\ fresh\ procedure\ context,\nmeaning\ all\ variables\ are\ local\n\nto\ that\ context\ by\ default.\ See\ also\ `\[namespace\ inscope\]`/`\[namespace\ code\]`\ and\nto\ that\ context\ by\ default.\ See\ also\ \[namespace\ inscope\]/\[namespace\ code\]\ and\nyou\ may\ also\ like\ \[dict\ with\].\n\n**\ Proposal:\ Modify\ `eval`\ to\ Accept\ a\ List\ of\ Lists\ \ **\n**\ Proposal:\ Modify\ `\[\[eval\]`\ to\ Accept\ a\ List\ of\ Lists\ \ **\nIn\ some\ cases\ `eval`\ does\ work\ on\ lists\ -\ and\ its\ special.\ \ In\ particular,\nIn\ some\ cases\ `\[\[\[eval\]\]`\ does\ work\ on\ lists\ -\ and\ its\ special.\ \ In\ particular,\nif\ eval\ is\ passed\ a\ \[pure\ list\]\ then\ it\ gets\ evaluated\ directly,\ without\nwhat\ it\ ''could''\ be.\n\nWhen\ you\ pass\ eval\ a\ pure\ list,\ you\ can\ only\ execute\ a\ single\ command.\ \ What\ if\nwe\ were\ to\ pass\ eval\ a\ list\ of\ pure\ lists\ -\ it\ should\ directly\ evaluate\ each\ of\nthem,\ and\ return\ the\ value\ of\ the\ the\ last\ one\ evaluated.\ \ This\ sounds\ a\ lot\nlike\ progn\ in\ \[lisp\],\ and\ it\ seems\ like\ it\ would\ allow\ for\ some\ nifty\ bits\ of\n\[introspection\]\ -\ for\ example,\ if\ `\[info\ body\]`\ returned\ a\ pure\ list\ of\ lists\n\[introspection\]\ -\ for\ example,\ if\ \[info\ body\]\ returned\ a\ pure\ list-of-lists\nwhole\ program\ becomes\ a\ list\ of\ lists.\n\nThe\ problem\ is\ how\ to\ signal\ to\ `eval`\ (or\ `\[uplevel\]`,\ `\[namespace\]`,\ `\[bind\]`,\ ...)\ that\ it\nThe\ problem\ is\ how\ to\ signal\ to\ eval\ (or\ uplevel,\ namespace,\ bind,\ ...)\ that\ it\nis\ a\ list\ of\ lists\ rather\ than\ just\ a\ list.\ \ Could\ eval\ determine\ if\ its\ input\nprogn?\n\nAnother\ place\ this\ seems\ like\ it\ could\ be\ useful:\ I\ have\ a\ \[pkgIndex.tcl\]\ file\ with\nAnother\ place\ this\ seems\ like\ it\ could\ be\ useful:\ I\ have\ a\ pkgIndex\ file\ with\n\npackage\ ifneeded\ tls\ 1.4\ \[\npackage\ ifneeded\ tls\ 1.4\ \"\[list\ load\ \[file\ join\ \$dir\ libtls1.4.so\]\]\;\[list\ source\ \[file\ join\ \$dir\ tls.tcl\]\]\"\n\nwhere\ most\ of\ the\ lines\ are\ like\n\n======\npackage\ ifneeded\ tclperl\ 2.3\ \[list\ load\ \[file\ join\ \$dir\ tclperl.so\]\]\n======\n\nsince\ they\ only\ need\ one\ command\;\ but\ the\ tls\ line\ needs\ two\ commands.\ \ So\ why\ can't\ it\ be\n\n======\npackage\ ifneeded\ tls\ 1.4\ \[list\ \[\npackage\ ifneeded\ tls\ 1.4\ \[list\ \[list\ load\ \[file\ join\ \$dir\ libtls1.4.so\]\]\ \[list\ source\ \[file\ join\ \$dir\ tls.tcl\]\]\]\n\n\n\n\n\[RS\]\ 2004-02-06:\ As\ usual\ in\ Tcl,\ functionality\ you\ miss\ you\ can\ easy\ roll\nyourself.\ I\ needed\ a\ progn-like\ list\ eval\ in\ \[RPN\ again\],\ and\ did\ it\ similar\ to\nthis:\n\n======\nproc\ leval\ args\ \{\n\ \ \ \ foreach\ arg\ \$args\ \{\n\ \ \ \ \ \ \ \ set\ res\ \[uplevel\ 1\ \$arg\]\n\ \ \ \ \}\n\ \ \ \ set\ res\ \;#\ return\ last\ (\"n-th\")\ result,\ as\ Tcl\ evaluation\ does\n\}\n======\n\n\n\n**\ eval\ versus\ bytecode\ **\n**\ `eval`\ versus\ bytecode\ **\n\[AMG\]:\ It\ appears\ `\[\[eval\]\]`'ed\ code\ does\ not\ get\ \[bytecode\]-compiled,\ even\nwhen\ \[\[eval\]\]\ is\ passed\ a\ single\ brace-quoted\ argument.\ \ The\ same\ is\ true\ for\n`\[\[\[uplevel\]\ 0\]`\ and\ `\[\[\[time\]\]`.\ \ `\[\[\[catch\]\]`\ and\ `\[\[\[if\]\ \{1\}\]\]`\ seem\ to\ be\n\"argument\",\ rather\ a\ single\ command\ line\ pre-chewed\ into\ an\ objv\ list.\nBytecoding\ cannot\ take\ place\ when\ the\ argument\ is\ the\ product\ of\ `\[list\]`,\nBytecoding\ cannot\ take\ place\ when\ the\ argument\ is\ the\ product\ of\ `\[\[\[list\]\]`,\n\n======\nproc\ a\ \{\}\ \{eval\ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ b\ \{\}\ \{uplevel\ 0\ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ c\ \{\}\ \{time\ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ d\ \{\}\ \{catch\ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ e\ \{\}\ \{if\ \{1\}\ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ f\ \{\}\ \{\ \ \ \ \ \ \ \ \ \ \ \ \{*\}\{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ g\ \{\}\ \{eval\ \ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ h\ \{\}\ \{uplevel\ 0\ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ i\ \{\}\ \{time\ \ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ j\ \{\}\ \{catch\ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ k\ \{\}\ \{if\ \{1\}\ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ l\ \{\}\ \{\ \ \ \ \ \ \ \{*\}\[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ m\ \{\}\ \{try\ \ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\na\;b\;c\;d\;e\;f\;g\;h\;i\;j\;k\;l\;m\ntime\ a\ 10\ \ \ \ \;#\ \ 80723.8\ microseconds\ per\ iteration\ -\ slow\ntime\ b\ 10\ \ \ \ \;#\ \ 65380.2\ microseconds\ per\ iteration\ -\ slow\ntime\ c\ 10\ \ \ \ \;#\ \ 66024.8\ microseconds\ per\ iteration\ -\ slow\ntime\ d\ 100\ \ \ \;#\ \ 18888.3\ microseconds\ per\ iteration\ -\ fast\ntime\ e\ 100\ \ \ \;#\ \ 18779.3\ microseconds\ per\ iteration\ -\ fast\ntime\ f\ 100\ \ \ \;#\ \ 19375.2\ microseconds\ per\ iteration\ -\ fast\ntime\ g\ 10\ \ \ \ \;#\ 319111.5\ microseconds\ per\ iteration\ -\ very\ slow\ntime\ h\ 10\ \ \ \ \;#\ 342878.4\ microseconds\ per\ iteration\ -\ very\ slow\ntime\ i\ 10\ \ \ \ \;#\ 322279.2\ microseconds\ per\ iteration\ -\ very\ slow\ntime\ j\ 10\ \ \ \ \;#\ 316939.0\ microseconds\ per\ iteration\ -\ very\ slow\ntime\ k\ 10\ \ \ \ \;#\ 321865.5\ microseconds\ per\ iteration\ -\ very\ slow\ntime\ l\ 10\ \ \ \ \;#\ 344009.5\ microseconds\ per\ iteration\ -\ very\ slow\ntime\ m\ 100\ \ \ \;#\ \ 19503.0\ microseconds\ per\ iteration\ -\ fast\n======\n\nI\ want\ single-argument\ `eval`\ functionality\ in\ my\ code,\ but\ I\ also\ want\nI\ want\ single-argument\ `\[\[\[eval\]\]`\ functionality\ in\ my\ code,\ but\ I\ also\ want\nbytecoding.\ \ `\[\[\[catch\]\]`\ has\ the\ undesirable\ side\ effect\ of\ hiding\ errors,\ so\nI\ guess\ I\ have\ to\ use\ `\[\[\[if\]\ \{1\}\]`\ which\ is\ a\ really\ weird\ idiom.\ \ Does\ anyone\n\n\[AMG\]:\ I\ reran\ the\ tests\ and\ got\ better\ numbers.\ \ The\ current\ version\ of\ Tcl\nmust\ be\ faster\ than\ whatever\ I\ used\ when\ I\ first\ did\ this\ benchmark\ (I'm\ using\nthe\ same\ computer).\ \ Look\ in\ the\ page\ history\ to\ see\ the\ comparison.\ \ More\nimportantly,\ I\ think\ I\ found\ a\ bytecoded\ `eval`:\ single-argument\ `\[try\]`.\nimportantly,\ I\ think\ I\ found\ a\ bytecoded\ \[\[eval\]\]:\ single-argument\ \[\[\[try\]\]\].\nmethods.\ \ It's\ considerably\ less\ weird\ than\ `\[if\]\ 1`,\ and\ it\ doesn't\ hide\nmethods.\ \ It's\ considerably\ less\ weird\ than\ \[\[if\ \{1\}\]\],\ and\ it\ doesn't\ hide\n\n\[DKF\]:\ We've\ been\ focusing\ a\ bit\ more\ on\ improving\ the\ most\ cripplingly-slow\ncases,\ but\ three\ execution\ modes\ still\ exist\ that\ have\ fundamentally\ different\nspeeds.\ There's\ compilation\ to\ bytecode-with-local-var-table\ (which\ is\ the\nfastest\;\ the\ speed\ comes\ from\ being\ able\ to\ compile\ in\ indexes\ into\ the\ LVT\ninto\ the\ generated\ bytecode,\ which\ this\ test\ is\ particularly\ sensitive\ to),\nthere's\ compilation\ to\ bytecode-without-LVT\ (slower\;\ variables\ have\ to\ be\nlooked\ up\ each\ time\ they're\ accessed),\ and\ there's\ interpreting\ (slowest\ by\nfar).\ There's\ not\ much\ point\ in\ doing\ a\ lot\ of\ comparison\ between\ the\ three\;\nthey\ all\ exist\ for\ a\ reason.\ (We\ could\ make\ straight\ `eval`/`\[uplevel\]\nthey\ all\ exist\ for\ a\ reason.\ (We\ could\ make\ straight\ '''eval'''/'''\[uplevel\]\n0'''\ of\ constant\ arguments\ work\ at\ full\ speed,\ but\ we\ see\ no\ reason\ to\ bother\ngiven\ how\ rare\ they\ are\ in\ real\ code,\ and\ it's\ better\ that\ \[time\]\ is\ kept\nto\ get\ by\ using\ `\[::tcl::unsupported::disassemble\]`\ to\ look\ at\ the\ bytecode\ to\ see\nto\ get\ by\ using\ \[tcl::unsupported::disassemble\]\ to\ look\ at\ the\ bytecode\ to\ see\ndone\ by\ just\ building\ arguments\ and\ invoking\ “cnormal”\ commands.\ndone\ by\ just\ building\ arguments\ and\ invoking\ “normal”\ commands.\n\[Twylite\]\ 2012-08-24:\ \ I've\ been\ optimising\ some\ control\ constructs\ and\ was\ntrying\ to\ understand\ the\ performance\ of\ various\ combinations\ of\ uplevel,\ntailcall,\ catch\ and\ try.\ \ Along\ the\ way\ I\ found\ \[AMG\]'s\ performance\ figures,\nand\ have\ updated\ them\ with\ some\ new\ ones:\n\n======\n#\ Fast\ (prefix\ f)\nproc\ f_baseline\ \ \ \ \ \ \ \{\}\ \{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\ \}\nproc\ f_catch\ \ \ \ \ \ \ \ \ \ \{\}\ \{catch\ \ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ f_catch\ \ \ \ \ \ \ \ \ \ \{\}\ \{catch\ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ f_if_1\ \ \ \ \ \ \ \ \ \ \ \{\}\ \{if\ \{1\}\ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ f_expand\ \ \ \ \ \ \ \ \ \{\}\ \{\ \ \ \ \ \ \ \ \ \ \ \ \ \{*\}\{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ f_try\ \ \ \ \ \ \ \ \ \ \ \ \{\}\ \{try\ \ \ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ f_time_apply\ \ \ \ \ \{\}\ \{time\ \{apply\ \{\{\}\ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\}\}\n#\ Medium\ (prefix\ m)\ \ \ \ \ \ \ \ \ \ \ \ \ \nproc\ m_eval\ \ \ \ \ \ \ \ \ \ \ \{\}\ \{eval\ \ \ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ m_eval\ \ \ \ \ \ \ \ \ \ \ \{\}\ \{eval\ \ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ m_uplevel_0\ \ \ \ \ \ \{\}\ \{uplevel\ 0\ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ m_time\ \ \ \ \ \ \ \ \ \ \ \{\}\ \{time\ \ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ m_tailcall_try\ \ \ \{\}\ \{tailcall\ \ \ \ try\ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ m_catch_uplvl_1\ \ \{\}\ \{\ \ \ \ \ \ \ set\ body\ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\ \;\ catch\ \{\ uplevel\ 1\ \$body\ \}\ \}\ \ \nproc\ m_uplvl_1_catch\ \ \{\}\ \{\ \ \ \ \ \ \ set\ body\ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\ \;\ uplevel\ 1\ \[list\ catch\ \$body\]\ \}\ \ \n#\ Slow\ (prefix\ s)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \nproc\ s_eval_list\ \ \ \ \ \ \{\}\ \{eval\ \ \ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ s_uplevel_0_list\ \{\}\ \{uplevel\ 0\ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ s_time_list\ \ \ \ \ \ \{\}\ \{time\ \ \ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ s_catch_list\ \ \ \ \ \{\}\ \{catch\ \ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ s_if_1_list\ \ \ \ \ \ \{\}\ \{if\ 1\ \ \ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ s_if_1_list\ \ \ \ \ \ \{\}\ \{if\ \{1\}\ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ s_tailcall\ \ \ \ \ \ \ \{\}\ \{tailcall\ \ \ \ \ \ \ \ \ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\ \}\n\nif\ 0\ \{\nif\ \{0\}\ \{\n\ \ set\ REPS\ \{f\ 10\ m\ 40\ s\ 100\}\ \;#\ reps\ by\ prefix\n\ \ set\ cmds\ \{f_baseline\ f_catch\ f_if_1\ f_expand\ f_try\ f_time_apply\ \n\ \ \ \ m_eval\ m_uplevel_0\ m_time\ m_tailcall_try\ m_catch_uplvl_1\ m_uplvl_1_catch\ \n\ \ \ \ s_eval_list\ s_uplevel_0_list\ s_time_list\ s_catch_list\ s_if_1_list\ \n\ \ \ \ s_expand_list\ s_tailcall\}\n\ \ \n\ \ foreach\ cmd\ \$cmds\ \{\ \$cmd\ \}\ \;#\ compile\n\ \ set\ cmdrepstimes\ \{\}\ \;\ foreach\ cmd\ \$cmds\ \{\ \;#\ time\n\ \ \ \ set\ reps\ \[dict\ get\ \$::REPS\ \[string\ index\ \$cmd\ 0\]\]\ \n\ \ \ \ lappend\ cmdrepstimes\ \[lindex\ \[time\ \$cmd\ \$reps\]\ 0\]\ \$cmd\ \$reps\ \n\ \ \}\n\ \ \n\ \ set\ mintime\ \[::tcl::mathfunc::min\ \{*\}\$times\]\n\ \ foreach\ \{t\ cmd\ reps\}\ \[lsort\ -real\ -stride\ 3\ \$cmdrepstimes\]\ \{\n\ \ \ \ puts\ \[format\ \"time\ %-16s\ \$reps\\t\;#\ %9.1f\ microseconds\ per\ iteration,\ factor\ %5.2f\"\ \\\n\ \ \ \ \ \ \$cmd\ \$t\ \[expr\ \{\ \$t\ /\ \$mintime\ \}\]\ \]\ \n\ \ \}\n\ntime\ f_time_apply\ \ \ \ \ 10\ \ \ \ \ \ \ \ \;#\ \ \ \ 4625.8\ microseconds\ per\ iteration,\ factor\ \ 1.00\ntime\ f_if_1\ \ \ \ \ \ \ \ \ \ \ 10\ \ \ \ \ \ \ \ \;#\ \ \ \ 4641.8\ microseconds\ per\ iteration,\ factor\ \ 1.00\ntime\ f_expand\ \ \ \ \ \ \ \ \ 10\ \ \ \ \ \ \ \ \;#\ \ \ \ 4645.0\ microseconds\ per\ iteration,\ factor\ \ 1.00\ntime\ f_catch\ \ \ \ \ \ \ \ \ \ 10\ \ \ \ \ \ \ \ \;#\ \ \ \ 4651.3\ microseconds\ per\ iteration,\ factor\ \ 1.00\ntime\ f_baseline\ \ \ \ \ \ \ 10\ \ \ \ \ \ \ \ \;#\ \ \ \ 4658.5\ microseconds\ per\ iteration,\ factor\ \ 1.01\ntime\ f_try\ \ \ \ \ \ \ \ \ \ \ \ 10\ \ \ \ \ \ \ \ \;#\ \ \ \ 4735.9\ microseconds\ per\ iteration,\ factor\ \ 1.02\ntime\ m_eval\ \ \ \ \ \ \ \ \ \ \ 40\ \ \ \ \ \ \ \ \;#\ \ \ 18454.3\ microseconds\ per\ iteration,\ factor\ \ 3.98\ntime\ m_uplevel_0\ \ \ \ \ \ 40\ \ \ \ \ \ \ \ \;#\ \ \ 18738.3\ microseconds\ per\ iteration,\ factor\ \ 4.04\ntime\ m_time\ \ \ \ \ \ \ \ \ \ \ 40\ \ \ \ \ \ \ \ \;#\ \ \ 19176.8\ microseconds\ per\ iteration,\ factor\ \ 4.14\ntime\ m_uplvl_1_catch\ \ 40\ \ \ \ \ \ \ \ \;#\ \ \ 21501.1\ microseconds\ per\ iteration,\ factor\ \ 4.64\ntime\ m_catch_uplvl_1\ \ 40\ \ \ \ \ \ \ \ \;#\ \ \ 21603.1\ microseconds\ per\ iteration,\ factor\ \ 4.66\ntime\ m_tailcall_try\ \ \ 40\ \ \ \ \ \ \ \ \;#\ \ \ 21698.4\ microseconds\ per\ iteration,\ factor\ \ 4.68\ntime\ s_uplevel_0_list\ 100\ \ \ \ \ \ \ \;#\ \ \ 84963.3\ microseconds\ per\ iteration,\ factor\ 18.34\ntime\ s_eval_list\ \ \ \ \ \ 100\ \ \ \ \ \ \ \;#\ \ \ 85519.3\ microseconds\ per\ iteration,\ factor\ 18.46\ntime\ s_catch_list\ \ \ \ \ 100\ \ \ \ \ \ \ \;#\ \ \ 85919.9\ microseconds\ per\ iteration,\ factor\ 18.54\ntime\ s_time_list\ \ \ \ \ \ 100\ \ \ \ \ \ \ \;#\ \ \ 85944.2\ microseconds\ per\ iteration,\ factor\ 18.55\ntime\ s_if_1_list\ \ \ \ \ \ 100\ \ \ \ \ \ \ \;#\ \ \ 87269.0\ microseconds\ per\ iteration,\ factor\ 18.84\ntime\ s_expand_list\ \ \ \ 100\ \ \ \ \ \ \ \;#\ \ \ 93096.9\ microseconds\ per\ iteration,\ factor\ 20.09\ntime\ s_tailcall\ \ \ \ \ \ \ 100\ \ \ \ \ \ \ \;#\ \ \ 94473.5\ microseconds\ per\ iteration,\ factor\ 20.39\n======\n\n\n regexp2} CALL {my render eval **\ Summary\ **\n\nInterprets\ data\ as\ a\ a\ Tcl\ script\ and\ evaluates\ it.\n**\ Synopsis\ **\n\n\n\ \ \ \ :\ \ \ '''eval'''\ ''arg''\ ?''arg\ ...''?\ \ \n\n\n\n\n\ \ \ \[Injection\ Attack\]:\ \ \ \n\ \ \ \[introspection\]:\ \ \ \n\ \ \ \[Introspection\]:\ \ \ \n\ \ \ \[Many\ Ways\ to\ eval\]:\ \ \ \n\n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/eval.htm%|%official\ reference\]:\ \ \ \n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/eval.htm%|%man\ page\]:\ \ \ \n\n\n**\ Usage\ **\n\n`\[\[\[if\]\ 1\ ...\]`,\ which\ is\ byte-compiled,\ is\ an\ efficient\ replacement\ for\n`\[\[\[eval\]\]`\ in\ all\ cases.\ \ Thus,\ modern\ Tcl\ code\ has\ zero\ use\ for\ `\[\[eval\]`.\n\nTo\ avoid\ the\ caveats\ of\ `\[\[eval\]`\ the\ rule\ of\ thumb\ is\ to\ pass\ only\ one\nargument\ to\ `\[\[eval\]`.\ \ Passing\ a\ single\ script,\ rather\ than\ relying\ on\nimplicit\ concatenation\ helps\ to\ avoid\ dumb\ mistakes\ such\ as\ passing\ a\ string\nwhich\ contains\ newlines.\n\n\n\n'''`eval`'''\ concatenates\ its\ arguments\ in\ the\ same\ fashion\ as\n'''`\[\[eval\]`'''\ concatenates\ its\ arguments\ in\ the\ same\ fashion\ as\n`\[\[\[concat\]\]`,\ and\ hands\ them\ to\ the\ interpreter\ to\ be\ evaluated\ as\ a\ Tcl\nscript.\ \ It\ then\ returns\ the\ result\ of\ that\ evaluation\ or\ any\ error\ generated\nby\ it.\n`eval`\ is\ an\ old,\ old\ command\ that's\ been\ in\ \[Tcl\]\ from\ the\ beginning.\n`\[\[\[eval\]\]`\ is\ an\ old,\ old\ command,\ that's\ been\ in\ \[Tcl\]\ from\ the\ beginning.\n`eval`\ is\ useful\ when\ one\ wishes\ to\ generate\ a\ script\ and\ then\ interpret\ it.\n`\[\[eval\]`\ is\ useful\ when\ one\ wishes\ to\ generate\ a\ script\ and\ then\ interpret\ it.\nIn\ modern\ Tcl,\ `\[\[eval\]`\ is\ merely\ an\ abbreviation\ for\ `\[\[\[uplevel\]\ 0\]`.\ \ This\n'''self-modifying\ programs''',\ and\ related\ esoterica.\n\"self-modifying\ programs\",\ and\ related\ esoterica.\n`\[if\]\ 1\ ...`,\ which\ may\ be\ \[bytecode%|%byte-compiled\],\ is\ an\ efficient\n`eval`\ is\ used\ by\ \ all\ the\ commands\ --\ `\[bind\]`,\ everything\ with\n`\[\[eval\]`\ is\ used\ by\ \ all\ the\ commands\ --\ `\[\[\[bind\]\]`,\ everything\ with\n\nWhen\ using\ `eval`,\ it\ is\ very\ easy\ to\ leave\ holes\ which\ can\ be\ exploited\ to\nWhen\ using\ `\[\[eval\]`,\ it\ is\ very\ easy\ to\ leave\ holes\ which\ can\ be\ exploited\ to\ninject\ malicious\ code,\ so\ it\ is\ best\ to\ exercise\ extreme\ care\ with\ it\ until\ one\n\n`eval`\ can\ often\ be\ avoided,\ particularly\ with\ more\ modern\ recent\ versions\ of\n`\[\[eval\]`\ can\ often\ be\ avoided,\ particulary\ with\ more\ modern\ recent\ versions\ of\n\n\n\n**\ Is\ `\[\[eval\]`\ Evil?\ **\nShort\ answer:\ No.\ \ Like\ many\ commands\ in\ Tcl,\ `eval`\ can\ lead\ to\ \[double\nShort\ answer:\ No.\ \ Like\ many\ commands\ in\ Tcl,\ `\[\[eval\]`\ can\ lead\ to\ \[double\nskilled\ Tcl\ programmer\ knows\ how\ to\ wield\ \[double\ substitution\].\nskilled\ Tcl\ programmer\ learns\ how\ to\ wield\ \[double\ substitution\].\nHistorically,\ `eval`\ was\ often\ used\ with\ exec,\ to\ flatten\ lists,\ allowing\n\nHistorically,\ `\[\[\[eval\]\]`\ was\ often\ used\ with\ exec,\ to\ flatten\ lists,\ allowing\na\ single\ list\ to\ provide\ multiple\ arguments\ to\ a\ command:\ \n======\n#warning:\ no-longer\ recommended\neval\ exec\ grep\ foo\ \$filelist\n======\n\nbecause\ otherwise\ ''grep''\ would\ receive\ filelist\ as\ one\ long\ filename\ with\ embedded\ blanks.\nIn\ modern\ Tcl,\ the\ following\ is\ preferred:\nIn\ modern\ Tcl,\ the\ following\ is\ preferred\ for\ reasons\ of\ efficiency\ and\ safety:\nexec\ grep\ foo\ \{*\}\$filelist\n======\n\nOr,\ if\ you\ want\ to\ append\ one\ list's\ elements\ to\ another,\ and\ you're\ willing\ to\ assume\ that\ the\ variable\ containing\ the\ new\ elements\ doesn't\ embed\ any\ unquoted\ semicolons\ or\ newlines:\nembedded\ blanks.\ Or,\ if\ you\ want\ to\ append\ one\ list's\ elements\ to\ another:\n======\neval\ lappend\ thislist\ \$thatlist\nset\ thislist\ \[concat\ \$thislist\ \$thatlist\]\ \;#\ can\ also\ be\ done\ as\n======\n\nThough\ the\ following\ two\ options\ are\ safer\ and\ faster:\nstring)\ and\ finally\ calling\n\n======\neval\ \$script\n======\n\nWhen\ the\ script\ contains\ only\ one\ command,\ \[argument\ expansion\]\ is\ preferred:\n\n======\n\{*\}\$cmd\n======\n\n**\ Expanding\ Lists\ with\ `eval`\ **\n**\ Expanding\ Lists\ with\ `\[\[eval\]`\ **\nPrior\ to\ Tcl\ version\ 8.5,\ one\ use\ case\ for\ `eval`\ was\ to\ expand\ lists.\nPrior\ to\ Tcl\ version\ 8.5,\ one\ use\ case\ for\ `\[\[eval\]`\ was\ to\ expand\ lists.\nThere\ is\ no\ longer\ any\ reason\ to\ do\ this.\ \ Use\ `\[\{*\}\]`\ instead.\nSee\ \[Argument\ expansion\].\n\n----\nInstead\ of:\n\n\n======\n#warning:\ not\ recommended\neval\ pack\ \[winfo\ children\ .\]\n======\n\nuse:\n\n======\npack\ \{*\}\[winfo\ children\ .\]\n======\n\n----\n\nAnd\ instead\ of:\n\n======\n#warning:\ this\ is\ not\ recommended\nset\ filepath\ \[list\ path\ to\ the\ file\]\neval\ file\ join\ \$filepath\n======\n\nuse:\n\n======\nset\ filepath\ \[list\ path\ to\ the\ file\]\nfile\ join\ \{*\}\$filepath\n======\n\n----\nAnother\ similar\ example\n\n\n======\n#the\ old\ (bad)\ way\nset\ f\ \[glob\ *.tcl\]\neval\ \[linsert\ \$f\ 0\ exec\ lp\]\n======\n\n======\n#the\ shiny\ new\ way\nexec\ lp\ \{*\}\$f\n======\n\n\n***\ Historical\ ***\n\nThe\ following\ describes\ the\ situation\ before\ the\ advent\ of\ \[\{*\}\]:\n\nNaive\ code\ might\ look\ like\ this\ (an\ actual\ example\ from\ BWidget's\nentry.tcl:97):\n\n======\n#warning:\ bad\ code\ ahead!\neval\ entry\ \$path\ \$maps(:cmd)\n======\n\nAn\ unsuccessful\ attempt\ to\ fix\ the\ problem:\nAn\ unsuccesful\ attempt\ to\ fix\ the\ problem:\n======\n#warning:\ bad\ code\ ahead!\neval\ entry\ \[list\ \$path\]\ \$maps(:cmd)\n======\n\nBut\ `\$maps(:cmd)`\ might\ be\ a\ string\ with\ newlines:\n\n======\nset\ maps(:cmd)\ \{\n\ \ \ \ -opt1\ val1\n\ \ \ \ -opt2\ val2\n\}\n======\n\nIt's\ necessary\ to\ first\ convert\ `\$maps(:cmd)`\ to\ a\ proper\ list\ using\ one\ of\ the\nlist\ commands:\n\n======\neval\ \[linsert\ \$maps(:cmd)\ 0\ entry\ \$path\]\n======\n\n***\ See\ Also\ ***\n\n\ \ \ \[http://code.activestate.com/lists/tcl-core/414/%|%RE:\ TCLCORE\ Re:\ CFV:\ TIPs\ #156\ and\ #157\],\ \[Jeff\ Hobbs\],\ \[Tcl\ Core\ Team%|%tcl-core\ mailing\ list\],\ 2003-10-12:\ \ \ \[AMG\]:\ Text\ repeated\ below,\ please\ read\ it\ until\ you\ understand\ what\ trouble\ \[\[eval\]\]\ buys\ you\ and\ how\ helpful\ \[\{*\}\]\ is.\n\ \ \ \[http://web.archive.org/web/20060325121839/http://aspn.activestate.com/ASPN/Mail/Message/tcl-core/1748289%|%TCLCORE\ TIP\ #144:\ Argument\ Expansion\ Syntax\],\ by\ \[tclguy\]:\ \ \ \n\ \ \ \[http://web.archive.org/web/20060325121839/http://aspn.activestate.com/ASPN/Mail/Message/tcl-core/1748289%|%TCLCORE\ TIP\ #144:\ Argument\ Expansion\ Syntax\],\ \[Jeff\ Hobbs\],\ \[Tcl\ Core\ Team%|%tcl-core\ mailing\ list\],\ 2003-07-26:\ \ \ \n\ \ \ \[http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/c3d6651005e12629/a9dc3e05d95b0f12?hl=en&ie=UTF-8&q=argument+expansion+apply+variadic+group:comp.lang.tcl*#%|%eval\ is\ evil\ (for\ spreading\ list-arguments)\]\ ,\[comp.lang.tcl\]\ ,2003-03-11:\ \ \ \n****\ Re:\ CFV:\ TIPs\ #156\ and\ #157\ ****\n\n\nThe\ arguments\ to\ `eval`\ are\ concatenated\ into\ a\ string\ to\ be\ interpreted,\ but\nThe\ arguments\ to\ \[\[eval\]\ are\ concatenated\ into\ a\ string\ to\ be\ interpreted,\ but\n(i.e.,\ one\ conforming\ to\ the\ Tcl\ parsing\ rules\ as\ laid\ out\ in\ the\ Tcl\ manual\npage).\n\nThe\ following\ script\ breaks\ because\ the\ concatenation\ keeps\ the\ newlines\ from\nthe\ list's\ string\ representation,\ making\ `eval`\ interpret\ the\ second\ element\nthe\ list's\ string\ representation,\ making\ \[\[eval\]\]\ interpret\ the\ second\ element\n\n======none\n%\ set\ arg\ \{a\nb\nc\n\}\na\nb\nc\n%\ eval\ list\ \$arg\nambiguous\ command\ name\ \"b\":\ bgerror\ binary\ break\n======\n\nTo\ solve\ this,\ construct\ the\ argument\ using\ list\ primitives\ like\ `\[lappend\]`,\nTo\ solve\ this,\ construct\ the\ argument\ using\ list\ primitives\ like\ \[lappend\],\n\[list\],\ etc.\ \ DKF\ says:\ \ \"list\ and\ eval\ are\ truly\ made\ for\ each\ other.\"\nAnother\ solution\ is\ to\ use\ the\ following\ idiom:\n\n======none\n%\ eval\ \[linsert\ \$arg\ 0\ list\]\na\ b\ c\n======\n\n`\[linsert\]`\ converts\ its\ list\ argument\ to\ a\ well-formed\ list\ with\ single\n`\[\[\[linsert\]\]`\ converts\ its\ list\ argument\ to\ a\ well-formed\ list\ with\ single\nof\ these\ elements\ contain\ newlines,\ they\ remain\ in\ the\ resulting\ string).\n\nIt's\ important\ to\ remember\ that\ `eval`\ works\ on\ '''strings''',\ not\ lists,\nIt's\ important\ to\ remember\ that\ `\[\[\[eval\]\]`\ works\ on\ '''strings''',\ not\ lists,\nfor\ interpreting\ a\ string\ as\ a\ script.\n\n\n**\ Verbose\ Evaluation\ **\n\n\[LV\]:\ I\ just\ had\ to\ copy\ this\ over\ to\ the\ wiki\ -\ it\ is\ so\ neat!\n\nFrom\ comp.lang.tcl,\ \[Bob\ Techentin\]\ writes\ in\ response\ to\ a\ poster:\n\nIt\ sounds\ like\ you're\ looking\ for\ something\ similar\ to\ /bin/sh\ \"set\ -v\"\ command\nwhich\ prints\ shell\ input\ lines\ as\ they\ are\ read,\ and\ \"set\ -x\"\ which\ prints\nexpanded\ commands.\ \ Kind\ of\ like\ a\ verbose\ mode.\n\nNope.\ \ Nothing\ like\ that.\ \ But\ you\ wouldn't\ have\ to\ write\ your\ own\ shell.\ \ You\ncould\ walk\ through\ a\ script\ (a\ list\ of\ lines),\ and\ use\ `\[info\ complete\]`\ to\ncould\ walk\ through\ a\ script\ (a\ list\ of\ lines),\ and\ use\ `\[\[\[info\ complete\]\]`\ to\ncommand\ and\ the\ command's\ results.\ \ This\ seems\ to\ work.\n\n======\nproc\ verbose_eval\ \{script\}\ \{\n\ \ \ \ set\ cmd\ \{\}\ \n\ \ \ \ set\ cmd\ \"\"\n\ \ \ \ if\ \{\$line\ eq\ \{\}\}\ \{continue\}\n\ \ \ \ if\ \{\$line\ eq\ \"\"\}\ \{continue\}\n\ \ \ \ \ \ \ \ if\ \{\[info\ complete\ \$cmd\]\}\ \{\n\ \ \ \ \ \ \ \ if\ \{\ \[info\ complete\ \$cmd\]\ \}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ puts\ -nonewline\ \[uplevel\ 1\ \$cmd\]\n\ \ \ \ \ \ \ \ \ \ \ \ set\ cmd\ \"\"\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\}\n\nset\ script\ \{\n\ \ \ \ puts\ hello\n\ \ \ \ expr\ \{2.2\ *\ 3\}\n\ \ \ \ expr\ 2.2*3\n\nverbose_eval\ \$script\ \n======\n\n\[LV\]:\ This\ proc\ is\ so\ slick!\ I\ love\ it!\n\[LV\]\ This\ proc\ is\ so\ slick!\ I\ love\ it!\n\[Lars\ H\]:\ \ Another\ approach\ to\ this\ (which\ also\ can\ see\ individual\ commands\ in\n`\[if\]`\ branches,\ loop\ bodies,\ etc.)\ is\ to\ use\ `\[trace\]`s.\ Do\ we\ have\ that\ written\n\[if\]\ branches,\ loop\ bodies,\ etc.)\ is\ to\ use\ \[trace\]s.\ Do\ we\ have\ that\ written\n\n\[AR\]\ Here\ is\ my\ proposal\ with\ traces.\ Rem:\ the\ \"noop\"\ string\ is\ some\ kind\ of\ magic\ cookie.\n\n\n\[wtracy\]\ 2008-06-23:\ I\ want\ the\ commands\ I\ run\ in\ eval\ to\ have\ their\ own\ set\ of\nvariables\ independently\ of\ the\ calling\ script.\ Is\ there\ some\ way\ I\ can\ hand\neval\ a\ context\ (maybe\ as\ an\ associative\ array?).\n\n\[Lars\ H\]:\ Sounds\ like\ you\ want\ a\ \[lambda\]\ (or\ possibly\ a\ \[closure\],\ which\ is\nmore\ difficult).\ If\ you're\ using\ Tcl\ 8.5,\ then\ have\ a\ look\ at\ `\[apply\]`.\nmore\ difficult).\ If\ you're\ using\ Tcl\ 8.5,\ then\ have\ a\ look\ at\ `\[\[\[apply\]\]`.\n\[RS\]:\ Long\ before\ 8.5,\ you\ could\ always\ write\ a\ little\ proc\ to\ hide\ its\ local\nvariables\ (x\ in\ this\ example):\n\n======none\n%\ eval\ \{proc\ \{\}\ x\ \{expr\ \{\$x*\$x\}\}\;\ \{\}\ 5\}\n%\ eval\ \{proc\ \{\}\ x\ \{expr\ \$x*\$x\}\;\ \{\}\ 5\}\n======\n\n\[wtracy\]:\ Thanks.\ It\ looks\ like\ `\[apply\]`\ is\ the\ closest\ Tcl\ feature\ to\ what\n\[wtracy\]:\ Thanks.\ It\ looks\ like\ `\[\[\[apply\]\]`\ is\ the\ closest\ Tcl\ feature\ to\ what\n\n\[wtracy\]:\ Actually,\ it\ looks\ like\ what\ I\ *really*\ want\ is\ to\ nest\ `eval`\n\[wtracy\]:\ Actually,\ it\ looks\ like\ what\ I\ *really*\ want\ is\ to\ nest\ `\[\[eval\]`\ninside\ of\ a\ `\[\[\[namespace\ eval\]\]`\ block.\n\[wtracy\]:\ Okay,\ for\ the\ sake\ of\ any\ lost\ soul\ that\ comes\ along\ after\ me,\ this\nis\ what\ I\ really\ wanted\ to\ do\ all\ along:\n\n======none\n\$\ set\ cmd\ \{puts\ FOO\}\n>\ set\ cmd\ \{puts\ FOO\}\n\$\ namespace\ eval\ MyNameSpace\ \$cmd\n>\ namespace\ eval\ MyNameSpace\ \$cmd\n======\n\n\[NEM\]:\ As\ mentioned,\ `\[apply\]`\ is\ probably\ a\ better\ choice\ in\ this\ case\ as\ it\n\[NEM\]\ As\ mentioned,\ `\[\[\[apply\]\]`\ is\ probably\ a\ better\ choice\ in\ this\ case\ as\ it\n\[dangers\ of\ creative\ writing\]\ for\ some\ related\ discussion.\ The\ `\[apply\]`\ version\ is:\n\[dangers\ of\ creative\ writing\]\ for\ some\ related\ discussion.\ The\ apply\ version\ is:\n======\napply\ \{\{\}\ \{puts\ FOO\}\ ::MyNameSpace\}\napply\ \{\{\}\ \{\ puts\ FOO\ \}\ ::MyNameSpace\}\n\nThis\ has\ the\ benefit\ of\ evaluating\ the\ code\ within\ a\ fresh\ procedure\ context,\nmeaning\ all\ variables\ are\ local\n\nto\ that\ context\ by\ default.\ See\ also\ `\[namespace\ inscope\]`/`\[namespace\ code\]`\ and\nto\ that\ context\ by\ default.\ See\ also\ \[namespace\ inscope\]/\[namespace\ code\]\ and\nyou\ may\ also\ like\ \[dict\ with\].\n\n**\ Proposal:\ Modify\ `eval`\ to\ Accept\ a\ List\ of\ Lists\ \ **\n**\ Proposal:\ Modify\ `\[\[eval\]`\ to\ Accept\ a\ List\ of\ Lists\ \ **\nIn\ some\ cases\ `eval`\ does\ work\ on\ lists\ -\ and\ its\ special.\ \ In\ particular,\nIn\ some\ cases\ `\[\[\[eval\]\]`\ does\ work\ on\ lists\ -\ and\ its\ special.\ \ In\ particular,\nif\ eval\ is\ passed\ a\ \[pure\ list\]\ then\ it\ gets\ evaluated\ directly,\ without\nwhat\ it\ ''could''\ be.\n\nWhen\ you\ pass\ eval\ a\ pure\ list,\ you\ can\ only\ execute\ a\ single\ command.\ \ What\ if\nwe\ were\ to\ pass\ eval\ a\ list\ of\ pure\ lists\ -\ it\ should\ directly\ evaluate\ each\ of\nthem,\ and\ return\ the\ value\ of\ the\ the\ last\ one\ evaluated.\ \ This\ sounds\ a\ lot\nlike\ progn\ in\ \[lisp\],\ and\ it\ seems\ like\ it\ would\ allow\ for\ some\ nifty\ bits\ of\n\[introspection\]\ -\ for\ example,\ if\ `\[info\ body\]`\ returned\ a\ pure\ list\ of\ lists\n\[introspection\]\ -\ for\ example,\ if\ \[info\ body\]\ returned\ a\ pure\ list-of-lists\nwhole\ program\ becomes\ a\ list\ of\ lists.\n\nThe\ problem\ is\ how\ to\ signal\ to\ `eval`\ (or\ `\[uplevel\]`,\ `\[namespace\]`,\ `\[bind\]`,\ ...)\ that\ it\nThe\ problem\ is\ how\ to\ signal\ to\ eval\ (or\ uplevel,\ namespace,\ bind,\ ...)\ that\ it\nis\ a\ list\ of\ lists\ rather\ than\ just\ a\ list.\ \ Could\ eval\ determine\ if\ its\ input\nprogn?\n\nAnother\ place\ this\ seems\ like\ it\ could\ be\ useful:\ I\ have\ a\ \[pkgIndex.tcl\]\ file\ with\nAnother\ place\ this\ seems\ like\ it\ could\ be\ useful:\ I\ have\ a\ pkgIndex\ file\ with\n\npackage\ ifneeded\ tls\ 1.4\ \[\npackage\ ifneeded\ tls\ 1.4\ \"\[list\ load\ \[file\ join\ \$dir\ libtls1.4.so\]\]\;\[list\ source\ \[file\ join\ \$dir\ tls.tcl\]\]\"\n\nwhere\ most\ of\ the\ lines\ are\ like\n\n======\npackage\ ifneeded\ tclperl\ 2.3\ \[list\ load\ \[file\ join\ \$dir\ tclperl.so\]\]\n======\n\nsince\ they\ only\ need\ one\ command\;\ but\ the\ tls\ line\ needs\ two\ commands.\ \ So\ why\ can't\ it\ be\n\n======\npackage\ ifneeded\ tls\ 1.4\ \[list\ \[\npackage\ ifneeded\ tls\ 1.4\ \[list\ \[list\ load\ \[file\ join\ \$dir\ libtls1.4.so\]\]\ \[list\ source\ \[file\ join\ \$dir\ tls.tcl\]\]\]\n\n\n\n\n\[RS\]\ 2004-02-06:\ As\ usual\ in\ Tcl,\ functionality\ you\ miss\ you\ can\ easy\ roll\nyourself.\ I\ needed\ a\ progn-like\ list\ eval\ in\ \[RPN\ again\],\ and\ did\ it\ similar\ to\nthis:\n\n======\nproc\ leval\ args\ \{\n\ \ \ \ foreach\ arg\ \$args\ \{\n\ \ \ \ \ \ \ \ set\ res\ \[uplevel\ 1\ \$arg\]\n\ \ \ \ \}\n\ \ \ \ set\ res\ \;#\ return\ last\ (\"n-th\")\ result,\ as\ Tcl\ evaluation\ does\n\}\n======\n\n\n\n**\ eval\ versus\ bytecode\ **\n**\ `eval`\ versus\ bytecode\ **\n\[AMG\]:\ It\ appears\ `\[\[eval\]\]`'ed\ code\ does\ not\ get\ \[bytecode\]-compiled,\ even\nwhen\ \[\[eval\]\]\ is\ passed\ a\ single\ brace-quoted\ argument.\ \ The\ same\ is\ true\ for\n`\[\[\[uplevel\]\ 0\]`\ and\ `\[\[\[time\]\]`.\ \ `\[\[\[catch\]\]`\ and\ `\[\[\[if\]\ \{1\}\]\]`\ seem\ to\ be\n\"argument\",\ rather\ a\ single\ command\ line\ pre-chewed\ into\ an\ objv\ list.\nBytecoding\ cannot\ take\ place\ when\ the\ argument\ is\ the\ product\ of\ `\[list\]`,\nBytecoding\ cannot\ take\ place\ when\ the\ argument\ is\ the\ product\ of\ `\[\[\[list\]\]`,\n\n======\nproc\ a\ \{\}\ \{eval\ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ b\ \{\}\ \{uplevel\ 0\ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ c\ \{\}\ \{time\ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ d\ \{\}\ \{catch\ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ e\ \{\}\ \{if\ \{1\}\ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ f\ \{\}\ \{\ \ \ \ \ \ \ \ \ \ \ \ \{*\}\{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ g\ \{\}\ \{eval\ \ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ h\ \{\}\ \{uplevel\ 0\ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ i\ \{\}\ \{time\ \ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ j\ \{\}\ \{catch\ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ k\ \{\}\ \{if\ \{1\}\ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ l\ \{\}\ \{\ \ \ \ \ \ \ \{*\}\[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ m\ \{\}\ \{try\ \ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\na\;b\;c\;d\;e\;f\;g\;h\;i\;j\;k\;l\;m\ntime\ a\ 10\ \ \ \ \;#\ \ 80723.8\ microseconds\ per\ iteration\ -\ slow\ntime\ b\ 10\ \ \ \ \;#\ \ 65380.2\ microseconds\ per\ iteration\ -\ slow\ntime\ c\ 10\ \ \ \ \;#\ \ 66024.8\ microseconds\ per\ iteration\ -\ slow\ntime\ d\ 100\ \ \ \;#\ \ 18888.3\ microseconds\ per\ iteration\ -\ fast\ntime\ e\ 100\ \ \ \;#\ \ 18779.3\ microseconds\ per\ iteration\ -\ fast\ntime\ f\ 100\ \ \ \;#\ \ 19375.2\ microseconds\ per\ iteration\ -\ fast\ntime\ g\ 10\ \ \ \ \;#\ 319111.5\ microseconds\ per\ iteration\ -\ very\ slow\ntime\ h\ 10\ \ \ \ \;#\ 342878.4\ microseconds\ per\ iteration\ -\ very\ slow\ntime\ i\ 10\ \ \ \ \;#\ 322279.2\ microseconds\ per\ iteration\ -\ very\ slow\ntime\ j\ 10\ \ \ \ \;#\ 316939.0\ microseconds\ per\ iteration\ -\ very\ slow\ntime\ k\ 10\ \ \ \ \;#\ 321865.5\ microseconds\ per\ iteration\ -\ very\ slow\ntime\ l\ 10\ \ \ \ \;#\ 344009.5\ microseconds\ per\ iteration\ -\ very\ slow\ntime\ m\ 100\ \ \ \;#\ \ 19503.0\ microseconds\ per\ iteration\ -\ fast\n======\n\nI\ want\ single-argument\ `eval`\ functionality\ in\ my\ code,\ but\ I\ also\ want\nI\ want\ single-argument\ `\[\[\[eval\]\]`\ functionality\ in\ my\ code,\ but\ I\ also\ want\nbytecoding.\ \ `\[\[\[catch\]\]`\ has\ the\ undesirable\ side\ effect\ of\ hiding\ errors,\ so\nI\ guess\ I\ have\ to\ use\ `\[\[\[if\]\ \{1\}\]`\ which\ is\ a\ really\ weird\ idiom.\ \ Does\ anyone\n\n\[AMG\]:\ I\ reran\ the\ tests\ and\ got\ better\ numbers.\ \ The\ current\ version\ of\ Tcl\nmust\ be\ faster\ than\ whatever\ I\ used\ when\ I\ first\ did\ this\ benchmark\ (I'm\ using\nthe\ same\ computer).\ \ Look\ in\ the\ page\ history\ to\ see\ the\ comparison.\ \ More\nimportantly,\ I\ think\ I\ found\ a\ bytecoded\ `eval`:\ single-argument\ `\[try\]`.\nimportantly,\ I\ think\ I\ found\ a\ bytecoded\ \[\[eval\]\]:\ single-argument\ \[\[\[try\]\]\].\nmethods.\ \ It's\ considerably\ less\ weird\ than\ `\[if\]\ 1`,\ and\ it\ doesn't\ hide\nmethods.\ \ It's\ considerably\ less\ weird\ than\ \[\[if\ \{1\}\]\],\ and\ it\ doesn't\ hide\n\n\[DKF\]:\ We've\ been\ focusing\ a\ bit\ more\ on\ improving\ the\ most\ cripplingly-slow\ncases,\ but\ three\ execution\ modes\ still\ exist\ that\ have\ fundamentally\ different\nspeeds.\ There's\ compilation\ to\ bytecode-with-local-var-table\ (which\ is\ the\nfastest\;\ the\ speed\ comes\ from\ being\ able\ to\ compile\ in\ indexes\ into\ the\ LVT\ninto\ the\ generated\ bytecode,\ which\ this\ test\ is\ particularly\ sensitive\ to),\nthere's\ compilation\ to\ bytecode-without-LVT\ (slower\;\ variables\ have\ to\ be\nlooked\ up\ each\ time\ they're\ accessed),\ and\ there's\ interpreting\ (slowest\ by\nfar).\ There's\ not\ much\ point\ in\ doing\ a\ lot\ of\ comparison\ between\ the\ three\;\nthey\ all\ exist\ for\ a\ reason.\ (We\ could\ make\ straight\ `eval`/`\[uplevel\]\nthey\ all\ exist\ for\ a\ reason.\ (We\ could\ make\ straight\ '''eval'''/'''\[uplevel\]\n0'''\ of\ constant\ arguments\ work\ at\ full\ speed,\ but\ we\ see\ no\ reason\ to\ bother\ngiven\ how\ rare\ they\ are\ in\ real\ code,\ and\ it's\ better\ that\ \[time\]\ is\ kept\nto\ get\ by\ using\ `\[::tcl::unsupported::disassemble\]`\ to\ look\ at\ the\ bytecode\ to\ see\nto\ get\ by\ using\ \[tcl::unsupported::disassemble\]\ to\ look\ at\ the\ bytecode\ to\ see\ndone\ by\ just\ building\ arguments\ and\ invoking\ “cnormal”\ commands.\ndone\ by\ just\ building\ arguments\ and\ invoking\ “normal”\ commands.\n\[Twylite\]\ 2012-08-24:\ \ I've\ been\ optimising\ some\ control\ constructs\ and\ was\ntrying\ to\ understand\ the\ performance\ of\ various\ combinations\ of\ uplevel,\ntailcall,\ catch\ and\ try.\ \ Along\ the\ way\ I\ found\ \[AMG\]'s\ performance\ figures,\nand\ have\ updated\ them\ with\ some\ new\ ones:\n\n======\n#\ Fast\ (prefix\ f)\nproc\ f_baseline\ \ \ \ \ \ \ \{\}\ \{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\ \}\nproc\ f_catch\ \ \ \ \ \ \ \ \ \ \{\}\ \{catch\ \ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ f_catch\ \ \ \ \ \ \ \ \ \ \{\}\ \{catch\ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ f_if_1\ \ \ \ \ \ \ \ \ \ \ \{\}\ \{if\ \{1\}\ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ f_expand\ \ \ \ \ \ \ \ \ \{\}\ \{\ \ \ \ \ \ \ \ \ \ \ \ \ \{*\}\{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ f_try\ \ \ \ \ \ \ \ \ \ \ \ \{\}\ \{try\ \ \ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ f_time_apply\ \ \ \ \ \{\}\ \{time\ \{apply\ \{\{\}\ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\}\}\n#\ Medium\ (prefix\ m)\ \ \ \ \ \ \ \ \ \ \ \ \ \nproc\ m_eval\ \ \ \ \ \ \ \ \ \ \ \{\}\ \{eval\ \ \ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ m_eval\ \ \ \ \ \ \ \ \ \ \ \{\}\ \{eval\ \ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ m_uplevel_0\ \ \ \ \ \ \{\}\ \{uplevel\ 0\ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ m_time\ \ \ \ \ \ \ \ \ \ \ \{\}\ \{time\ \ \ \ \ \ \ \ \ \ \ \ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ m_tailcall_try\ \ \ \{\}\ \{tailcall\ \ \ \ try\ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\}\nproc\ m_catch_uplvl_1\ \ \{\}\ \{\ \ \ \ \ \ \ set\ body\ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\ \;\ catch\ \{\ uplevel\ 1\ \$body\ \}\ \}\ \ \nproc\ m_uplvl_1_catch\ \ \{\}\ \{\ \ \ \ \ \ \ set\ body\ \{for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\}\ \;\ uplevel\ 1\ \[list\ catch\ \$body\]\ \}\ \ \n#\ Slow\ (prefix\ s)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \nproc\ s_eval_list\ \ \ \ \ \ \{\}\ \{eval\ \ \ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ s_uplevel_0_list\ \{\}\ \{uplevel\ 0\ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ s_time_list\ \ \ \ \ \ \{\}\ \{time\ \ \ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ s_catch_list\ \ \ \ \ \{\}\ \{catch\ \ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ s_if_1_list\ \ \ \ \ \ \{\}\ \{if\ 1\ \ \ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ s_if_1_list\ \ \ \ \ \ \{\}\ \{if\ \{1\}\ \ \ \ \ \[list\ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\]\}\nproc\ s_tailcall\ \ \ \ \ \ \ \{\}\ \{tailcall\ \ \ \ \ \ \ \ \ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100000\}\ \{incr\ i\}\ \{\}\ \}\n\nif\ 0\ \{\nif\ \{0\}\ \{\n\ \ set\ REPS\ \{f\ 10\ m\ 40\ s\ 100\}\ \;#\ reps\ by\ prefix\n\ \ set\ cmds\ \{f_baseline\ f_catch\ f_if_1\ f_expand\ f_try\ f_time_apply\ \n\ \ \ \ m_eval\ m_uplevel_0\ m_time\ m_tailcall_try\ m_catch_uplvl_1\ m_uplvl_1_catch\ \n\ \ \ \ s_eval_list\ s_uplevel_0_list\ s_time_list\ s_catch_list\ s_if_1_list\ \n\ \ \ \ s_expand_list\ s_tailcall\}\n\ \ \n\ \ foreach\ cmd\ \$cmds\ \{\ \$cmd\ \}\ \;#\ compile\n\ \ set\ cmdrepstimes\ \{\}\ \;\ foreach\ cmd\ \$cmds\ \{\ \;#\ time\n\ \ \ \ set\ reps\ \[dict\ get\ \$::REPS\ \[string\ index\ \$cmd\ 0\]\]\ \n\ \ \ \ lappend\ cmdrepstimes\ \[lindex\ \[time\ \$cmd\ \$reps\]\ 0\]\ \$cmd\ \$reps\ \n\ \ \}\n\ \ \n\ \ set\ mintime\ \[::tcl::mathfunc::min\ \{*\}\$times\]\n\ \ foreach\ \{t\ cmd\ reps\}\ \[lsort\ -real\ -stride\ 3\ \$cmdrepstimes\]\ \{\n\ \ \ \ puts\ \[format\ \"time\ %-16s\ \$reps\\t\;#\ %9.1f\ microseconds\ per\ iteration,\ factor\ %5.2f\"\ \\\n\ \ \ \ \ \ \$cmd\ \$t\ \[expr\ \{\ \$t\ /\ \$mintime\ \}\]\ \]\ \n\ \ \}\n\ntime\ f_time_apply\ \ \ \ \ 10\ \ \ \ \ \ \ \ \;#\ \ \ \ 4625.8\ microseconds\ per\ iteration,\ factor\ \ 1.00\ntime\ f_if_1\ \ \ \ \ \ \ \ \ \ \ 10\ \ \ \ \ \ \ \ \;#\ \ \ \ 4641.8\ microseconds\ per\ iteration,\ factor\ \ 1.00\ntime\ f_expand\ \ \ \ \ \ \ \ \ 10\ \ \ \ \ \ \ \ \;#\ \ \ \ 4645.0\ microseconds\ per\ iteration,\ factor\ \ 1.00\ntime\ f_catch\ \ \ \ \ \ \ \ \ \ 10\ \ \ \ \ \ \ \ \;#\ \ \ \ 4651.3\ microseconds\ per\ iteration,\ factor\ \ 1.00\ntime\ f_baseline\ \ \ \ \ \ \ 10\ \ \ \ \ \ \ \ \;#\ \ \ \ 4658.5\ microseconds\ per\ iteration,\ factor\ \ 1.01\ntime\ f_try\ \ \ \ \ \ \ \ \ \ \ \ 10\ \ \ \ \ \ \ \ \;#\ \ \ \ 4735.9\ microseconds\ per\ iteration,\ factor\ \ 1.02\ntime\ m_eval\ \ \ \ \ \ \ \ \ \ \ 40\ \ \ \ \ \ \ \ \;#\ \ \ 18454.3\ microseconds\ per\ iteration,\ factor\ \ 3.98\ntime\ m_uplevel_0\ \ \ \ \ \ 40\ \ \ \ \ \ \ \ \;#\ \ \ 18738.3\ microseconds\ per\ iteration,\ factor\ \ 4.04\ntime\ m_time\ \ \ \ \ \ \ \ \ \ \ 40\ \ \ \ \ \ \ \ \;#\ \ \ 19176.8\ microseconds\ per\ iteration,\ factor\ \ 4.14\ntime\ m_uplvl_1_catch\ \ 40\ \ \ \ \ \ \ \ \;#\ \ \ 21501.1\ microseconds\ per\ iteration,\ factor\ \ 4.64\ntime\ m_catch_uplvl_1\ \ 40\ \ \ \ \ \ \ \ \;#\ \ \ 21603.1\ microseconds\ per\ iteration,\ factor\ \ 4.66\ntime\ m_tailcall_try\ \ \ 40\ \ \ \ \ \ \ \ \;#\ \ \ 21698.4\ microseconds\ per\ iteration,\ factor\ \ 4.68\ntime\ s_uplevel_0_list\ 100\ \ \ \ \ \ \ \;#\ \ \ 84963.3\ microseconds\ per\ iteration,\ factor\ 18.34\ntime\ s_eval_list\ \ \ \ \ \ 100\ \ \ \ \ \ \ \;#\ \ \ 85519.3\ microseconds\ per\ iteration,\ factor\ 18.46\ntime\ s_catch_list\ \ \ \ \ 100\ \ \ \ \ \ \ \;#\ \ \ 85919.9\ microseconds\ per\ iteration,\ factor\ 18.54\ntime\ s_time_list\ \ \ \ \ \ 100\ \ \ \ \ \ \ \;#\ \ \ 85944.2\ microseconds\ per\ iteration,\ factor\ 18.55\ntime\ s_if_1_list\ \ \ \ \ \ 100\ \ \ \ \ \ \ \;#\ \ \ 87269.0\ microseconds\ per\ iteration,\ factor\ 18.84\ntime\ s_expand_list\ \ \ \ 100\ \ \ \ \ \ \ \;#\ \ \ 93096.9\ microseconds\ per\ iteration,\ factor\ 20.09\ntime\ s_tailcall\ \ \ \ \ \ \ 100\ \ \ \ \ \ \ \;#\ \ \ 94473.5\ microseconds\ per\ iteration,\ factor\ 20.39\n======\n\n\n} CALL {my revision eval} CALL {::oo::Obj4132321 process revision/eval} CALL {::oo::Obj4132319 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