Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/tailcall?V=33
QUERY_STRINGV=33
CONTENT_TYPE
DOCUMENT_URI/revision/tailcall
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.70.134.182
REMOTE_PORT41264
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR35.153.106.141
HTTP_CF_RAY86c0cdecc93358d2-IAD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTclaudebot
HTTP_CF_CONNECTING_IP35.153.106.141
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 tailcall \n\n\ \ \ \[wrapping\ commands\]:\ \ \ wrap\ commands\ by\ using\ `\[interp\ invokehidden\]`\ together\ with\ `tailcall`\n\n\n'''`tailcall`'''\ interprets\ its\ arguments\ as\ a\ command\ and\ executes\ the\n`\[\[Tailcall\]`\ is\ made\ possible\ by\ \[NRE\].\ \ It\ first\ became\ available\ as\n`\[\[\[::tcl::unsupported::tailcall\]`\ in\ the\ release\ of\ Tcl8.6a2.\ It\ provides\nproper\ tailcalls,\ with\ the\ following\ semantics:\nUnlike\ some\ other\ languages,\ `tailcall`\ is\ not\ limited\ to\ executing\ only\ its\n\ \ \ *\ a\ proc/lambda\ invokes\ '''\[\[tailcall\ foo\ \[\[bar\]\]\ \$soom\]\]'''\n\ \ \ *\ '''bar'''\ is\ invoked\ and\ the\ value\ of\ '''soom'''\ fetched,\ as\ if\ '''\[\[list\ foo\ \[\[bar\]\]\ \$soom\]\]'''\ had\ been\ called\n\ \ \ *\ a\ command\ named\ '''foo'''\ is\ looked\ up\ ''in\ the\ current\ context''\n\ \ \ *\ the\ current\ proc/lambda\ replaces\ itself\ in\ the\ call\ stack\ with\ a\ call\ to\ the\ just\ found\ command\n`tailcall`\ is\ made\ possible\ by\ \[NRE\].\ \ It\ first\ became\ available\ as\nThat\ is:\ '''tailcall\ foo\ \[\[bar\]\]\ \$soom'''\ is\ very\ similar\ to\ '''return\ \[\[uplevel\ 1\ \[\[list\ foo\ \[\[bar\]\]\ \$soom\]\]\]\]'''\ with\ two\ exceptions:\nContrast\ the\ following\ two\ commands:\n\ \ \ 1.\ '''foo'''\ is\ looked\ up\ in\ the\ ''current''\ context,\ not\ in\ the\ caller's\n\n\nTo\ `tailcall`\ a\ script:\n**\ Usage\ **\n\nWhile\ `\[\[\[uplevel\]\]`\ takes\ a\ script,\ \[\[tailcall\]\ takes\ a\ command.\ \ If\ you\ want\nto\ \[\[tailcall\]\ a\ script\ do\ it\ as\ follows:\n\ntailcall\ try\ \$script\n======\n\n----\n\n\[WHD\]:\ Let\ me\ see\ if\ I\ understand\ what\ this\ does.\n\n======\nproc\ fred\ \{\}\ \{\n\ \ \ \ george\n\}\n\nproc\ george\ \{\}\ \{\n\ \ \ \ \ tailcall\ harry\n\}\n======\n\nIf\ I\ call\ fred,\ it's\ almost\ as\ though\ fred\ called\ harry\ directly,\ instead\ of\ngeorge.\ \ Not\ so?\n\n\[MS\]:\ \ yup\ -\ all\ traces\ of\ george\ are\ gone\ from\ the\ program\ stack\ when\ harry\ is\ncalled.\ Now,\ if\ harry\ resolves\ to\ a\ different\ command\ in\ george's\ current\nnamespace\ than\ it\ would\ under\ fred's,\ the\ harry\ that\ is\ called\ is\ george's\ and\nnot\ fred's\ (no\ diff\ if\ the\ commands\ are\ FQ,\ of\ course).\n\nI\ think\ this\ does\ pretty\ much\ what\ delegation\ is\ supposed\ to\ do,\ right?\n\n----\n\n\[jima\]\ 2009-10-15:\ Perhaps\ this\ has\ been\ asked\ before\ or\ somewhere\ else...\n\nIs\ this\ an\ optimization\ that\ takes\ place\ at\ bytecode\ generation\ time?\n\nI\ mean,\ once\ fred\ knows\ that\ has\ to\ call\ harry\ directly\ the\ bytecodes\ generated\nwould\ be\ the\ ones\ equivalent\ to\ have\ said:\n\n======\nproc\ fred\ \{\}\ \{\n\ \ \ \ harry\n\}\n======\n\nI\ reckon\ I\ am\ not\ familiar\ with\ all\ the\ internals\ of\ Tcl\ but\ I\ find\ this\ would\nbe\ an\ interesting\ thing.\ Wouldn't\ this\ be\ a\ new\ way\ to\ have\ some\ sort\ of\nmacros?\n\n\[MS\]:\ \ Currently,\ `tailcall`\ is\ not\ bytecompiled.\ Everything\ happens\ at\n\[MS\]:\ \ Currently,\ \[\[tailcall\]\ is\ not\ byte\ compiled.\ Everything\ happens\ at\nbut\ things\ get\ more\ involved\ as\ soon\ as\ `fred`\ has\ a\ bit\ more\ structure\ to\nbut\ things\ get\ more\ involved\ as\ soon\ as\ `\[\[fred\]`\ has\ a\ bit\ more\ structure\ to\nlookup,\ multiple\ exit\ points\ with\ different\ (or\ no)\ `tailcall`\ in\ them,\nlookup,\ multiple\ exit\ points\ with\ different\ (or\ no)\ `\[\[\[tailcall\]\]`\ in\ them,\n\n\[jima\]:\ Thanks\ a\ lot\ Miguel\ for\ the\ answer.\ I\ see\ the\ point.\ I\ guess\ this\ is\nthe\ same\ with\ `\[uplevel\]\ 1`,\ isn't\ it?\nthe\ same\ with\ `\[\[\[uplevel\]\ 1\]\]`,\ isn't\ it?\n======\nproc\ fred\ \{\}\ \{\n\ \ \ \ uplevel\ 1\ \{\n\ \ \ \ \ \ \ \ #code\ here\n\ \ \ \ \}\n\}\n======\n\nWould\ it\ be\ interesting\ to\ define\ a\ case\ (like\ a\ contract)\ saying\ if\ your\ proc\nis\ simple\ enough\ then\ it\ gets\ bytecompiled\ and\ you\ get\ some\ benefits?\n\n\[MS\]:\ \ you\ do\ not\ mean\ \"bytecompiled\"\ but\ rather\ \"inlined\ into\ the\ caller\",\ as\nall\ `\[proc\]`\ bodies\ get\ bytecompiled.\ There\ are\ quite\ a\ few\ other\ issues\ with\ that,\nall\ `\[\[\[proc\]\]`\ bodies\ get\ bytecompiled.\ There\ are\ quite\ a\ few\ other\ issues\ with\ that,\ncause\ a\ spoiling\ of\ all\ bytecodes\ and\ recompilation\ of\ the\ world,\ at\ least\ with\nthe\ current\ approach\ to\ bytecode\ lifetime\ management.\nthe\ current\ approach\ to\ bytecode\ lifetime\ management.\ \n----\n\n\[AMG\]:\ Sounds\ a\ lot\ like\ `exec`\ in\ \[Unix\ shells\].\ \ See\ \[execline\]\ for\ more\ninformation\ on\ a\ noninteractive\ Unix\ shell\ where\ everything\ is\ done\ with\nexec/tailcall.\n\n\n\n***\ Interaction\ with\ `\[\[\[try\]\]`\ ***\n----\n'''%'''\ proc\ foo\ \{\}\ \{puts\ \{I'm\ foo\}\}\n'''%'''\ proc\ foo\ \{\}\ \{puts\ \"I'm\ foo\"\}\n'''%'''\ proc\ bar\ \{\}\ \{puts\ \"I'm\ bar\"\;\ try\ \{\ tailcall\ foo\ \}\ finally\ \{\ puts\ \"exitting\"\ \}\}\n''I'm\ foo''\n'''%'''\ bar\n''I'm\ bar''\n''exiting''\n''exitting''\n===\n31-03-2015\ \[HE\]\ I'm\ sure\ \;-)\ that\ I\ don't\ understood\ what\ happend\ there.\ Why\ \"exiting\"\ is\ printed\ before\ \"I'm\ foo\"\ when\ I\ call\ bar?\n\[AMG\]:\ \[\[foo\]\]\ is\ invoked\ by\ replacing\ \[\[bar\]\]\ which\ implies\ the\ intervening\ \[\[\[try\]\]\]\ block\ must\ exit\ before\ \[\[foo\]\]\ can\ start.\n\[wdb\]:\ Apparently,\ the\ `tailcall`\ closes\ one\ of\ the\ last\ gaps\ in\n\n\[wdb\]:\ Apparently,\ the\ command\ `\[\[\[tailcall\]\]`\ closes\ one\ of\ the\ last\ gaps\ in\n\n\n\n\n\[NEM\]:\ As\ a\ test/demo\ of\ how\ to\ use\ this\ facility,\ here\ is\ a\ simple\ benchmark\n\[NEM\]\ As\ a\ test/demo\ of\ how\ to\ use\ this\ facility,\ here\ is\ a\ simple\ benchmark\n\n======\npackage\ require\ Tcl\ 8.6a1\nnamespace\ import\ ::tcl::mathop::*\ninterp\ alias\ \{\}\ tailcall\ \{\}\ tcl::unsupported::tailcall\n\n#\ Naive\ recursive\ factorial\ function\nproc\ fac\ n\ \{\n\ \ \ \ if\ \{\$n\ <=\ 1\}\ \{\n\ \ \ \ \ \ \ \ return\ 1\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ *\ \$n\ \[fac\ \[-\ \$n\ 1\]\]\n\ \ \ \ \}\n\}\n\n#\ Tail-recursive\ factorial\nproc\ fac-tr\ \{n\ \{k\ 1\}\}\ \{\n\ \ \ \ if\ \{\$n\ <=\ 1\}\ \{\n\ \ \ \ \ \ \ \ return\ \$k\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ tailcall\ fac-tr\ \[-\ \$n\ 1\]\ \[*\ \$n\ \$k\]\n\ \ \ \ \}\n\}\n\n#\ Iterative\ factorial\nproc\ fac-i\ n\ \{\n\ \ \ \ for\ \{set\ k\ 1\}\ \{\$n\ >\ 1\}\ \{incr\ n\ -1\}\ \{\n\ \ \ \ \ \ \ \ set\ k\ \[expr\ \{\$n*\$k\}\]\n\ \ \ \ \}\n\ \ \ \ return\ \$k\n\}\n\nproc\ test\ \{\}\ \{\n\ \ \ \ set\ fmt\ \{%-10s\ ..%-12.12s\ %s\}\n\ \ \ \ set\ fmt\ \"%-10s\ ..%-12.12s\ %s\"\n\ \ \ \ puts\ \[format\ \$fmt\ \"Implementation\"\ \"Result\"\ \"Time\"\]\n\ \ \ \ \ \ \ \ puts\ \"\\nfac\ \$n:\"\n\ \ \ \ \ \ \ \ foreach\ impl\ \{fac\ fac-i\ fac-tr\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[catch\ \{\$impl\ \$n\}\ result\]\}\ \{\ \n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[catch\ \{\ \$impl\ \$n\ \}\ result\]\}\ \{\ \n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ result\ \"n/a\"\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ time\ \"n/a\"\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ time\ \[time\ \[list\ \$impl\ \$n\]\ 10\]\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ puts\ \[format\ \$fmt\ \$impl\ \$result\ \$time\]\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\}\ntest\n======\n\nPutting\ this\ in\ a\ table,\ we\ get\ (timings\ taken\ on\ Linux\ box,\ 2.66GHz,\ 1GB\ RAM):\n\n%|\ N\ |\ `fac`\ Time\ |\ `fac-i`\ Time\ |\ `fac-tr`\ Time\ |%\n&|\ 1\ |\ 3.2\ |\ 3.0\ |\ 2.8\ |&\n&|\ 5\ |\ 10.1\ |\ 4.7\ |\ 19.4\ |&\n&|\ 10\ |\ 18.4\ |\ 6.4\ |\ 37.9\ |&\n&|\ 100\ |\ 345.5\ |\ 267.4\ |\ 717.8\ |&\n&|\ 500\ |\ 3133.9\ |\ 3715.6\ |\ 6182.5\ |&\n&|\ 1000\ |\ n/a\ |\ 13811.7\ |\ 19764.3\ |&\n&|\ 2500\ |\ n/a\ |\ 65121.1\ |\ 84556.5\ |&\n&|\ 5000\ |\ n/a\ |\ 241176.8\ |\ 288136.1\ |&\n&|\ 10000\ |\ n/a\ |\ 987057.8\ |\ 1643480.7\ |&\n\nAs\ we\ can\ see,\ the\ tail-recursive\ version\ is\ slightly\ slower\ than\ the\ iterative\nversion,\ and\ unlike\ the\ naive\ version,\ manages\ to\ not\ blow\ the\ stack.\n\n\n\n\n**\ Emulating\ \[\[Tailcall\]\]\ **\n**\ Using\ Tailcall\ for\ Callbacks\ **\n\[Lars\ H\]\ 2010-05-09:\ As\ of\ late,\ when\ writing\ an\ `\[\[\[uplevel\]\]`,\ I've\ sometimes\nfound\ myself\ thinking\ \"That\ would\ be\ slicker\ with\ `\[\[\[tailcall\]\]`,\ but\ I\ can't\nhowever\ use\ a\ `\[proc\]`\ to\ emulate\ the\ properties\ of\ `tailcall`\ that\ would\nhowever\ use\ a\ `\[\[\[proc\]\]`\ to\ emulate\ the\ properties\ of\ \[\[tailcall\]\ that\ would\n\nThe\ main\ situation\ I've\ encountered\ is\ that\ of\ delegating\ to\ another\ command\nwhich\ may\ make\ use\ of\ `\[upvar\]`\ or\ `\[uplevel\]`.\ That's\ basically\ taken\nwhich\ may\ make\ use\ of\ `\[\[\[upvar\]\]`\ or\ `\[\[\[uplevel\]\]`.\ That's\ basically\ taken\n\n======\nproc\ utailcall\ args\ \{uplevel\ 2\ \$args\}\nproc\ utailcall\ \{args\}\ \{uplevel\ 2\ \$args\}\n\nalthough\ it's\ safer\ to\ make\ it\n\n======\nproc\ utailcall\ args\ \{return\ -code\ return\ \[uplevel\ 2\ \$args\]\}\nproc\ utailcall\ \{args\}\ \{return\ -code\ return\ \[uplevel\ 2\ \$args\]\}\n\nin\ case\ the\ \"terminate\ proc\ early\"\ aspect\ of\ `tailcall`\ is\ relied\ upon\;\ this\nin\ case\ the\ \"terminate\ proc\ early\"\ aspect\ of\ \[\[tailcall\]\ is\ relied\ upon\;\ this\n\nAnother\ aspect\ of\ `tailcall`\ is\ the\ name\ resolution\ of\ the\ called\ command.\nAnother\ aspect\ of\ `\[\[tailcall\]`\ is\ the\ name\ resolution\ of\ the\ called\ command.\n\n======\nproc\ ntailcall\ \{cmd\ args\}\ \{\n\ \ \ \ return\ -code\ return\ \[\n\ \ \ \ \ \ \ \ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\ \{*\}\$args\n\ \ \ \ \]\n\}\n======\n\nbut\ it's\ almost\ as\ easy\ to\ do\ both\ at\ the\ same\ time\n\n======\nproc\ untailcall\ \{cmd\ args\}\ \{\n\ \ \ \ return\ -code\ return\ \[\n\ \ \ \ \ \ \ \ uplevel\ 2\ \[list\ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\]\ \$args\n\ \ \ \ \]\n\}\n======\n\nA\ word\ of\ warning\ here\ is\ that\ this\ will\ produce\ a\ very\ confusing\ error\ message\nif\ the\ command\ is\ undefined,\ as\ `\[namespace\ which\]`\ returns\ an\ empty\ string\nif\ the\ command\ is\ undefined,\ as\ `\[\[\[namespace\ which\]\]`\ returns\ an\ empty\ string\n\nA\ third\ aspect\ is\ that\ of\ preserving\ `\[return\]`\ levels.\nA\ third\ aspect\ is\ that\ of\ preserving\ `\[\[\[return\]\]`\ levels.\n======\nproc\ rtailcall\ args\ \{\nproc\ rtailcall\ \{args\}\ \{\n\ \ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ \ return\ -options\ \$options\ \$result\n\}\n======\n\nThis\ leaves\ some\ extra\ material\ in\ the\ \[errorInfo\],\ but\ one\ can\ probably\ live\nwith\ that.\ Combining\ the\ \"r\"\ and\ \"u\"\ aspects\ is\ straightforward,\ but\ will\ leave\neven\ more:\n\n======\nproc\ rutailcall\ args\ \{\nproc\ rutailcall\ \{args\}\ \{\n\ \ \ catch\ \{uplevel\ 2\ \$args\}\ result\ options\n\ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ return\ -options\ \$options\ \$result\n======\n\nTo\ complete\ the\ set,\ one\ might\ just\ as\ well\ write\ down\ the\ combination\ of\ the\n\"r\"\ and\ \"n\"\ aspects\n\n======\nproc\ rntailcall\ \{cmd\ args\}\ \{\n\ \ \ \ catch\ \{\n\ \ \ catch\ \{\n\ \ \ \ \ \ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\ \{*\}\$args\n\ \ \ \}\ result\ options\n\ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ return\ -options\ \$options\ \$result\n======\n\nand\ of\ all\ three\n\n======\nproc\ rnutailcall\ \{cmd\ args\}\ \{\n\ \ \ \ catch\ \{\n\ \ \ catch\ \{\n\ \ \ \ \ \ uplevel\ 2\ \[list\ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\]\ \$args\n\ \ \ \}\ result\ options\n\ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ return\ -options\ \$options\ \$result\n======\n\nBut\ note:\ ''all\ of\ the\ above\ will\ fail\ if\ used\ for\ tail\ recursion'',\ as\ soon\ as\nthe\ loops\ get\ long\ enough.\n\n\n**\ Replacement\ for\ `\[uplevel\]`\ **\n**\ Replacement\ for\ \[\[\[uplevel\]\]\ **\n\[AMG\]:\ `\[uplevel\]`\ has\ limitations\ with\ respect\ to\ \[bytecode\]\ compilation\n\[AMG\]:\ `\[\[\[uplevel\]\]`\ has\ limitations\ with\ respect\ to\ \[bytecode\]\ compilation\nand\ interpretation\ of\ `\[\[\[return\]\]`.\ \ If\ `\[\[\[uplevel\]\]`'s\ level\ count\ is\ 1,\ and\nif\ it's\ the\ last\ thing\ being\ done\ in\ the\ `\[\[\[proc\]\]`,\ these\ limitations\ can\ be\navoided\ by\ using\ `\[\[\[tailcall\]\]`\ instead.\ \ Note\ that\ `\[\[\[uplevel\]\]`\ takes\ a\nscript\ whereas\ `\[\[\[tailcall\]\]`\ takes\ a\ command.\ \ If\ you\ want\ to\ pass\ a\ script\nto\ `\[\[\[tailcall\]\]`,\ make\ it\ be\ the\ sole\ argument\ to\ `\[\[\[try\]\]`.\nSee\ \[http://wiki.tcl.tk/1507#pagetocc0434a60%|%Possible\ uplevel\ deficiencies%|%\].\nAlso\ see\ \[http://wiki.tcl.tk/1507#pagetocb7539876%|%When\ to\ use\ uplevel\]\ for\nmore\ on\ when\ to\ use\ or\ avoid\ `\[uplevel\]`.\ \ See\nmore\ on\ when\ to\ use\ or\ avoid\ `\[\[\[uplevel\]\]`.\ \ See\nperformance\ numbers\ regarding\ \[bytecode\]\ compilation\ with\ `\[eval\]`,\nperformance\ numbers\ regarding\ \[bytecode\]\ compilation\ with\ `\[\[\[eval\]\]`,\n`\[\[\[uplevel\]\]`,\ `\[\[\[try\]\]`,\ and\ others.\n**\ When\ to\ apply\ `tailcall`\ optimization\ **\n------\n\n======\nproc\ proc1\ \{arg1\ arg2\}\ \{\n\ \ \ \ #\ do\ something\ here\ which\ finds\ arg3\ and\ arg4\n\ \ \ \ return\ \[proc2\ \$arg3\ \$arg4\]\n\}\n======\n\nby\n\n======\nproc\ proc1\ \{arg1\ arg2\}\ \{\n\ \ \ \ #\ do\ something\ here\ which\ finds\ arg3\ and\ arg4\n\ \ \ \ tailcall\ proc2\ \$arg3\ \$arg4\n\}\n======\n\nIf\ proc2\ is\ for\ sure\ found\ in\ the\ caller\ namespace?\n\nIs\ this\ an\ intelligent\ optimization?\n\nI\ came\ to\ this\ idea,\ as\ the\ TI\ C\ compiler\ calls\ this\ \"tailcall\ optimization\".\n\n\[AMG\]:\ Yes,\ except\ in\ a\ highly\ unlikely\ situation\ where\ `proc2`\ needs\ `proc1`\ to\ be\ visible\ in\ the\ stack.\ \ Procedures\ really\ ought\ not\ to\ care\ who\ called\ them,\ but\ Tcl\ makes\ all\ sorts\ of\ things\ possible,\ including\ stupid\ things.\n\[AMG\]:\ Yes,\ except\ in\ a\ highly\ unlikely\ situation\ where\ \[\[proc2\]\]\ needs\ \[\[proc1\]\]\ to\ be\ visible\ in\ the\ stack.\ \ Procedures\ really\ ought\ not\ to\ care\ who\ called\ them,\ but\ Tcl\ makes\ all\ sorts\ of\ things\ possible,\ including\ stupid\ things.\n\n\n\n\[NEM\]:\ \ Many\ thanks\ to\ \[MS\]\ for\ his\ hard\ work\ making\ this\ a\ reality!\n\n<<categories>>\ Command\ |\ Concept\ |\ Control\ structure\ |\ Functional\ Programming\n regexp2} CALL {my render tailcall \n\n\ \ \ \[wrapping\ commands\]:\ \ \ wrap\ commands\ by\ using\ `\[interp\ invokehidden\]`\ together\ with\ `tailcall`\n\n\n'''`tailcall`'''\ interprets\ its\ arguments\ as\ a\ command\ and\ executes\ the\n`\[\[Tailcall\]`\ is\ made\ possible\ by\ \[NRE\].\ \ It\ first\ became\ available\ as\n`\[\[\[::tcl::unsupported::tailcall\]`\ in\ the\ release\ of\ Tcl8.6a2.\ It\ provides\nproper\ tailcalls,\ with\ the\ following\ semantics:\nUnlike\ some\ other\ languages,\ `tailcall`\ is\ not\ limited\ to\ executing\ only\ its\n\ \ \ *\ a\ proc/lambda\ invokes\ '''\[\[tailcall\ foo\ \[\[bar\]\]\ \$soom\]\]'''\n\ \ \ *\ '''bar'''\ is\ invoked\ and\ the\ value\ of\ '''soom'''\ fetched,\ as\ if\ '''\[\[list\ foo\ \[\[bar\]\]\ \$soom\]\]'''\ had\ been\ called\n\ \ \ *\ a\ command\ named\ '''foo'''\ is\ looked\ up\ ''in\ the\ current\ context''\n\ \ \ *\ the\ current\ proc/lambda\ replaces\ itself\ in\ the\ call\ stack\ with\ a\ call\ to\ the\ just\ found\ command\n`tailcall`\ is\ made\ possible\ by\ \[NRE\].\ \ It\ first\ became\ available\ as\nThat\ is:\ '''tailcall\ foo\ \[\[bar\]\]\ \$soom'''\ is\ very\ similar\ to\ '''return\ \[\[uplevel\ 1\ \[\[list\ foo\ \[\[bar\]\]\ \$soom\]\]\]\]'''\ with\ two\ exceptions:\nContrast\ the\ following\ two\ commands:\n\ \ \ 1.\ '''foo'''\ is\ looked\ up\ in\ the\ ''current''\ context,\ not\ in\ the\ caller's\n\n\nTo\ `tailcall`\ a\ script:\n**\ Usage\ **\n\nWhile\ `\[\[\[uplevel\]\]`\ takes\ a\ script,\ \[\[tailcall\]\ takes\ a\ command.\ \ If\ you\ want\nto\ \[\[tailcall\]\ a\ script\ do\ it\ as\ follows:\n\ntailcall\ try\ \$script\n======\n\n----\n\n\[WHD\]:\ Let\ me\ see\ if\ I\ understand\ what\ this\ does.\n\n======\nproc\ fred\ \{\}\ \{\n\ \ \ \ george\n\}\n\nproc\ george\ \{\}\ \{\n\ \ \ \ \ tailcall\ harry\n\}\n======\n\nIf\ I\ call\ fred,\ it's\ almost\ as\ though\ fred\ called\ harry\ directly,\ instead\ of\ngeorge.\ \ Not\ so?\n\n\[MS\]:\ \ yup\ -\ all\ traces\ of\ george\ are\ gone\ from\ the\ program\ stack\ when\ harry\ is\ncalled.\ Now,\ if\ harry\ resolves\ to\ a\ different\ command\ in\ george's\ current\nnamespace\ than\ it\ would\ under\ fred's,\ the\ harry\ that\ is\ called\ is\ george's\ and\nnot\ fred's\ (no\ diff\ if\ the\ commands\ are\ FQ,\ of\ course).\n\nI\ think\ this\ does\ pretty\ much\ what\ delegation\ is\ supposed\ to\ do,\ right?\n\n----\n\n\[jima\]\ 2009-10-15:\ Perhaps\ this\ has\ been\ asked\ before\ or\ somewhere\ else...\n\nIs\ this\ an\ optimization\ that\ takes\ place\ at\ bytecode\ generation\ time?\n\nI\ mean,\ once\ fred\ knows\ that\ has\ to\ call\ harry\ directly\ the\ bytecodes\ generated\nwould\ be\ the\ ones\ equivalent\ to\ have\ said:\n\n======\nproc\ fred\ \{\}\ \{\n\ \ \ \ harry\n\}\n======\n\nI\ reckon\ I\ am\ not\ familiar\ with\ all\ the\ internals\ of\ Tcl\ but\ I\ find\ this\ would\nbe\ an\ interesting\ thing.\ Wouldn't\ this\ be\ a\ new\ way\ to\ have\ some\ sort\ of\nmacros?\n\n\[MS\]:\ \ Currently,\ `tailcall`\ is\ not\ bytecompiled.\ Everything\ happens\ at\n\[MS\]:\ \ Currently,\ \[\[tailcall\]\ is\ not\ byte\ compiled.\ Everything\ happens\ at\nbut\ things\ get\ more\ involved\ as\ soon\ as\ `fred`\ has\ a\ bit\ more\ structure\ to\nbut\ things\ get\ more\ involved\ as\ soon\ as\ `\[\[fred\]`\ has\ a\ bit\ more\ structure\ to\nlookup,\ multiple\ exit\ points\ with\ different\ (or\ no)\ `tailcall`\ in\ them,\nlookup,\ multiple\ exit\ points\ with\ different\ (or\ no)\ `\[\[\[tailcall\]\]`\ in\ them,\n\n\[jima\]:\ Thanks\ a\ lot\ Miguel\ for\ the\ answer.\ I\ see\ the\ point.\ I\ guess\ this\ is\nthe\ same\ with\ `\[uplevel\]\ 1`,\ isn't\ it?\nthe\ same\ with\ `\[\[\[uplevel\]\ 1\]\]`,\ isn't\ it?\n======\nproc\ fred\ \{\}\ \{\n\ \ \ \ uplevel\ 1\ \{\n\ \ \ \ \ \ \ \ #code\ here\n\ \ \ \ \}\n\}\n======\n\nWould\ it\ be\ interesting\ to\ define\ a\ case\ (like\ a\ contract)\ saying\ if\ your\ proc\nis\ simple\ enough\ then\ it\ gets\ bytecompiled\ and\ you\ get\ some\ benefits?\n\n\[MS\]:\ \ you\ do\ not\ mean\ \"bytecompiled\"\ but\ rather\ \"inlined\ into\ the\ caller\",\ as\nall\ `\[proc\]`\ bodies\ get\ bytecompiled.\ There\ are\ quite\ a\ few\ other\ issues\ with\ that,\nall\ `\[\[\[proc\]\]`\ bodies\ get\ bytecompiled.\ There\ are\ quite\ a\ few\ other\ issues\ with\ that,\ncause\ a\ spoiling\ of\ all\ bytecodes\ and\ recompilation\ of\ the\ world,\ at\ least\ with\nthe\ current\ approach\ to\ bytecode\ lifetime\ management.\nthe\ current\ approach\ to\ bytecode\ lifetime\ management.\ \n----\n\n\[AMG\]:\ Sounds\ a\ lot\ like\ `exec`\ in\ \[Unix\ shells\].\ \ See\ \[execline\]\ for\ more\ninformation\ on\ a\ noninteractive\ Unix\ shell\ where\ everything\ is\ done\ with\nexec/tailcall.\n\n\n\n***\ Interaction\ with\ `\[\[\[try\]\]`\ ***\n----\n'''%'''\ proc\ foo\ \{\}\ \{puts\ \{I'm\ foo\}\}\n'''%'''\ proc\ foo\ \{\}\ \{puts\ \"I'm\ foo\"\}\n'''%'''\ proc\ bar\ \{\}\ \{puts\ \"I'm\ bar\"\;\ try\ \{\ tailcall\ foo\ \}\ finally\ \{\ puts\ \"exitting\"\ \}\}\n''I'm\ foo''\n'''%'''\ bar\n''I'm\ bar''\n''exiting''\n''exitting''\n===\n31-03-2015\ \[HE\]\ I'm\ sure\ \;-)\ that\ I\ don't\ understood\ what\ happend\ there.\ Why\ \"exiting\"\ is\ printed\ before\ \"I'm\ foo\"\ when\ I\ call\ bar?\n\[AMG\]:\ \[\[foo\]\]\ is\ invoked\ by\ replacing\ \[\[bar\]\]\ which\ implies\ the\ intervening\ \[\[\[try\]\]\]\ block\ must\ exit\ before\ \[\[foo\]\]\ can\ start.\n\[wdb\]:\ Apparently,\ the\ `tailcall`\ closes\ one\ of\ the\ last\ gaps\ in\n\n\[wdb\]:\ Apparently,\ the\ command\ `\[\[\[tailcall\]\]`\ closes\ one\ of\ the\ last\ gaps\ in\n\n\n\n\n\[NEM\]:\ As\ a\ test/demo\ of\ how\ to\ use\ this\ facility,\ here\ is\ a\ simple\ benchmark\n\[NEM\]\ As\ a\ test/demo\ of\ how\ to\ use\ this\ facility,\ here\ is\ a\ simple\ benchmark\n\n======\npackage\ require\ Tcl\ 8.6a1\nnamespace\ import\ ::tcl::mathop::*\ninterp\ alias\ \{\}\ tailcall\ \{\}\ tcl::unsupported::tailcall\n\n#\ Naive\ recursive\ factorial\ function\nproc\ fac\ n\ \{\n\ \ \ \ if\ \{\$n\ <=\ 1\}\ \{\n\ \ \ \ \ \ \ \ return\ 1\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ *\ \$n\ \[fac\ \[-\ \$n\ 1\]\]\n\ \ \ \ \}\n\}\n\n#\ Tail-recursive\ factorial\nproc\ fac-tr\ \{n\ \{k\ 1\}\}\ \{\n\ \ \ \ if\ \{\$n\ <=\ 1\}\ \{\n\ \ \ \ \ \ \ \ return\ \$k\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ tailcall\ fac-tr\ \[-\ \$n\ 1\]\ \[*\ \$n\ \$k\]\n\ \ \ \ \}\n\}\n\n#\ Iterative\ factorial\nproc\ fac-i\ n\ \{\n\ \ \ \ for\ \{set\ k\ 1\}\ \{\$n\ >\ 1\}\ \{incr\ n\ -1\}\ \{\n\ \ \ \ \ \ \ \ set\ k\ \[expr\ \{\$n*\$k\}\]\n\ \ \ \ \}\n\ \ \ \ return\ \$k\n\}\n\nproc\ test\ \{\}\ \{\n\ \ \ \ set\ fmt\ \{%-10s\ ..%-12.12s\ %s\}\n\ \ \ \ set\ fmt\ \"%-10s\ ..%-12.12s\ %s\"\n\ \ \ \ puts\ \[format\ \$fmt\ \"Implementation\"\ \"Result\"\ \"Time\"\]\n\ \ \ \ \ \ \ \ puts\ \"\\nfac\ \$n:\"\n\ \ \ \ \ \ \ \ foreach\ impl\ \{fac\ fac-i\ fac-tr\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[catch\ \{\$impl\ \$n\}\ result\]\}\ \{\ \n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[catch\ \{\ \$impl\ \$n\ \}\ result\]\}\ \{\ \n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ result\ \"n/a\"\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ time\ \"n/a\"\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ time\ \[time\ \[list\ \$impl\ \$n\]\ 10\]\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ puts\ \[format\ \$fmt\ \$impl\ \$result\ \$time\]\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\}\ntest\n======\n\nPutting\ this\ in\ a\ table,\ we\ get\ (timings\ taken\ on\ Linux\ box,\ 2.66GHz,\ 1GB\ RAM):\n\n%|\ N\ |\ `fac`\ Time\ |\ `fac-i`\ Time\ |\ `fac-tr`\ Time\ |%\n&|\ 1\ |\ 3.2\ |\ 3.0\ |\ 2.8\ |&\n&|\ 5\ |\ 10.1\ |\ 4.7\ |\ 19.4\ |&\n&|\ 10\ |\ 18.4\ |\ 6.4\ |\ 37.9\ |&\n&|\ 100\ |\ 345.5\ |\ 267.4\ |\ 717.8\ |&\n&|\ 500\ |\ 3133.9\ |\ 3715.6\ |\ 6182.5\ |&\n&|\ 1000\ |\ n/a\ |\ 13811.7\ |\ 19764.3\ |&\n&|\ 2500\ |\ n/a\ |\ 65121.1\ |\ 84556.5\ |&\n&|\ 5000\ |\ n/a\ |\ 241176.8\ |\ 288136.1\ |&\n&|\ 10000\ |\ n/a\ |\ 987057.8\ |\ 1643480.7\ |&\n\nAs\ we\ can\ see,\ the\ tail-recursive\ version\ is\ slightly\ slower\ than\ the\ iterative\nversion,\ and\ unlike\ the\ naive\ version,\ manages\ to\ not\ blow\ the\ stack.\n\n\n\n\n**\ Emulating\ \[\[Tailcall\]\]\ **\n**\ Using\ Tailcall\ for\ Callbacks\ **\n\[Lars\ H\]\ 2010-05-09:\ As\ of\ late,\ when\ writing\ an\ `\[\[\[uplevel\]\]`,\ I've\ sometimes\nfound\ myself\ thinking\ \"That\ would\ be\ slicker\ with\ `\[\[\[tailcall\]\]`,\ but\ I\ can't\nhowever\ use\ a\ `\[proc\]`\ to\ emulate\ the\ properties\ of\ `tailcall`\ that\ would\nhowever\ use\ a\ `\[\[\[proc\]\]`\ to\ emulate\ the\ properties\ of\ \[\[tailcall\]\ that\ would\n\nThe\ main\ situation\ I've\ encountered\ is\ that\ of\ delegating\ to\ another\ command\nwhich\ may\ make\ use\ of\ `\[upvar\]`\ or\ `\[uplevel\]`.\ That's\ basically\ taken\nwhich\ may\ make\ use\ of\ `\[\[\[upvar\]\]`\ or\ `\[\[\[uplevel\]\]`.\ That's\ basically\ taken\n\n======\nproc\ utailcall\ args\ \{uplevel\ 2\ \$args\}\nproc\ utailcall\ \{args\}\ \{uplevel\ 2\ \$args\}\n\nalthough\ it's\ safer\ to\ make\ it\n\n======\nproc\ utailcall\ args\ \{return\ -code\ return\ \[uplevel\ 2\ \$args\]\}\nproc\ utailcall\ \{args\}\ \{return\ -code\ return\ \[uplevel\ 2\ \$args\]\}\n\nin\ case\ the\ \"terminate\ proc\ early\"\ aspect\ of\ `tailcall`\ is\ relied\ upon\;\ this\nin\ case\ the\ \"terminate\ proc\ early\"\ aspect\ of\ \[\[tailcall\]\ is\ relied\ upon\;\ this\n\nAnother\ aspect\ of\ `tailcall`\ is\ the\ name\ resolution\ of\ the\ called\ command.\nAnother\ aspect\ of\ `\[\[tailcall\]`\ is\ the\ name\ resolution\ of\ the\ called\ command.\n\n======\nproc\ ntailcall\ \{cmd\ args\}\ \{\n\ \ \ \ return\ -code\ return\ \[\n\ \ \ \ \ \ \ \ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\ \{*\}\$args\n\ \ \ \ \]\n\}\n======\n\nbut\ it's\ almost\ as\ easy\ to\ do\ both\ at\ the\ same\ time\n\n======\nproc\ untailcall\ \{cmd\ args\}\ \{\n\ \ \ \ return\ -code\ return\ \[\n\ \ \ \ \ \ \ \ uplevel\ 2\ \[list\ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\]\ \$args\n\ \ \ \ \]\n\}\n======\n\nA\ word\ of\ warning\ here\ is\ that\ this\ will\ produce\ a\ very\ confusing\ error\ message\nif\ the\ command\ is\ undefined,\ as\ `\[namespace\ which\]`\ returns\ an\ empty\ string\nif\ the\ command\ is\ undefined,\ as\ `\[\[\[namespace\ which\]\]`\ returns\ an\ empty\ string\n\nA\ third\ aspect\ is\ that\ of\ preserving\ `\[return\]`\ levels.\nA\ third\ aspect\ is\ that\ of\ preserving\ `\[\[\[return\]\]`\ levels.\n======\nproc\ rtailcall\ args\ \{\nproc\ rtailcall\ \{args\}\ \{\n\ \ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ \ return\ -options\ \$options\ \$result\n\}\n======\n\nThis\ leaves\ some\ extra\ material\ in\ the\ \[errorInfo\],\ but\ one\ can\ probably\ live\nwith\ that.\ Combining\ the\ \"r\"\ and\ \"u\"\ aspects\ is\ straightforward,\ but\ will\ leave\neven\ more:\n\n======\nproc\ rutailcall\ args\ \{\nproc\ rutailcall\ \{args\}\ \{\n\ \ \ catch\ \{uplevel\ 2\ \$args\}\ result\ options\n\ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ return\ -options\ \$options\ \$result\n======\n\nTo\ complete\ the\ set,\ one\ might\ just\ as\ well\ write\ down\ the\ combination\ of\ the\n\"r\"\ and\ \"n\"\ aspects\n\n======\nproc\ rntailcall\ \{cmd\ args\}\ \{\n\ \ \ \ catch\ \{\n\ \ \ catch\ \{\n\ \ \ \ \ \ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\ \{*\}\$args\n\ \ \ \}\ result\ options\n\ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ return\ -options\ \$options\ \$result\n======\n\nand\ of\ all\ three\n\n======\nproc\ rnutailcall\ \{cmd\ args\}\ \{\n\ \ \ \ catch\ \{\n\ \ \ catch\ \{\n\ \ \ \ \ \ uplevel\ 2\ \[list\ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\]\ \$args\n\ \ \ \}\ result\ options\n\ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ return\ -options\ \$options\ \$result\n======\n\nBut\ note:\ ''all\ of\ the\ above\ will\ fail\ if\ used\ for\ tail\ recursion'',\ as\ soon\ as\nthe\ loops\ get\ long\ enough.\n\n\n**\ Replacement\ for\ `\[uplevel\]`\ **\n**\ Replacement\ for\ \[\[\[uplevel\]\]\ **\n\[AMG\]:\ `\[uplevel\]`\ has\ limitations\ with\ respect\ to\ \[bytecode\]\ compilation\n\[AMG\]:\ `\[\[\[uplevel\]\]`\ has\ limitations\ with\ respect\ to\ \[bytecode\]\ compilation\nand\ interpretation\ of\ `\[\[\[return\]\]`.\ \ If\ `\[\[\[uplevel\]\]`'s\ level\ count\ is\ 1,\ and\nif\ it's\ the\ last\ thing\ being\ done\ in\ the\ `\[\[\[proc\]\]`,\ these\ limitations\ can\ be\navoided\ by\ using\ `\[\[\[tailcall\]\]`\ instead.\ \ Note\ that\ `\[\[\[uplevel\]\]`\ takes\ a\nscript\ whereas\ `\[\[\[tailcall\]\]`\ takes\ a\ command.\ \ If\ you\ want\ to\ pass\ a\ script\nto\ `\[\[\[tailcall\]\]`,\ make\ it\ be\ the\ sole\ argument\ to\ `\[\[\[try\]\]`.\nSee\ \[http://wiki.tcl.tk/1507#pagetocc0434a60%|%Possible\ uplevel\ deficiencies%|%\].\nAlso\ see\ \[http://wiki.tcl.tk/1507#pagetocb7539876%|%When\ to\ use\ uplevel\]\ for\nmore\ on\ when\ to\ use\ or\ avoid\ `\[uplevel\]`.\ \ See\nmore\ on\ when\ to\ use\ or\ avoid\ `\[\[\[uplevel\]\]`.\ \ See\nperformance\ numbers\ regarding\ \[bytecode\]\ compilation\ with\ `\[eval\]`,\nperformance\ numbers\ regarding\ \[bytecode\]\ compilation\ with\ `\[\[\[eval\]\]`,\n`\[\[\[uplevel\]\]`,\ `\[\[\[try\]\]`,\ and\ others.\n**\ When\ to\ apply\ `tailcall`\ optimization\ **\n------\n\n======\nproc\ proc1\ \{arg1\ arg2\}\ \{\n\ \ \ \ #\ do\ something\ here\ which\ finds\ arg3\ and\ arg4\n\ \ \ \ return\ \[proc2\ \$arg3\ \$arg4\]\n\}\n======\n\nby\n\n======\nproc\ proc1\ \{arg1\ arg2\}\ \{\n\ \ \ \ #\ do\ something\ here\ which\ finds\ arg3\ and\ arg4\n\ \ \ \ tailcall\ proc2\ \$arg3\ \$arg4\n\}\n======\n\nIf\ proc2\ is\ for\ sure\ found\ in\ the\ caller\ namespace?\n\nIs\ this\ an\ intelligent\ optimization?\n\nI\ came\ to\ this\ idea,\ as\ the\ TI\ C\ compiler\ calls\ this\ \"tailcall\ optimization\".\n\n\[AMG\]:\ Yes,\ except\ in\ a\ highly\ unlikely\ situation\ where\ `proc2`\ needs\ `proc1`\ to\ be\ visible\ in\ the\ stack.\ \ Procedures\ really\ ought\ not\ to\ care\ who\ called\ them,\ but\ Tcl\ makes\ all\ sorts\ of\ things\ possible,\ including\ stupid\ things.\n\[AMG\]:\ Yes,\ except\ in\ a\ highly\ unlikely\ situation\ where\ \[\[proc2\]\]\ needs\ \[\[proc1\]\]\ to\ be\ visible\ in\ the\ stack.\ \ Procedures\ really\ ought\ not\ to\ care\ who\ called\ them,\ but\ Tcl\ makes\ all\ sorts\ of\ things\ possible,\ including\ stupid\ things.\n\n\n\n\[NEM\]:\ \ Many\ thanks\ to\ \[MS\]\ for\ his\ hard\ work\ making\ this\ a\ reality!\n\n<<categories>>\ Command\ |\ Concept\ |\ Control\ structure\ |\ Functional\ Programming\n} CALL {my revision tailcall} CALL {::oo::Obj1500038 process revision/tailcall} CALL {::oo::Obj1500036 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