Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/Closures?V=74
QUERY_STRINGV=74
CONTENT_TYPE
DOCUMENT_URI/revision/Closures
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.70.131.201
REMOTE_PORT43428
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR18.189.2.122
HTTP_CF_RAY8768533c79fb2cb3-ORD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTclaudebot
HTTP_CF_CONNECTING_IP18.189.2.122
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 Closures These\ references\ are\ standard\ for\ the\ abstract\ notion\ of\ \"closure\":\n\[http://en.wikipedia.org/wiki/Closure_%28computer_science%29\]\ \[http://c2.com/cgi/wiki?LexicalClosure\]\ \[http://www.perl.com/doc/FAQs/FAQ/oldfaq-html/Q3.14.html\].\n\n\nFrom\ the\ \[Tcl\ chatroom\]:\n===none\n\[dkf\]\ \ \ Aliases\ are\ sort-of\ poor-mans\ closures.\ If\ we\ had\ real\ closures,\ we'd\ use\ them.\n\n\[suchenwi\]\ \ \ \ \ \ What\ prevents\ us\ from\ having\ them?\n\n\[dkf\]\ \ \ Lifespan\ issues\ mainly.\n\n\[am\]\ \ \ \ Why\ are\ aliases\ not\ closures\ -\ sorry,\ I\ think\ I\ have\ asked\ this\ before,\ but\ I\ do\ not\ fully\ grasp\ the\ concept\ of\ a\ closure\n\n\[dkf\]\ \ \ If\ we\ could\ be\ sure\ that\ the\ closure\ would\ go\ away\ as\ soon\ as\ it\ was\ no\ longer\ needed,\ they'd\ be\ trivial\ to\ add.\ A\ closure\ is\ really\ a\ piece\ of\ stack\ frame\ that\ is\ not\ on\ the\ stack.\ Or\ something\ like\ that.\n(The\ really\ strange\ things\ are\ \[continuation\]s,\ but\ we're\ not\ dealing\ with\ those\ now.)\nNow\ it\ would\ be\ pretty\ easy\ to\ create\ a\ new\ closure\ object\ and\ commands\ to\ manipulate\ that,\ but\ ensuring\ \nthat\ it\ doesn't\ go\ away\ at\ the\ wrong\ moment\ is\ not\ entirely\ trivial.\n\n\[suchenwi\]\ \ \ \ \ \ Could\ \[static\ variables\]\ be\ called\ atomar\ closures?\ I\ meant\ in\ the\ sense\ that\ they're\ local\ to\ a\ function,\ but\ persistent\ between\ calls.\n\n\[dkf\]\ \ \ \[C\]'s\ static\ variables?\ \ Sort\ of.\ \ Not\ that\ they're\ exactly\ that.\ Closures\ are\ really\ a\ bit\ antithetical\ to\ C\ anyway.\n\n''\[Lars\ H\],\ 2010-02-05:\ It\ seems\ Apple\ is\ bent\ on\ adding\ some\ kind\ of\ closures\ to\ C,\ though\ \[http://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars/10\].''\n\n\[dkf\]\ \ \ However,\ I\ could\ envision\ a\ closure/stack-frame\ object\ that\ you'd\ access\ through\ \[upvar\]\nA\ proper\ closure\ keeps\ track\ of\ all\ enclosing\ stack\ frames,\ but\ that's\ probably\ more\ than\ is\ needed\ for\ most\ purposes.\nThen\ you\ could\ also\ store\ the\ object\ as\ an\ argument\ to\ the\ proc\ using\ aliases...\nAnd\ that'd\ work.\nSo\ long\ as\ the\ closure\ doesn't\ get\ disposed\ of\ too\ early.\nWe\ really\ need\ to\ extend\ Tcl_ObjType\ when\ we\ come\ to\ \[Tcl9\].\n===\n----\n\[glennj\]\ It\ took\ me\ a\ while\ to\ figure\ out\ how\ aliases\ could\ work\ like\ closures\ in\ the\ above\ discussion.\ \ I\ think\ I\ came\ up\ with\ an\ example:\ a\ procedure\ returns\ the\ number\ of\ times\ it's\ been\ invoked:\n======\n\ \ #\ the\ first\ time,\ send\ \"0\"\ to\ the\ aliased\ proc\n\ \ interp\ alias\ \{\}\ countMe\ \{\}\ _countMe\ 0\n\n\ \ proc\ _countMe\ \{count\}\ \{\n\ \ \ \ \ \ #\ for\ the\ next\ invocation,\ reset\ the\ alias\n\ \ \ \ \ \ interp\ alias\ \{\}\ countMe\ \{\}\ _countMe\ \[incr\ count\]\n\ \ \ \ \ \ return\ \$count\n\ \ \}\n\n\ \ puts\ \[countMe\]\ \;#\ ==>\ 1\n\ \ puts\ \[countMe\]\ \;#\ ==>\ 2\n\ \ puts\ \[countMe\]\ \;#\ ==>\ 3\n======\n-------\n''Another\ attempt\ at\ \[Emulating\ Closures\ in\ Tcl\]''\n\n\[Todd\ Coram\]\ -\nWhile\ playing\ with\ \[PostgresSQL\],\ I\ got\ tired\ of\ passing\ around\ \nthe\ ''connection\ id''\ to\ each\ postgres\ tcl\ command\ (plus\ there\ was\ some\nother\ contextual\ info\ I\ wanted\ to\ keep\ around\ with\ each\ connection).\n\nObjectifying\ the\ postgres\ interface\ seemed\ over-kill\ and\ keeping\ state\ in\na\ single\ namespace\ prevented\ me\ from\ keeping\ more\ than\ one\ database\ connection\ open\ \nat\ a\ time.\ I\ could\ have\ used\ the\ classic\ objectifying\ technique\ of\ keeping\nthe\ instance\ info\ in\ array,\ but\ this\ felt\ clumsy.\ I\ could\ have\ curried\ the\ connection\ id\nto\ postgres\ commands,\ but\ that\ felt\ too\ restricting.\n\nClosures\ are\ neat\ because\ they\ give\ you\ a\ way\ to\ let\ functions\ carry\ a\ bit\nof\ state\ with\ it.\ Tcl\ Namespaces\ give\ you\ most\ of\ what\ you\ need,\ but\ you\nstart\ to\ bleed\ into\ ''object\ land''\ when\ you\ try\ to\ create\ more\ than\ one\nexclusive\ set\ of\ variables.\n\nSo,\ thus\ was\ born\ this\ late\ night\ hacked\ attempt\ at\ emulating\ closures\ in\ Tcl:\n\n======\n\ #\ Create\ a\ proc\ named\ 'name'\ that\ will\ create\ a\ closure\ over\ the\ supplied\n\ #\ 'variables'\ definition\ for\ the\ 'lambda_proc'.\ Any\ supplied\ variables\ in\n\ #\ 'arglist'\ can\ be\ used\ to\ initialize\ 'variables'\ during\ the\ closure\n\ #\ definition.\n\ #\n\ proc\ make-closure-proc\ \{name\ arglist\ variables\ lambda_proc\}\ \{\n\ \ \ \ set\ invoke_context\ \[uplevel\ namespace\ current\]\n\ \ \ \ set\ name_context\ \$\{invoke_context\}::\$name\n\n\ \ \ \ #\ Create\ a\ namespace\ called\ \$name_context\ to\ hold\ auto_cnt\n\ \ \ \ #\n\ \ \ \ namespace\ eval\ \$name_context\ \{\n\ \ \ \ \ \ \ if\ \{!\[info\ exists\ auto_cnt\]\}\ \{\ variable\ auto_cnt\ -1\}\n\ \ \ \ \}\n\n\ \ \ \ #\ Now,\ build\ a\ proc\ in\ invocation\ context\ that\ will\ create\n\ \ \ \ #\ closures.\ We\ do\ this\ by\ substituting\ all\ of\ the\ passed\n\ \ \ \ #\ parameters\ (name,\ arglist,\ variables,\ lambda_proc)\ and\ the\n\ \ \ \ #\ \$name_context.\n\ \ \ \ #\n\ \ \ \ #\ The\ resulting\ proc\ will:\n\ \ \ \ #\ 1.\ Accept\ \$arglist\ as\ initializers\ for\ the\ closures.\n\ \ \ \ #\ 2.\ Create\ a\ unique\ closure_name\ from\ the\ auto_cnt\ variable.\n\ \ \ \ #\ 3.\ Create\ a\ namespace\ for\ the\ closure.\n\ \ \ \ #\ 4.\ Evaluate\ the\ \$variables\ (optionally\ evaluating\ them\ with\n\ \ \ \ #\ \ \ \ \$arglist).\n\ \ \ \ #\ 5.\ Create\ an\ alias\ called\ 'dispatch'\ for\ the\ lambda_proc.\n\ \ \ \ #\ 6.\ Return\ the\ alias.\n\ \ \ \ #\n\ \ \ \ namespace\ eval\ \$invoke_context\ \\\n\ \ \ \ \ \ \ \[subst\ -nocommands\ -nobackslashes\ \{\n\ \ \ \ \ \ \ \ \ \ \ proc\ \$name\ \{\$arglist\}\ \{\ \n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ closure_name\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \$\{name_context\}::\$name\[incr\ \$\{name_context\}::auto_cnt\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ eval\ \[subst\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ namespace\ eval\ \[set\ closure_name\]\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \$variables\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ namespace\ eval\ \[set\ closure_name\]\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Curry\ a\ dispatcher\ for\ the\ lambda_proc.\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ curry\ \[namespace\ current\]::dispatch\ \[\$lambda_proc\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\ \n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \[set\ closure_name\]::dispatch\}\n\ \ \ \ \ \ \ \ \ \ \ \ \}\]\n\ \}\n\n\ proc\ delete-closure\ \{name\}\ \{\n\ \ \ \ \ namespace\ delete\ \[namespace\ qualifiers\ \$name\]\n\ \}\n======\nI\ used\ a\ curry\ proc\ to\ create\ the\ dispatcher\ (I\ really\ don't\ create\ a\ curry\nand\ perhaps\ ''namespace\ code''\ could\ accomplish\ a\ similiar\ thing,\ but\ I\ had\ a\ curry\ proc\ handy,\ so\ there):\n======\n\ proc\ curry\ \{new\ args\}\ \{\n\ \ \ \ uplevel\ \[list\ interp\ alias\ \{\}\ \$new\ \{\}\]\ \$args\n\ \}\n======\nAnd\ a\ lambda\ proc\ to\ pass\ to\ the\ make-closure-proc:\n======\n\ proc\ lambda\ \{arglst\ body\}\ \{\n\ \ \ \ set\ level\ \[info\ level\ 0\]\n\ \ \ \ set\ name\ \[string\ map\ \{\\n\ _\ \\t\ _\ \\\"\ _\ \"\ \"\ _\ \\\;\ _\ \$\ _\ :\ _\ \\\{\ _\ \\\}\ _\ \\\[\ _\ \\\]\ _\}\ \$level\]\n\ \ \ \ set\ invoke_context\ \[uplevel\ namespace\ current\]\n\ \ \ \ proc\ \$\{invoke_context\}::\$name\ \$arglst\ \$body\n\ \ \ \ return\ \$\{invoke_context\}::\$name\n\ \}\n======\nHere\ is\ a\ (contrived)\ example\ of\ how\ to\ create\ and\ use\ the\ closures:\n======\n\ make-closure-proc\ make-logputs\ \{_level\ _filename\}\ \{\n\ \ \ \ variable\ fd\ \[open\ \$_filename\ w\]\n\ \ \ \ variable\ filename\ \$_filename\n\ \ \ \ variable\ level\ \$_level\n\ \}\ \{\n\ \ \ \ lambda\ \{cmd\ \{str\ \"\"\}\}\ \{\n\ \ \ \ \ \ \ \ variable\ fd\;\ variable\ filename\;\ variable\ level\n\ \ \ \ \ \ \ \ switch\ --\ \$cmd\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ puts\ \{\ \n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ puts\ \"Writing\ (\$level\ to\ \$filename)\ \$str\"\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ puts\ \$fd\ \"(\[clock\ format\ \[clock\ seconds\]\]\ -\ \$level)\ \$str\"\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ close\ \{\ \n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ close\ \$fd\ \n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \}\n\n\ set\ info\ \[make-logputs\ INFO\ info.out\]\n\ set\ warn\ \[make-logputs\ WARN\ warn.out\]\n\n\ \$info\ puts\ \"Some\ info:\ hello\ world\"\n\ \$info\ puts\ \"blech\"\n\ \$warn\ puts\ \"You\ have\ been\ warned!\"\n\n\ \$info\ close\n\ \$warn\ close\n\n\ delete-closure\ \$info\n\ delete-closure\ \$warn\n======\n----\n\[GN\]\ There\ is\ a\ strong\ relation\ between\ objects\ and\nclosures.\ a\ classical\ paper\ is\ from\ Uday\ Reddy\n\"Objects\ as\ closures:\ abstract\ semantics\ of\ object-oriented\ languages\",\nwho\ defines\ objects\ as\ an\ \"message\ environment\"\ (binding\ messages\nto\ methods)\ with\ an\ hidden\ local\ environment\ (binding\ instance\nvariables\ to\ values).\ \n\nThis\ is\ pretty\ close\ to\ the\ notion\ of\ objects\ in\ XOTcl\;\ \nthe\ example\ above\ can\ be\ written\ much\ simpler\ with\ \[XOTcl\]\ (certainly\nwith\ other\ \[oo\]\ languages\ as\ well):\n======\n\ package\ require\ XOTcl\;\ namespace\ import\ -force\ xotcl::*\n\n\ Class\ Logger\ -parameter\ \{level\ filename\}\n\ Logger\ instproc\ init\ \{\}\ \{\n\ \ \ my\ instvar\ fd\ filename\n\ \ \ set\ fd\ \[open\ \$filename\ w\]\n\ \}\n\ Logger\ instproc\ puts\ \{str\}\ \{\n\ \ \ my\ instvar\ level\ filename\ fd\n\ \ \ puts\ \"Writing\ (\$level\ to\ \$filename)\ \$str\"\n\ \ \ puts\ \$fd\ \"(\[clock\ format\ \[clock\ seconds\]\]\ -\ \$level)\ \$str\"\n\ \}\n\ Logger\ instproc\ close\ \{\}\ \{\n\ \ \ my\ instvar\ fd\n\ \ \ close\ \$fd\n\ \}\n\n\ set\ info\ \[Logger\ new\ -level\ INFO\ -filename\ info.out\]\n\ set\ warn\ \[Logger\ new\ -level\ WARN\ -filename\ warn.out\]\n\n\ \$info\ puts\ \"Some\ info:\ hello\ world\"\n\ \$info\ puts\ \"blech\"\n\ \$warn\ puts\ \"You\ have\ been\ warned!\"\n\n\ \$info\ close\n\ \$warn\ close\n\n\ \$info\ destroy\n\ \$warn\ destroy\n======\n----\n\[TV\]\ Isn't\ closure\ like\ in\ physics\ where\ you'd\ have\ a\ mathematical\ construct\ which\ is\ 'closed',\ which\ is\ usually\ pretty\ darn\ hard\ and\ often\ quite\ useless\ except\ probably\ in\ some\ essential\ fundamental\ cases.\n\n\[DKF\]:\ That's\ essentially\ unrelated.\ (And\ that's\ a\ maths/topology\ concept\ which\ physics\ has\ borrowed.)\n----\nSee\ \[custom\ curry\]\ and\ the\ references\ there\ for\ an\ explanation\ of\ ''curry''\ and\ ''currying\ function''.\n----\n\[RS\]\ asks:\ Could\ one\ say\ the\ following\ are\ (rudimentary)\ examples\ of\ closures?\n\n'''1.\ Default\ arguments'''\ (in\ danger\ to\ be\ overwritten\ by\ caller)\;\n======\n\ proc\ foo\ \{a\ b\ \{c\ 1\}\ \{d\ 2\}\ \{e\ 3\}\}\ \{...\}\n======\n\n'''2.\ Name-value\ map\ in\ an\ explicit\ argument'''\ \n======\n\ set\ closure\ \[list\ c\ 1\ d\ 2\ e\ 3\]\n\ ...\n\ proc\ bar\ \{a\ b\ closure\}\ \{\n\ \ \ \ \ foreach\ \{name\ value\}\ \$closure\ \{set\ \$name\ \$value\}\n\ \ \ \ \ ...\n\ \}\n======\n'''3.\ Closure\ values\ passed\ in\ over\ an\ alias:'''\n======\n\ proc\ _grill\ \{c\ d\ e\ a\ b\}\ \{...\}\n\ ...\n\ interp\ alias\ \{\}\ grill\ \{\}\ _grill\ 1\ 2\ 3\n======\n----\n\[Zarutian\]s\ first\ attempt\ at\ closures:\n======\n\ package\ require\ Tcl\ 8.4\n\ proc\ closure_var\ args\ \{\n\ \ \ set\ varname\ \[lindex\ \$args\ 0\]\n\ \ \ set\ value\ \ \ \[lindex\ \$args\ 1\]\n\ \ \ upvar\ \$varname\ breyta\n\ \ \ set\ breyta\ \$value\n\ \ \ trace\ remove\ variable\ breyta\ \{write\}\ update_closure_var\ \;\ #\ to\ prevent\ multiple\ trace\ clones\n\ \ \ trace\ add\ variable\ breyta\ \{write\}\ update_closure_var\n\ \}\n\ proc\ update_closure_var\ \{varname1\ varname2\ op\}\ \{\n\ \ \ if\ \{\$varname2\ !=\ \"\"\}\ \{\n\ \ \ \ \ set\ varname\ \"\[set\ varname1\](\[set\ varname2\])\"\n\ \ \ \}\ else\ \{\n\ \ \ \ \ set\ varname\ \$varname1\n\ \ \ \}\n\ \ \ upvar\ \$varname\ newvalue\n\ \ \ debug\ \[info\ level\ 1\]\ \$varname\ \$op\ \$newvalue\n\ \ \ #\ redefine\ the\ calling\ proc\ to\ reflect\ the\ variables\ new\ value\n\ \n\ \ \ set\ procsName\ \[lindex\ \[info\ level\ 1\]\ 0\]\n\ \ \ set\ procsArgs\ \[info\ args\ \$procsName\]\n\ \ \ set\ procsBody\ \[info\ body\ \$procsName\]\n\ \ \n\ \ \ debug\ \$procsName\ \$procsArgs\n\ \ \ debug\ \$procsBody\n\ \ \ \n\ \ \ set\ temp\ \"closure_var\ \$varname\"\n\ \ \ set\ insertLoc\ \[expr\ \[string\ last\ \$temp\ \$procsBody\]\ +\ \[string\ length\ \$temp\]\]\n\ \ \ set\ firstHalf\ \[string\ range\ \$procsBody\ 0\ \$insertLoc\]\n\ \ \ set\ lastHalf\ \ \[string\ range\ \$procsBody\ \$insertLoc\ end\]\n\ \ \ set\ procsBody\ \"\[set\ firstHalf\]\\\{\[set\ newvalue\]\\\}\[set\ lastHalf\]\"\n\ \ \ \n\ \ \ debug\ \$procsBody\n\ \ \ \n\ \ \ proc\ \$procsName\ \$procsArgs\ \$procsBody\n\ \}\n\ proc\ debug\ args\ \{\ puts\ \"\$args\"\ \}\n\ proc\ someFunction\ \{\}\ \{\n\ \ \ closure_var\ blu\ 21\n\ \ \ set\ blu\ 234\n\ \}\n======\nThe\ above\ implemention\ doesn't\ handle\ that\ when\ other\ sub-procs\ upvar\ a\ closure_var\ .\nThe\ next\ implemention\ of\ closures\ from\ Zarutian\ will\ have\ that\ fixed.\n\n\[Zarutian\]s\ second\ attempt\ at\ closures\n======\n\ package\ require\ Tcl\ 8.4\n\n\ proc\ closure_var\ args\ \{\n\ \ \ set\ varname\ \[lindex\ \$args\ 0\]\n\ \ \ set\ value\ \ \ \[lindex\ \$args\ 1\]\n\ \ \ upvar\ \$varname\ breyta\n\ \ \ set\ breyta\ \$value\n\ \ \ trace\ remove\ variable\ breyta\ \{write\}\ \[list\ update_closure_var\ \$varname\]\;\ #\ to\ prevent\ multiple\ trace\ clones\n\ \ \ trace\ add\ variable\ breyta\ \{write\}\ \[list\ update_closure_var\ \$varname\]\n\ \}\n\ proc\ update_closure_var\ \{originalVarname\ varname1\ varname2\ op\}\ \{\n\ \ \ if\ \{\$varname2\ !=\ \"\"\}\ \{\n\ \ \ \ \ set\ varname\ \"\[set\ varname1\](\[set\ varname2\])\"\n\ \ \ \}\ else\ \{\n\ \ \ \ \ set\ varname\ \$varname1\n\ \ \ \}\n\ \ \ upvar\ 1\ \$varname\ newvalue\n\ \ \ debug\ \[info\ level\ 1\]\ \$varname\ \$op\ \$newvalue\n\ \ \ #\ redefine\ the\ calling\ proc\ to\ reflect\ the\ variables\ new\ value\n\ \n\ \ \ set\ procsName\ \[lindex\ \[info\ level\ 1\]\ 0\]\n\ \ \ set\ procsArgs\ \[info\ args\ \$procsName\]\n\ \ \ set\ procsBody\ \[info\ body\ \$procsName\]\n\n\ \ \ debug\ \$procsName\ \$procsArgs\n\ \ \ debug\ \$procsBody\n\n\ \ \ set\ temp\ \"closure_var\ \$originalVarname\"\n\ \ \ debug\ \$temp\n\ \ \ set\ insertLoc\ \[expr\ \[string\ last\ \$temp\ \$procsBody\]\ +\ \[string\ length\ \$temp\]\]\n\n\ \ \ set\ firstHalf\ \[string\ range\ \$procsBody\ 0\ \$insertLoc\]\ \n\ \ \ set\ lastHalf\ \ \[string\ range\ \$procsBody\ \$insertLoc\ end\]\n\ \ \ set\ procsBody\ \"\[set\ firstHalf\]\\\{\[set\ newvalue\]\\\}\[set\ lastHalf\]\"\n\n\ \ \ debug\ \$procsBody\n\n\ \ \ proc\ \$procsName\ \$procsArgs\ \$procsBody\n\ \}\n\ proc\ debug\ args\ \{\ puts\ \"\$args\"\ \}\n\ proc\ someFunction\ \{\}\ \{\n\ \ \ closure_var\ blu\ 21\n\ \ \ decr\ blu\n\ \}\n\ proc\ decr\ \{varname\ \{delta\ 1\}\}\ \{\n\ \ \ upvar\ 1\ \$varname\ var\n\ \ \ set\ var\ \[expr\ \$var\ -\ \$delta\]\n\ \}\n======\nThis\ implemention\ should\ work\ fine\ with\ other\ sub-procs\ upvaring\ closure_vars.\nBut\ these\ two\ implementions\ have\ one\ catch/issue:\ namely\ that\ every\ previus\ value\ of\ a\ closure_var\ is\ saved\ too.\nI\ am\ trieing\ find\ out\ how\ it\ is\ possible\ to\ get\ the\ old\ value\ of\ a\ variable\ before\ it\ is\ updated\ to\ the\ new\nvalue\ so\ I\ can\ fix\ that\ catch/issue\n\nJust\ to\ be\ sure:\ isnt\ a\ closure\ just\ a\ procedure\ with\ some\ state\ saved\ with\ it,\ no?\n----\n\[SS\]\ 30\ Dec\ 2004:\ For\ the\ Tcl\ semantic,\ lexical\ binding\ is\ hard\ because\ it's\ not\ possible\ to\ tell\ from\ the\ source\ code\ what's\ a\ reference\nto\ a\ variable\ and\ what\ is\ not.\ Still\ it's\ possible\ to\ capture\ the\ context\ of\ a\ lambda's\ creation\ saving\ the\ current\ stack\ frame,\ thus\nallowing\ for\ real\ closures\ (procedures\ where\ if\ some\ variable\ can't\ be\ resolved\ in\ the\ local\ context,\ will\ try\ to\ access\ the\ stack\ frame\nthat\ was\ active\ at\ the\ procedure\ creation\ time).\ Because\ of\ the\ way\ Tcl\ works\ and\ the\ fact\ it's\ so\ dynamic\ I'm\ not\ sure\ closures\ may\nsignificantly\ help\ Tcl\ programming,\ '''but'''\ when\ they\ are\ used\ as\ objects.\ It's\ a\ more\ interesting\ addition\ to\ have\ an\ object\ system\ with\ngarbage\ collection.\ Because\ in\ most\ Tcl\ objects\ systems\ objects\ are\ \"callable\",\ like\ in\ \[\[\$o\ a\ b\ c\]\],\ objects\ can\ be\ used\ to\ do\ most\ of\ the\nthings\ you\ may\ like\ to\ do\ with\ closures,\ they\ are\ very\ similar\ to\ procedures\ but\ can\ take/alter\ their\ internal\ state.\nOf\ course\ this\ is\ possible\ to\ do\ even\ with\ OOP\ systems\ not\ having\ garbage\ collection,\ but\ the\ programming\ style\ that\ closures\ make\npossible\ is\ often\ about\ to\ capture\ some\ information\ to\ semplify/specialize\ the\ next\ uses\ of\ a\ given\ procedure,\ it's\ hard\ to\ think\ at\ this\nprogramming\ style\ as\ comfortable\ if\ you\ have\ to\ clean\ by\ hand\ the\ objects.\n----\n\[Zarutian\]\ wrote\ on\ 2.\ jan\ 2005:\nappend\ this\ to\ my\ second\ attempt\ at\ closures:\n\ ======\n\ proc\ closure\ \{name\ args\ body\}\ \{\n\ \ \ set\ locals\ \[uplevel\ 1\ \[list\ info\ locals\]\]\n\ \ \ foreach\ loco\ \$locals\ \{\n\ \ \ \ \ set\ body\ \"\[list\ closure_var\ \$loco\ \[uplevel\ 1\ \[list\ set\ \$loco\]\]\]\\n\[set\ body\]\"\n\ \ \ \}\n\ \ \ proc\ \$name\ \$args\ \$body\n\ \}\n======\nand\ I\ think\ you\ have\ got\ something\ like\ that\ \[SS\]\ described\ above.\n----\n\[SS\]\ 3\ Jan\ 2004:\ Yeah\ this\ is\ a\ smart\ idea,\ to\ capture\ the\ context.\ Still\ there\ are\ a\ few\ things\ to\ fix,\ and\ many\ other\ things\nthat\ we\ can't\ fix\ at\ all.\ What\ should\ be\ fixed\ is\ that\ this\ way\ you\ set\ the\ locals\ variables\ even\ if\ the\ name\ is\ the\ same\ as\ one\nof\ the\ procedure\ arguments,\ that's\ not\ correct:\ if\ there\ is\ an\ argument\ with\ that\ name,\ the\ symbol\ should\ be\ bound\ to\ it.\nSecond,\ in\ real\ closures,\ many\ closures\ can\ *share*\ the\ environment,\ and\ can\ modify\ it\ (and\ every\ other\ closure\ bound\ to\ the\ same\nexternal\ variables\ will\ see\ the\ change).\ We\ can't\ get\ that\ far\ with\ Tcl\ of\ course,\ but\ still\ your\ exercise\ is\ very\ interesting\nand\ valuable\ IMHO.\n\n\[DKF\]:\ I\ use\ something\ very\ much\ like\ closures\ in\ my\ \[oo2\]\ code.\ \ Basically,\ \[dict\]'s\ '''update'''\ and\ '''with'''\ subcommands\ (together\ with\ some\ wrapping\ scripts)\ allow\ for\ closure-like\ behaviour\ very\ easily.\ The\ complexity\ is\ that\ the\ closure\ is\ actually\ stored\ in\ a\ \"global\"\ variable,\ but\ as\ long\ as\ you\ ignore\ the\ man\ behind\ the\ curtain,\ you're\ OK...\ \;^)\n\n\[Zarutian\]\ 4.\ jan\ 2005:\ \[SS\]\ are\ you\ speaking\ from\ the\ past?\ \;-)\ Because\ I\ hope\ you\ meant\ 3\ Jan\ '''2005'''.\n\nAnyway,\ I\ should\ get\ to\ the\ point.\ As\ I\ understand\ it\ Tcl\ procedure's\ enviroment\ is\ three\ leveled:\ global,\ local\ to\ procedure's\ namespace,\ local\ to\ procedure's\ level/callstack.\n\nThen\ when\ variable\ lookup\ is\ performed\ (either\ because\ of\ Tcl's\ seventh\ substitution\ rule\ or\ procedure\ set\ is\ invoked)\ inside\ a\ procedure's\ body\ (the\ procedure\ was\ called)\ the\ interpreter\ first\ looks\ for\ the\ variable\ in\ local\ callstack\ scope\ then\ in\ procedure's\ namespace\ (if\ that\ variable\ name\ was\ marked\ by\ calling\ the\ procedure\ 'variable')\ and\ at\ last\ in\ the\ global\ namespace\ (likewise\ if\ the\ variable\ name\ was\ marked\ by\ calling\ the\ procedure\ 'global').\n\nWhere\ other\ scripting\ languages\ like\ \[Lua\]\ and\ \[Lisp\]\ variants\ use\ linked\ tables/hashmaps/dictionaries\ and\ lookup\ the\ variable's\ value\ in\ the\ parent\ table\ of\ the\ current\ variable|value\ binding\ table\ if\ not\ found\ in\ current\ until\ the\ top\ most\ variable|value\ binding\ table\ is\ reached.\ (Hmm...\ the\ preceeding\ sentence\ may\ be\ unclear\ because\ of\ my\ lack\ of\ skill\ writing\ English)\ \n\nHere\ above\ I\ have\ descriped\ two\ possible\ ways\ to\ look\ up\ values\ for\ variables.\nSo\ I\ ask\ what\ are\ the\ 'pros'\ and\ 'cons'\ of\ each?\n\nIn\ my\ opinion\ I\ think\ the\ latter\ method\ enables\ more\ flexibility\ of\ variable\ lookup\ for\ value.\n\{IS:\ Að\ mínu\ áliti\ held\ ég\ að\ síðari\ aðferðin\ gefi\ kost\ á\ meiri\ liðleika\ til\ að\ fletta\ upp\ gildi\ breytu.\}\n\n----\n\[SS\]\ 23Feb2005:\n\nThis\ is\ a\ proposal\ for\ closures\ I\ made\ in\ comp.lang.tcl:\n\nFrom\ time\ to\ time\ there\ is\ this\ discussion\ about\ adding\ closures\ to\nTcl,\ but\ usually\ the\ idea\ is\ to\ make\ they\ similar\ to\ languages\ like\n\[Scheme\],\ i.e.\ closures\ with\ lexical\ scoping.\ My\ opinion\ is\ that\ this\ is\nvery\ hard\ to\ do\ with\ Tcl,\ and\ even\ not\ in\ the\ spirit\ of\ the\ language.\nIn\ a\ Tcl\ program,\ what\ part\ of\ a\ procedure\ body\ is\ a\ variable\ is\ not\ndefined\ until\ execution,\ for\ example:\n======\n\ set\ a\ 10\n\ closure\ \{x\}\ \{\n\ \ \ \ incr\ a\n\ \}\n======\nThen\ I\ define\ 'incr'\ to\ be\ like\ 'puts',\ and\ 'a'\ is\ no\ longer\ a\ variable.\nIt\ was\ already\ suggested\ that\ in\ Tcl\ closures\ should\ not\ have\ any\ kind\ of\ creation-time\ resolution\ rule,\ but\ that\ the\ context\ where\ they\ are\ndefined\ should\ be\ captured\ as\ a\ whole,\ and\ used\ when\ the\ closure\ is\ running\ to\ resolve\ \"unbound\ symbols\"\ (that\ are\ better\ referred\ as\ variables\ and\ procedures\ not\ otherwise\ defined\ during\ execution\ in\nTcl\ slang).\ Still\ there\ is\ the\ problem\ that\ to\ similuate\ the\ lexical\ scoping\ you\ have\ to\ take\ *references*\ to\ the\ shared\ environment,\ so\ that:\n======\n\ set\ a\ 10\n\ set\ foo\ \[closure\ \{x\}\ \{\n\ \ \ \ incr\ a\ \$x\n\ \}\]\n\ set\ bar\ \[closure\ \{x\}\ \{\n\ \ \ \ incr\ a\ \$x\n\ \}\]\n\ \$foo\ 1\;#\ ->\ 11\n\ \$bar\ 1\;#\ ->\ 12\n======\nfoo\ and\ bar\ will\ share\ the\ same\ 'a'.\n\ \nI\ think\ this\ is\ a\ all\ to\ complex\ and\ UnTclish,\ so\ I\ tried\ to\ design\ a\ new\ semantic\ for\ closures.\n\ \nThe\ semantic\ is\ based\ on\ a\ single\ command\ \[closure\],\ that\ can\ set/get\nclosure\ variables\ in\ the\ scope\ of\ the\ current\ procedure,\ together\ with\na\ minimal\ change\ in\ the\ \[proc\]\ and\ \[lambda\]\ command\ (I\ know\ we\ don't\ have\ lambda...\ but\ still\ there\ is\ a\ way\ Tcl\ users\ already\ think\ about\nit\ and\ should\ change).\n\ \nBasically,\ to\ set\ a\ closure\ variable,\ there\ is\ to\ write\ the\ following\ command:\n======\n\ closure\ set\ x\ 10\n======\nthis\ will\ set\ 'x'\ inside\ the\ closure\ of\ the\ current\ procedure.\ This\ 'x'\nwill\ be\ persistent\ accross\ different\ calls\ of\ this\ procedure,\ and\ all\nthis\ environment\ will\ be\ destroied\ once\ the\ procedure\ itself\ is\ destroied.\ The\ procedure\ can\ test\ for\ the\ existence\ of\ a\ closure\ variable\ with\ \[\[closure\ exists\ x\]\],\ can\ get\ the\ value\ with\ \[\[closure\ get\ x\]\]\nand\ so\ on.\n\ \nThe\ change\ required\ to\ the\ \[proc\]\ command,\ is\ that\ it\ can\ take\ an\ optional\ further\ argument,\ that's\ a\ Tcl\ list\ of\ key/value\ pairs\ used\nto\ inizialize\ the\ closure\ at\ procedure\ creation\ time.\n\ \nso:\n======\n\ proc\ foo\ \{\}\ \{\ ....\ \}\ \{x\ 10\ y\ 20\}\n======\nwill\ create\ the\ procedure\ foo\ with\ x=10\ and\ y=20\ inside\ the\ closure.\nThe\ same\ for\ \[lambda\].\n\ \nThe\ following\ is\ an\ example\ of\ procedure\ that\ returns\ a\ progressive\ integer\ number\ every\ time\ it's\ called:\n======\n\ proc\ counter\ \{\}\ \{\n\ \ \ \ if\ \{!\[closure\ exists\ x\]\}\ \{\n\ \ \ \ \ \ \ \ \ set\ x\ 0\n\ \ \ \ \}\n\ \ \ \ set\ x\ \[closure\ get\ x\]\n\ \ \ \ closure\ set\ x\ \[expr\ \$x+1\]\n\ \ \ \ return\ \$x\n\ \}\n======\nOf\ course\ it's\ better\ to\ use\ the\ optional\ argument\ of\ proc\ and\ write\ it\ as:\n======\n\ proc\ counter\ \{\}\ \{\n\ \ \ \ set\ x\ \[closure\ get\ x\]\n\ \ \ \ closure\ set\ x\ \[expr\ \$x+1\]\n\ \ \ \ return\ \$x\n\ \}\ \{x\ 0\}\n======\nOf\ course\ for\ this\ to\ be\ very\ useful,\ lambda\ it's\ needed.\nThis\ version\ of\ lambda,\ like\ proc,\ should\ accept\ the\ optional\nargument\ to\ initialize\ the\ closure.\ This\ is\ an\ example:\n======\n\ proc\ createAdder\ \{x\}\ \{\n\ \ \ \ lamba\ \{y\}\ \{expr\ \$y+\[closure\ get\ \$x\]\}\ \[list\ x\ \$x\]\n\ \}\n\ \n\ set\ f\ \[createAdder\ 5\]\n\ \$f\ 10\ \;#\ ->\ 15\n======\nI\ think\ that\ this\ design\ can\ do\ everything\ lexical\ scoping\ is\ able\ to\ndo,\ but\ with\ a\ command-based\ interface\ that\ plays\ better\ with\ Tcl.\n\ \nThis\ kind\ of\ closures\ will\ be\ added\ into\ the\ Jim\ interpreter,\ a\nsmall\ footprint\ Tcl\ interpreter\ I'm\ writing.\ This\ interpreter\ is\ already\nworking\ and\ I'll\ be\ happy\ to\ send\ a\ preview\ tar.gz\ to\ interested\npeople\ (the\ license\ is\ the\ APACHE2,\ so\ it's\ possible\ to\ use\ Jim\ in\ncommercial\ projects\ if\ needed).\n\nRegards,<<br>>Salvatore\ \n\nand\ then\ I\ replyed\ to\ myself\ with\ this\ message:\n\nI\ forgot\ to\ include\ a\ couple\ of\ points.\n\ \nThe\ closure\ command\ can\ also\ access\ closures\ of\ external\ procedures:\n\ \n\ \[closure\ in\ \$procName\ get/set\ x\ ...\]\ and\ so\ on.\nThis\ makes\ possible\ to\ share\ the\ environment\ if\ really\ needed.\nExample:\n======\n\ proc\ createAdder\ \{x\}\ \{\n\ \ \ \ set\ a\ \[lamba\ \{y\}\ \{expr\ \$y+\[closure\ get\ \$x\]\}\ \[list\ x\ \$x\]\]\n\ \ \ \ set\ b\ \[lamba\ \{incr\}\ \{closure\ in\ \$a\ set\ x\ \$incr\}\ \[list\ a\ \$a\]\]\n\ \ \ \ list\ \$a\ \$b\n\ \}\n======\nthis\ returns\ one\ closure\ to\ add\ and\ one\ to\ change\ the\ increment\nperformed\ by\ the\ first\ closure.\n\ \nAlso\ it\ is\ worth\ to\ note\ that\ this\ way\ to\ do\ closures\ don't\ play\nwell\ with\ functions\ as\ values\ nor\ with\ lambas\ based\ on\ auto\ expansion,\nbecause\ full\ closures\ need\ to\ be\ able\ to\ modify\ their\ environment\nso\ they\ can\ not\ be\ immutable\ values.\n\nCiao,<<br>>Salvatore\ \n\n----\n\[NEM\]\ offers\ the\ following\ as\ a\ simple\ closure-like\ thing:\n======\n\ proc\ closure\ \{name\ arglist\ body\}\ \{\n\ \ \ \ if\ \{!\[string\ match\ ::*\ \$name\]\}\ \{\n\ \ \ \ \ \ \ \ #\ Not\ fully\ qualified\n\ \ \ \ \ \ \ \ set\ ns\ \[uplevel\ 1\ namespace\ current\]\n\ \ \ \ \ \ \ \ set\ name\ \$\{ns\}::\$name\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ set\ name\ \$name\n\ \ \ \ \}\n\ \ \ \ set\ sname\ \[namespace\ tail\ \$name\]\n\ \ \ \ #\ Just\ create\ a\ proc\ as\ usual,\ but\ a\ namespace\ along\ with\ it\n\ \ \ \ namespace\ eval\ \$name\ \[list\ proc\ \$sname\ \$arglist\ \$body\]\n\ \ \ \ interp\ alias\ \{\}\ \$name\ \{\}\ \$\{name\}::\$sname\n\ \}\n======\nand\ a\ test:\n======\n\ closure\ make-counter\ \{start\}\ \{\n\ \ \ \ \ variable\ id\n\ \ \ \ \ if\ \{!\[info\ exists\ id\]\}\ \{\ set\ id\ 0\ \}\n\ \ \ \ \ incr\ id\n\ \ \ \ \ closure\ counter-\$id\ \{\{amount\ 1\}\}\ \[string\ map\ \[list\ %S\ \$start\]\ \{\n\ \ \ \ \ \ \ \ \ variable\ counter\n\ \ \ \ \ \ \ \ \ if\ \{!\[info\ exists\ counter\]\}\ \{\ set\ counter\ %S\ \}\n\ \ \ \ \ \ \ \ \ incr\ counter\ \$amount\n\ \ \ \ \ \}\]\n\ \ \ \ \ return\ \[namespace\ current\]::counter-\$id\n\ \}\n======\nCould\ do\ with\ a\ bit\ of\ tarting\ up,\ and\ it's\ not\ as\ powerful\ as\ closures\ in\ Scheme,\ which\ get\ a\ lot\ of\ their\ power\ from\ lexical\ scoping.\ Still,\ it\ goes\ quite\ a\ long\ way,\ I\ think.\ Oh,\ and\ you\ can\ do\ drop-dead\ simple\ \[ensemble\]s\ too:\n======\n\ (tile)\ 57\ %\ closure\ MyEnsemble\ \{method\ args\}\ \{\n\ \n\ \ \ closure\ say\ \{message\}\ \{\ puts\ \"Say:\ \$message\"\ \}\n\ \ \ closure\ sing\ \{message\}\ \{\ puts\ \"Sing:\ \$message!\"\ \}\n\ \n\ \ \ \$method\ \{expand\}\$args\n\ \}\n\ ::::MyEnsemble\n\ (tile)\ 58\ %\ MyEnsemble\n\ wrong\ #\ args:\ should\ be\ \"::::MyEnsemble::MyEnsemble\ method\ ...\"\n\ (tile)\ 59\ %\ MyEnsemble\ say\ Hello\n\ Say:\ Hello\n\ (tile)\ 60\ %\ MyEnsemble\ sing\ \"Tra-la-la\"\n\ Sing:\ Tra-la-la!\n======\n----\n\[Sarnold\]\ 2010-Feb-5:\ Here\ is\ my\ own\ implementation\ of\ simple\ closures.\ To\ use\ them\ you\ will\ have\ to\ store\ them\ in\ a\ variable\ and\ pass\ its\ name\ to\ a\ custom\ applyc\ (apply-closure)\ proc,\ which\ saves\ the\ environment\ in\ the\ variable\ holding\ the\ closure.\ The\ closure\ proc\ creates\ a\ closure\ (a\ list)\ by\ passing\ to\ it\ a\ variable\ list\ for\ the\ environment.\ (this\ is\ AFAIK\ the\ way\ you\ create\ closures\ in\ PHP)\n\n======\npackage\ require\ Tcl\ 8.5\n\nproc\ closure\ \{arglist\ args\}\ \{\n\ \ \ \ \ \ \ \ #\ returns\ a\ list\ of\ 4\ elements:\n\ \ \ \ \ \ \ \ #\ -\ the\ argument\ list\ of\ apply\n\ \ \ \ \ \ \ \ #\ -\ the\ closure\ var\ list\n\ \ \ \ \ \ \ \ #\ -\ the\ closure\ vars\ initial\ values\ (to\ be\ updated\ by\ applyc)\n\ \ \ \ \ \ \ \ #\ -\ the\ body\n\ \ \ \ \ \ \ \ switch\ --\ \[llength\ \$args\]\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 1\ \{return\ \[list\ \$arglist\ \"\"\ \"\"\ \[lindex\ \$args\ 0\]\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2\ \{lassign\ \$args\ varlist\ body\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{error\ \"bad\ arguments\ to\ proc\ closure\"\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ if\ \{\[llength\ \$varlist\]==0\}\ \{return\ \[list\ \$arglist\ \"\"\ \"\"\ \$body\]\}\n\ \ \ \ \ \ \ \ foreach\ var\ \$varlist\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ data\ \[uplevel\ 1\ set\ \$var\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ body\ \"upvar\ 1\ closure_\$var\ \$var\\n\$body\"\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ list\ \$arglist\ \$varlist\ \$data\ \$body\n\}\n\nproc\ applyc\ \{name\ args\}\ \{\n\ \ \ \ \ \ \ \ upvar\ 1\ \$name\ _closure\n\ \ \ \ \ \ \ \ lassign\ \$_closure\ arglist\ varlist\ data\ body\n\ \ \ \ \ \ \ \ foreach\ var\ \$varlist\ val\ \$data\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ closure_\$var\ \$val\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ #\ call\ the\ lambda\n\ \ \ \ \ \ \ \ set\ res\ \[apply\ \[list\ \$arglist\ \$body\]\ \{*\}\$args\]\n\ \ \ \ \ \ \ \ #\ variable\ updates\ are\ saved\ in\ local\ vars\n\ \ \ \ \ \ \ \ foreach\ var\ \$varlist\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ retrieve\ them\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ values\ \[set\ closure_\$var\]\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ #\ save\ them\ as\ third\ element\ of\ _closure\n\ \ \ \ \ \ \ \ lset\ _closure\ 2\ \$values\n\ \ \ \ \ \ \ \ set\ res\n\}\n\n\nset\ x\ 1\nset\ accu\ \[closure\ \{num\}\ \{x\}\ \{incr\ x\ \$num\}\]\nputs\ \$accu\nputs\ \[applyc\ accu\ 2\]\nputs\ \[applyc\ accu\ 3\]\;#should\ increase\ value\nproc\ lam\ \{lam\}\ \{applyc\ lam\ 2\}\nputs\ \[lam\ \$accu\]\nputs\ \[lam\ \$accu\]\;#should\ print\ the\ same\n======\n\n\[NEM\]\ 2010-02-06:\ This\ is\ essentially\ how\ \[dictutils\]\ works,\ except\ that\ in\ that\ implementation\ the\ lambda\ expression\nand\ the\ variable\ environment\ (a\ \[dict\])\ are\ separate\ arguments\ to\ the\ apply\ command.\ Both\ have\ the\ nice\ property\ that\nupdates\ are\ only\ committed\ to\ the\ environment\ if\ no\ error\ is\ thrown\ in\ the\ body\ of\ the\ lambda.\ Both\ however\ need\ a\nlittle\ work\ to\ ensure\ that\ the\ lambda\ expression\ can\ be\ byte-compiled\ properly.\n\nThinking\ some\ more,\ a\ minimal\ closure\ construct\ that\ does\ the\ job\ and\ should\ be\ properly\ byte-compiled\ (but\ still\ not\nentirely\ optimised)\ is\ the\ following:\n======\nproc\ closure\ \{env\ params\ body\}\ \{\n\ \ \ \ set\ ns\ \[uplevel\ 1\ \{\ namespace\ current\ \}\]\n\ \ \ \ set\ body\ \[list\ with\ __scope__\ \$body\]\n\ \ \ \ set\ lambda\ \[list\ \$params\ \$body\ \$ns\]\n\ \ \ \ return\ \[list\ \$env\ \$lambda\]\n\}\nproc\ with\ \{scopeVar\ body\}\ \{\n\ \ \ \ uplevel\ 1\ \[list\ upvar\ 1\ \$scopeVar\ __scope__\]\n\ \ \ \ uplevel\ 1\ \[list\ dict\ with\ __scope__\ \$body\]\n\}\nproc\ applyc\ \{closureVar\ args\}\ \{\n\ \ \ \ upvar\ 1\ \$closureVar\ closure\n\ \ \ \ lassign\ \$closure\ __scope__\ lambda\n\ \ \ \ try\ \{\ apply\ \$lambda\ \{*\}\$args\ \}\ on\ ok\ result\ \{\ set\ closure\ \[list\ \$__scope__\ \$lambda\]\;\ return\ \$result\ \}\n\}\n#\ EXAMPLE\nset\ counter\ \[closure\ \{i\ 0\}\ \{\{n\ 1\}\}\ \{\ incr\ i\ \$n\ \}\]\napplyc\ counter\ \;#\ ->\ 1\napplyc\ counter\ \;#\ ->\ 2\napplyc\ counter\ 4\ \;#\ ->\ 6\ etc\n======\n----\n\[AMG\]:\ I'm\ pretty\ sure\ that\ \[sproc\]\ provides\ closures.\n\n----\nSee\ also\ \[Simple\ Closures\ and\ Objects\]\n\n<<categories>>\ Concept\ |\ Example\ |\ XOTcl\ Code regexp2} CALL {my render Closures These\ references\ are\ standard\ for\ the\ abstract\ notion\ of\ \"closure\":\n\[http://en.wikipedia.org/wiki/Closure_%28computer_science%29\]\ \[http://c2.com/cgi/wiki?LexicalClosure\]\ \[http://www.perl.com/doc/FAQs/FAQ/oldfaq-html/Q3.14.html\].\n\n\nFrom\ the\ \[Tcl\ chatroom\]:\n===none\n\[dkf\]\ \ \ Aliases\ are\ sort-of\ poor-mans\ closures.\ If\ we\ had\ real\ closures,\ we'd\ use\ them.\n\n\[suchenwi\]\ \ \ \ \ \ What\ prevents\ us\ from\ having\ them?\n\n\[dkf\]\ \ \ Lifespan\ issues\ mainly.\n\n\[am\]\ \ \ \ Why\ are\ aliases\ not\ closures\ -\ sorry,\ I\ think\ I\ have\ asked\ this\ before,\ but\ I\ do\ not\ fully\ grasp\ the\ concept\ of\ a\ closure\n\n\[dkf\]\ \ \ If\ we\ could\ be\ sure\ that\ the\ closure\ would\ go\ away\ as\ soon\ as\ it\ was\ no\ longer\ needed,\ they'd\ be\ trivial\ to\ add.\ A\ closure\ is\ really\ a\ piece\ of\ stack\ frame\ that\ is\ not\ on\ the\ stack.\ Or\ something\ like\ that.\n(The\ really\ strange\ things\ are\ \[continuation\]s,\ but\ we're\ not\ dealing\ with\ those\ now.)\nNow\ it\ would\ be\ pretty\ easy\ to\ create\ a\ new\ closure\ object\ and\ commands\ to\ manipulate\ that,\ but\ ensuring\ \nthat\ it\ doesn't\ go\ away\ at\ the\ wrong\ moment\ is\ not\ entirely\ trivial.\n\n\[suchenwi\]\ \ \ \ \ \ Could\ \[static\ variables\]\ be\ called\ atomar\ closures?\ I\ meant\ in\ the\ sense\ that\ they're\ local\ to\ a\ function,\ but\ persistent\ between\ calls.\n\n\[dkf\]\ \ \ \[C\]'s\ static\ variables?\ \ Sort\ of.\ \ Not\ that\ they're\ exactly\ that.\ Closures\ are\ really\ a\ bit\ antithetical\ to\ C\ anyway.\n\n''\[Lars\ H\],\ 2010-02-05:\ It\ seems\ Apple\ is\ bent\ on\ adding\ some\ kind\ of\ closures\ to\ C,\ though\ \[http://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars/10\].''\n\n\[dkf\]\ \ \ However,\ I\ could\ envision\ a\ closure/stack-frame\ object\ that\ you'd\ access\ through\ \[upvar\]\nA\ proper\ closure\ keeps\ track\ of\ all\ enclosing\ stack\ frames,\ but\ that's\ probably\ more\ than\ is\ needed\ for\ most\ purposes.\nThen\ you\ could\ also\ store\ the\ object\ as\ an\ argument\ to\ the\ proc\ using\ aliases...\nAnd\ that'd\ work.\nSo\ long\ as\ the\ closure\ doesn't\ get\ disposed\ of\ too\ early.\nWe\ really\ need\ to\ extend\ Tcl_ObjType\ when\ we\ come\ to\ \[Tcl9\].\n===\n----\n\[glennj\]\ It\ took\ me\ a\ while\ to\ figure\ out\ how\ aliases\ could\ work\ like\ closures\ in\ the\ above\ discussion.\ \ I\ think\ I\ came\ up\ with\ an\ example:\ a\ procedure\ returns\ the\ number\ of\ times\ it's\ been\ invoked:\n======\n\ \ #\ the\ first\ time,\ send\ \"0\"\ to\ the\ aliased\ proc\n\ \ interp\ alias\ \{\}\ countMe\ \{\}\ _countMe\ 0\n\n\ \ proc\ _countMe\ \{count\}\ \{\n\ \ \ \ \ \ #\ for\ the\ next\ invocation,\ reset\ the\ alias\n\ \ \ \ \ \ interp\ alias\ \{\}\ countMe\ \{\}\ _countMe\ \[incr\ count\]\n\ \ \ \ \ \ return\ \$count\n\ \ \}\n\n\ \ puts\ \[countMe\]\ \;#\ ==>\ 1\n\ \ puts\ \[countMe\]\ \;#\ ==>\ 2\n\ \ puts\ \[countMe\]\ \;#\ ==>\ 3\n======\n-------\n''Another\ attempt\ at\ \[Emulating\ Closures\ in\ Tcl\]''\n\n\[Todd\ Coram\]\ -\nWhile\ playing\ with\ \[PostgresSQL\],\ I\ got\ tired\ of\ passing\ around\ \nthe\ ''connection\ id''\ to\ each\ postgres\ tcl\ command\ (plus\ there\ was\ some\nother\ contextual\ info\ I\ wanted\ to\ keep\ around\ with\ each\ connection).\n\nObjectifying\ the\ postgres\ interface\ seemed\ over-kill\ and\ keeping\ state\ in\na\ single\ namespace\ prevented\ me\ from\ keeping\ more\ than\ one\ database\ connection\ open\ \nat\ a\ time.\ I\ could\ have\ used\ the\ classic\ objectifying\ technique\ of\ keeping\nthe\ instance\ info\ in\ array,\ but\ this\ felt\ clumsy.\ I\ could\ have\ curried\ the\ connection\ id\nto\ postgres\ commands,\ but\ that\ felt\ too\ restricting.\n\nClosures\ are\ neat\ because\ they\ give\ you\ a\ way\ to\ let\ functions\ carry\ a\ bit\nof\ state\ with\ it.\ Tcl\ Namespaces\ give\ you\ most\ of\ what\ you\ need,\ but\ you\nstart\ to\ bleed\ into\ ''object\ land''\ when\ you\ try\ to\ create\ more\ than\ one\nexclusive\ set\ of\ variables.\n\nSo,\ thus\ was\ born\ this\ late\ night\ hacked\ attempt\ at\ emulating\ closures\ in\ Tcl:\n\n======\n\ #\ Create\ a\ proc\ named\ 'name'\ that\ will\ create\ a\ closure\ over\ the\ supplied\n\ #\ 'variables'\ definition\ for\ the\ 'lambda_proc'.\ Any\ supplied\ variables\ in\n\ #\ 'arglist'\ can\ be\ used\ to\ initialize\ 'variables'\ during\ the\ closure\n\ #\ definition.\n\ #\n\ proc\ make-closure-proc\ \{name\ arglist\ variables\ lambda_proc\}\ \{\n\ \ \ \ set\ invoke_context\ \[uplevel\ namespace\ current\]\n\ \ \ \ set\ name_context\ \$\{invoke_context\}::\$name\n\n\ \ \ \ #\ Create\ a\ namespace\ called\ \$name_context\ to\ hold\ auto_cnt\n\ \ \ \ #\n\ \ \ \ namespace\ eval\ \$name_context\ \{\n\ \ \ \ \ \ \ if\ \{!\[info\ exists\ auto_cnt\]\}\ \{\ variable\ auto_cnt\ -1\}\n\ \ \ \ \}\n\n\ \ \ \ #\ Now,\ build\ a\ proc\ in\ invocation\ context\ that\ will\ create\n\ \ \ \ #\ closures.\ We\ do\ this\ by\ substituting\ all\ of\ the\ passed\n\ \ \ \ #\ parameters\ (name,\ arglist,\ variables,\ lambda_proc)\ and\ the\n\ \ \ \ #\ \$name_context.\n\ \ \ \ #\n\ \ \ \ #\ The\ resulting\ proc\ will:\n\ \ \ \ #\ 1.\ Accept\ \$arglist\ as\ initializers\ for\ the\ closures.\n\ \ \ \ #\ 2.\ Create\ a\ unique\ closure_name\ from\ the\ auto_cnt\ variable.\n\ \ \ \ #\ 3.\ Create\ a\ namespace\ for\ the\ closure.\n\ \ \ \ #\ 4.\ Evaluate\ the\ \$variables\ (optionally\ evaluating\ them\ with\n\ \ \ \ #\ \ \ \ \$arglist).\n\ \ \ \ #\ 5.\ Create\ an\ alias\ called\ 'dispatch'\ for\ the\ lambda_proc.\n\ \ \ \ #\ 6.\ Return\ the\ alias.\n\ \ \ \ #\n\ \ \ \ namespace\ eval\ \$invoke_context\ \\\n\ \ \ \ \ \ \ \[subst\ -nocommands\ -nobackslashes\ \{\n\ \ \ \ \ \ \ \ \ \ \ proc\ \$name\ \{\$arglist\}\ \{\ \n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ closure_name\ \\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \$\{name_context\}::\$name\[incr\ \$\{name_context\}::auto_cnt\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ eval\ \[subst\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ namespace\ eval\ \[set\ closure_name\]\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \$variables\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ namespace\ eval\ \[set\ closure_name\]\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Curry\ a\ dispatcher\ for\ the\ lambda_proc.\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ curry\ \[namespace\ current\]::dispatch\ \[\$lambda_proc\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\ \n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \[set\ closure_name\]::dispatch\}\n\ \ \ \ \ \ \ \ \ \ \ \ \}\]\n\ \}\n\n\ proc\ delete-closure\ \{name\}\ \{\n\ \ \ \ \ namespace\ delete\ \[namespace\ qualifiers\ \$name\]\n\ \}\n======\nI\ used\ a\ curry\ proc\ to\ create\ the\ dispatcher\ (I\ really\ don't\ create\ a\ curry\nand\ perhaps\ ''namespace\ code''\ could\ accomplish\ a\ similiar\ thing,\ but\ I\ had\ a\ curry\ proc\ handy,\ so\ there):\n======\n\ proc\ curry\ \{new\ args\}\ \{\n\ \ \ \ uplevel\ \[list\ interp\ alias\ \{\}\ \$new\ \{\}\]\ \$args\n\ \}\n======\nAnd\ a\ lambda\ proc\ to\ pass\ to\ the\ make-closure-proc:\n======\n\ proc\ lambda\ \{arglst\ body\}\ \{\n\ \ \ \ set\ level\ \[info\ level\ 0\]\n\ \ \ \ set\ name\ \[string\ map\ \{\\n\ _\ \\t\ _\ \\\"\ _\ \"\ \"\ _\ \\\;\ _\ \$\ _\ :\ _\ \\\{\ _\ \\\}\ _\ \\\[\ _\ \\\]\ _\}\ \$level\]\n\ \ \ \ set\ invoke_context\ \[uplevel\ namespace\ current\]\n\ \ \ \ proc\ \$\{invoke_context\}::\$name\ \$arglst\ \$body\n\ \ \ \ return\ \$\{invoke_context\}::\$name\n\ \}\n======\nHere\ is\ a\ (contrived)\ example\ of\ how\ to\ create\ and\ use\ the\ closures:\n======\n\ make-closure-proc\ make-logputs\ \{_level\ _filename\}\ \{\n\ \ \ \ variable\ fd\ \[open\ \$_filename\ w\]\n\ \ \ \ variable\ filename\ \$_filename\n\ \ \ \ variable\ level\ \$_level\n\ \}\ \{\n\ \ \ \ lambda\ \{cmd\ \{str\ \"\"\}\}\ \{\n\ \ \ \ \ \ \ \ variable\ fd\;\ variable\ filename\;\ variable\ level\n\ \ \ \ \ \ \ \ switch\ --\ \$cmd\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ puts\ \{\ \n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ puts\ \"Writing\ (\$level\ to\ \$filename)\ \$str\"\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ puts\ \$fd\ \"(\[clock\ format\ \[clock\ seconds\]\]\ -\ \$level)\ \$str\"\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ close\ \{\ \n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ close\ \$fd\ \n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \}\n\n\ set\ info\ \[make-logputs\ INFO\ info.out\]\n\ set\ warn\ \[make-logputs\ WARN\ warn.out\]\n\n\ \$info\ puts\ \"Some\ info:\ hello\ world\"\n\ \$info\ puts\ \"blech\"\n\ \$warn\ puts\ \"You\ have\ been\ warned!\"\n\n\ \$info\ close\n\ \$warn\ close\n\n\ delete-closure\ \$info\n\ delete-closure\ \$warn\n======\n----\n\[GN\]\ There\ is\ a\ strong\ relation\ between\ objects\ and\nclosures.\ a\ classical\ paper\ is\ from\ Uday\ Reddy\n\"Objects\ as\ closures:\ abstract\ semantics\ of\ object-oriented\ languages\",\nwho\ defines\ objects\ as\ an\ \"message\ environment\"\ (binding\ messages\nto\ methods)\ with\ an\ hidden\ local\ environment\ (binding\ instance\nvariables\ to\ values).\ \n\nThis\ is\ pretty\ close\ to\ the\ notion\ of\ objects\ in\ XOTcl\;\ \nthe\ example\ above\ can\ be\ written\ much\ simpler\ with\ \[XOTcl\]\ (certainly\nwith\ other\ \[oo\]\ languages\ as\ well):\n======\n\ package\ require\ XOTcl\;\ namespace\ import\ -force\ xotcl::*\n\n\ Class\ Logger\ -parameter\ \{level\ filename\}\n\ Logger\ instproc\ init\ \{\}\ \{\n\ \ \ my\ instvar\ fd\ filename\n\ \ \ set\ fd\ \[open\ \$filename\ w\]\n\ \}\n\ Logger\ instproc\ puts\ \{str\}\ \{\n\ \ \ my\ instvar\ level\ filename\ fd\n\ \ \ puts\ \"Writing\ (\$level\ to\ \$filename)\ \$str\"\n\ \ \ puts\ \$fd\ \"(\[clock\ format\ \[clock\ seconds\]\]\ -\ \$level)\ \$str\"\n\ \}\n\ Logger\ instproc\ close\ \{\}\ \{\n\ \ \ my\ instvar\ fd\n\ \ \ close\ \$fd\n\ \}\n\n\ set\ info\ \[Logger\ new\ -level\ INFO\ -filename\ info.out\]\n\ set\ warn\ \[Logger\ new\ -level\ WARN\ -filename\ warn.out\]\n\n\ \$info\ puts\ \"Some\ info:\ hello\ world\"\n\ \$info\ puts\ \"blech\"\n\ \$warn\ puts\ \"You\ have\ been\ warned!\"\n\n\ \$info\ close\n\ \$warn\ close\n\n\ \$info\ destroy\n\ \$warn\ destroy\n======\n----\n\[TV\]\ Isn't\ closure\ like\ in\ physics\ where\ you'd\ have\ a\ mathematical\ construct\ which\ is\ 'closed',\ which\ is\ usually\ pretty\ darn\ hard\ and\ often\ quite\ useless\ except\ probably\ in\ some\ essential\ fundamental\ cases.\n\n\[DKF\]:\ That's\ essentially\ unrelated.\ (And\ that's\ a\ maths/topology\ concept\ which\ physics\ has\ borrowed.)\n----\nSee\ \[custom\ curry\]\ and\ the\ references\ there\ for\ an\ explanation\ of\ ''curry''\ and\ ''currying\ function''.\n----\n\[RS\]\ asks:\ Could\ one\ say\ the\ following\ are\ (rudimentary)\ examples\ of\ closures?\n\n'''1.\ Default\ arguments'''\ (in\ danger\ to\ be\ overwritten\ by\ caller)\;\n======\n\ proc\ foo\ \{a\ b\ \{c\ 1\}\ \{d\ 2\}\ \{e\ 3\}\}\ \{...\}\n======\n\n'''2.\ Name-value\ map\ in\ an\ explicit\ argument'''\ \n======\n\ set\ closure\ \[list\ c\ 1\ d\ 2\ e\ 3\]\n\ ...\n\ proc\ bar\ \{a\ b\ closure\}\ \{\n\ \ \ \ \ foreach\ \{name\ value\}\ \$closure\ \{set\ \$name\ \$value\}\n\ \ \ \ \ ...\n\ \}\n======\n'''3.\ Closure\ values\ passed\ in\ over\ an\ alias:'''\n======\n\ proc\ _grill\ \{c\ d\ e\ a\ b\}\ \{...\}\n\ ...\n\ interp\ alias\ \{\}\ grill\ \{\}\ _grill\ 1\ 2\ 3\n======\n----\n\[Zarutian\]s\ first\ attempt\ at\ closures:\n======\n\ package\ require\ Tcl\ 8.4\n\ proc\ closure_var\ args\ \{\n\ \ \ set\ varname\ \[lindex\ \$args\ 0\]\n\ \ \ set\ value\ \ \ \[lindex\ \$args\ 1\]\n\ \ \ upvar\ \$varname\ breyta\n\ \ \ set\ breyta\ \$value\n\ \ \ trace\ remove\ variable\ breyta\ \{write\}\ update_closure_var\ \;\ #\ to\ prevent\ multiple\ trace\ clones\n\ \ \ trace\ add\ variable\ breyta\ \{write\}\ update_closure_var\n\ \}\n\ proc\ update_closure_var\ \{varname1\ varname2\ op\}\ \{\n\ \ \ if\ \{\$varname2\ !=\ \"\"\}\ \{\n\ \ \ \ \ set\ varname\ \"\[set\ varname1\](\[set\ varname2\])\"\n\ \ \ \}\ else\ \{\n\ \ \ \ \ set\ varname\ \$varname1\n\ \ \ \}\n\ \ \ upvar\ \$varname\ newvalue\n\ \ \ debug\ \[info\ level\ 1\]\ \$varname\ \$op\ \$newvalue\n\ \ \ #\ redefine\ the\ calling\ proc\ to\ reflect\ the\ variables\ new\ value\n\ \n\ \ \ set\ procsName\ \[lindex\ \[info\ level\ 1\]\ 0\]\n\ \ \ set\ procsArgs\ \[info\ args\ \$procsName\]\n\ \ \ set\ procsBody\ \[info\ body\ \$procsName\]\n\ \ \n\ \ \ debug\ \$procsName\ \$procsArgs\n\ \ \ debug\ \$procsBody\n\ \ \ \n\ \ \ set\ temp\ \"closure_var\ \$varname\"\n\ \ \ set\ insertLoc\ \[expr\ \[string\ last\ \$temp\ \$procsBody\]\ +\ \[string\ length\ \$temp\]\]\n\ \ \ set\ firstHalf\ \[string\ range\ \$procsBody\ 0\ \$insertLoc\]\n\ \ \ set\ lastHalf\ \ \[string\ range\ \$procsBody\ \$insertLoc\ end\]\n\ \ \ set\ procsBody\ \"\[set\ firstHalf\]\\\{\[set\ newvalue\]\\\}\[set\ lastHalf\]\"\n\ \ \ \n\ \ \ debug\ \$procsBody\n\ \ \ \n\ \ \ proc\ \$procsName\ \$procsArgs\ \$procsBody\n\ \}\n\ proc\ debug\ args\ \{\ puts\ \"\$args\"\ \}\n\ proc\ someFunction\ \{\}\ \{\n\ \ \ closure_var\ blu\ 21\n\ \ \ set\ blu\ 234\n\ \}\n======\nThe\ above\ implemention\ doesn't\ handle\ that\ when\ other\ sub-procs\ upvar\ a\ closure_var\ .\nThe\ next\ implemention\ of\ closures\ from\ Zarutian\ will\ have\ that\ fixed.\n\n\[Zarutian\]s\ second\ attempt\ at\ closures\n======\n\ package\ require\ Tcl\ 8.4\n\n\ proc\ closure_var\ args\ \{\n\ \ \ set\ varname\ \[lindex\ \$args\ 0\]\n\ \ \ set\ value\ \ \ \[lindex\ \$args\ 1\]\n\ \ \ upvar\ \$varname\ breyta\n\ \ \ set\ breyta\ \$value\n\ \ \ trace\ remove\ variable\ breyta\ \{write\}\ \[list\ update_closure_var\ \$varname\]\;\ #\ to\ prevent\ multiple\ trace\ clones\n\ \ \ trace\ add\ variable\ breyta\ \{write\}\ \[list\ update_closure_var\ \$varname\]\n\ \}\n\ proc\ update_closure_var\ \{originalVarname\ varname1\ varname2\ op\}\ \{\n\ \ \ if\ \{\$varname2\ !=\ \"\"\}\ \{\n\ \ \ \ \ set\ varname\ \"\[set\ varname1\](\[set\ varname2\])\"\n\ \ \ \}\ else\ \{\n\ \ \ \ \ set\ varname\ \$varname1\n\ \ \ \}\n\ \ \ upvar\ 1\ \$varname\ newvalue\n\ \ \ debug\ \[info\ level\ 1\]\ \$varname\ \$op\ \$newvalue\n\ \ \ #\ redefine\ the\ calling\ proc\ to\ reflect\ the\ variables\ new\ value\n\ \n\ \ \ set\ procsName\ \[lindex\ \[info\ level\ 1\]\ 0\]\n\ \ \ set\ procsArgs\ \[info\ args\ \$procsName\]\n\ \ \ set\ procsBody\ \[info\ body\ \$procsName\]\n\n\ \ \ debug\ \$procsName\ \$procsArgs\n\ \ \ debug\ \$procsBody\n\n\ \ \ set\ temp\ \"closure_var\ \$originalVarname\"\n\ \ \ debug\ \$temp\n\ \ \ set\ insertLoc\ \[expr\ \[string\ last\ \$temp\ \$procsBody\]\ +\ \[string\ length\ \$temp\]\]\n\n\ \ \ set\ firstHalf\ \[string\ range\ \$procsBody\ 0\ \$insertLoc\]\ \n\ \ \ set\ lastHalf\ \ \[string\ range\ \$procsBody\ \$insertLoc\ end\]\n\ \ \ set\ procsBody\ \"\[set\ firstHalf\]\\\{\[set\ newvalue\]\\\}\[set\ lastHalf\]\"\n\n\ \ \ debug\ \$procsBody\n\n\ \ \ proc\ \$procsName\ \$procsArgs\ \$procsBody\n\ \}\n\ proc\ debug\ args\ \{\ puts\ \"\$args\"\ \}\n\ proc\ someFunction\ \{\}\ \{\n\ \ \ closure_var\ blu\ 21\n\ \ \ decr\ blu\n\ \}\n\ proc\ decr\ \{varname\ \{delta\ 1\}\}\ \{\n\ \ \ upvar\ 1\ \$varname\ var\n\ \ \ set\ var\ \[expr\ \$var\ -\ \$delta\]\n\ \}\n======\nThis\ implemention\ should\ work\ fine\ with\ other\ sub-procs\ upvaring\ closure_vars.\nBut\ these\ two\ implementions\ have\ one\ catch/issue:\ namely\ that\ every\ previus\ value\ of\ a\ closure_var\ is\ saved\ too.\nI\ am\ trieing\ find\ out\ how\ it\ is\ possible\ to\ get\ the\ old\ value\ of\ a\ variable\ before\ it\ is\ updated\ to\ the\ new\nvalue\ so\ I\ can\ fix\ that\ catch/issue\n\nJust\ to\ be\ sure:\ isnt\ a\ closure\ just\ a\ procedure\ with\ some\ state\ saved\ with\ it,\ no?\n----\n\[SS\]\ 30\ Dec\ 2004:\ For\ the\ Tcl\ semantic,\ lexical\ binding\ is\ hard\ because\ it's\ not\ possible\ to\ tell\ from\ the\ source\ code\ what's\ a\ reference\nto\ a\ variable\ and\ what\ is\ not.\ Still\ it's\ possible\ to\ capture\ the\ context\ of\ a\ lambda's\ creation\ saving\ the\ current\ stack\ frame,\ thus\nallowing\ for\ real\ closures\ (procedures\ where\ if\ some\ variable\ can't\ be\ resolved\ in\ the\ local\ context,\ will\ try\ to\ access\ the\ stack\ frame\nthat\ was\ active\ at\ the\ procedure\ creation\ time).\ Because\ of\ the\ way\ Tcl\ works\ and\ the\ fact\ it's\ so\ dynamic\ I'm\ not\ sure\ closures\ may\nsignificantly\ help\ Tcl\ programming,\ '''but'''\ when\ they\ are\ used\ as\ objects.\ It's\ a\ more\ interesting\ addition\ to\ have\ an\ object\ system\ with\ngarbage\ collection.\ Because\ in\ most\ Tcl\ objects\ systems\ objects\ are\ \"callable\",\ like\ in\ \[\[\$o\ a\ b\ c\]\],\ objects\ can\ be\ used\ to\ do\ most\ of\ the\nthings\ you\ may\ like\ to\ do\ with\ closures,\ they\ are\ very\ similar\ to\ procedures\ but\ can\ take/alter\ their\ internal\ state.\nOf\ course\ this\ is\ possible\ to\ do\ even\ with\ OOP\ systems\ not\ having\ garbage\ collection,\ but\ the\ programming\ style\ that\ closures\ make\npossible\ is\ often\ about\ to\ capture\ some\ information\ to\ semplify/specialize\ the\ next\ uses\ of\ a\ given\ procedure,\ it's\ hard\ to\ think\ at\ this\nprogramming\ style\ as\ comfortable\ if\ you\ have\ to\ clean\ by\ hand\ the\ objects.\n----\n\[Zarutian\]\ wrote\ on\ 2.\ jan\ 2005:\nappend\ this\ to\ my\ second\ attempt\ at\ closures:\n\ ======\n\ proc\ closure\ \{name\ args\ body\}\ \{\n\ \ \ set\ locals\ \[uplevel\ 1\ \[list\ info\ locals\]\]\n\ \ \ foreach\ loco\ \$locals\ \{\n\ \ \ \ \ set\ body\ \"\[list\ closure_var\ \$loco\ \[uplevel\ 1\ \[list\ set\ \$loco\]\]\]\\n\[set\ body\]\"\n\ \ \ \}\n\ \ \ proc\ \$name\ \$args\ \$body\n\ \}\n======\nand\ I\ think\ you\ have\ got\ something\ like\ that\ \[SS\]\ described\ above.\n----\n\[SS\]\ 3\ Jan\ 2004:\ Yeah\ this\ is\ a\ smart\ idea,\ to\ capture\ the\ context.\ Still\ there\ are\ a\ few\ things\ to\ fix,\ and\ many\ other\ things\nthat\ we\ can't\ fix\ at\ all.\ What\ should\ be\ fixed\ is\ that\ this\ way\ you\ set\ the\ locals\ variables\ even\ if\ the\ name\ is\ the\ same\ as\ one\nof\ the\ procedure\ arguments,\ that's\ not\ correct:\ if\ there\ is\ an\ argument\ with\ that\ name,\ the\ symbol\ should\ be\ bound\ to\ it.\nSecond,\ in\ real\ closures,\ many\ closures\ can\ *share*\ the\ environment,\ and\ can\ modify\ it\ (and\ every\ other\ closure\ bound\ to\ the\ same\nexternal\ variables\ will\ see\ the\ change).\ We\ can't\ get\ that\ far\ with\ Tcl\ of\ course,\ but\ still\ your\ exercise\ is\ very\ interesting\nand\ valuable\ IMHO.\n\n\[DKF\]:\ I\ use\ something\ very\ much\ like\ closures\ in\ my\ \[oo2\]\ code.\ \ Basically,\ \[dict\]'s\ '''update'''\ and\ '''with'''\ subcommands\ (together\ with\ some\ wrapping\ scripts)\ allow\ for\ closure-like\ behaviour\ very\ easily.\ The\ complexity\ is\ that\ the\ closure\ is\ actually\ stored\ in\ a\ \"global\"\ variable,\ but\ as\ long\ as\ you\ ignore\ the\ man\ behind\ the\ curtain,\ you're\ OK...\ \;^)\n\n\[Zarutian\]\ 4.\ jan\ 2005:\ \[SS\]\ are\ you\ speaking\ from\ the\ past?\ \;-)\ Because\ I\ hope\ you\ meant\ 3\ Jan\ '''2005'''.\n\nAnyway,\ I\ should\ get\ to\ the\ point.\ As\ I\ understand\ it\ Tcl\ procedure's\ enviroment\ is\ three\ leveled:\ global,\ local\ to\ procedure's\ namespace,\ local\ to\ procedure's\ level/callstack.\n\nThen\ when\ variable\ lookup\ is\ performed\ (either\ because\ of\ Tcl's\ seventh\ substitution\ rule\ or\ procedure\ set\ is\ invoked)\ inside\ a\ procedure's\ body\ (the\ procedure\ was\ called)\ the\ interpreter\ first\ looks\ for\ the\ variable\ in\ local\ callstack\ scope\ then\ in\ procedure's\ namespace\ (if\ that\ variable\ name\ was\ marked\ by\ calling\ the\ procedure\ 'variable')\ and\ at\ last\ in\ the\ global\ namespace\ (likewise\ if\ the\ variable\ name\ was\ marked\ by\ calling\ the\ procedure\ 'global').\n\nWhere\ other\ scripting\ languages\ like\ \[Lua\]\ and\ \[Lisp\]\ variants\ use\ linked\ tables/hashmaps/dictionaries\ and\ lookup\ the\ variable's\ value\ in\ the\ parent\ table\ of\ the\ current\ variable|value\ binding\ table\ if\ not\ found\ in\ current\ until\ the\ top\ most\ variable|value\ binding\ table\ is\ reached.\ (Hmm...\ the\ preceeding\ sentence\ may\ be\ unclear\ because\ of\ my\ lack\ of\ skill\ writing\ English)\ \n\nHere\ above\ I\ have\ descriped\ two\ possible\ ways\ to\ look\ up\ values\ for\ variables.\nSo\ I\ ask\ what\ are\ the\ 'pros'\ and\ 'cons'\ of\ each?\n\nIn\ my\ opinion\ I\ think\ the\ latter\ method\ enables\ more\ flexibility\ of\ variable\ lookup\ for\ value.\n\{IS:\ Að\ mínu\ áliti\ held\ ég\ að\ síðari\ aðferðin\ gefi\ kost\ á\ meiri\ liðleika\ til\ að\ fletta\ upp\ gildi\ breytu.\}\n\n----\n\[SS\]\ 23Feb2005:\n\nThis\ is\ a\ proposal\ for\ closures\ I\ made\ in\ comp.lang.tcl:\n\nFrom\ time\ to\ time\ there\ is\ this\ discussion\ about\ adding\ closures\ to\nTcl,\ but\ usually\ the\ idea\ is\ to\ make\ they\ similar\ to\ languages\ like\n\[Scheme\],\ i.e.\ closures\ with\ lexical\ scoping.\ My\ opinion\ is\ that\ this\ is\nvery\ hard\ to\ do\ with\ Tcl,\ and\ even\ not\ in\ the\ spirit\ of\ the\ language.\nIn\ a\ Tcl\ program,\ what\ part\ of\ a\ procedure\ body\ is\ a\ variable\ is\ not\ndefined\ until\ execution,\ for\ example:\n======\n\ set\ a\ 10\n\ closure\ \{x\}\ \{\n\ \ \ \ incr\ a\n\ \}\n======\nThen\ I\ define\ 'incr'\ to\ be\ like\ 'puts',\ and\ 'a'\ is\ no\ longer\ a\ variable.\nIt\ was\ already\ suggested\ that\ in\ Tcl\ closures\ should\ not\ have\ any\ kind\ of\ creation-time\ resolution\ rule,\ but\ that\ the\ context\ where\ they\ are\ndefined\ should\ be\ captured\ as\ a\ whole,\ and\ used\ when\ the\ closure\ is\ running\ to\ resolve\ \"unbound\ symbols\"\ (that\ are\ better\ referred\ as\ variables\ and\ procedures\ not\ otherwise\ defined\ during\ execution\ in\nTcl\ slang).\ Still\ there\ is\ the\ problem\ that\ to\ similuate\ the\ lexical\ scoping\ you\ have\ to\ take\ *references*\ to\ the\ shared\ environment,\ so\ that:\n======\n\ set\ a\ 10\n\ set\ foo\ \[closure\ \{x\}\ \{\n\ \ \ \ incr\ a\ \$x\n\ \}\]\n\ set\ bar\ \[closure\ \{x\}\ \{\n\ \ \ \ incr\ a\ \$x\n\ \}\]\n\ \$foo\ 1\;#\ ->\ 11\n\ \$bar\ 1\;#\ ->\ 12\n======\nfoo\ and\ bar\ will\ share\ the\ same\ 'a'.\n\ \nI\ think\ this\ is\ a\ all\ to\ complex\ and\ UnTclish,\ so\ I\ tried\ to\ design\ a\ new\ semantic\ for\ closures.\n\ \nThe\ semantic\ is\ based\ on\ a\ single\ command\ \[closure\],\ that\ can\ set/get\nclosure\ variables\ in\ the\ scope\ of\ the\ current\ procedure,\ together\ with\na\ minimal\ change\ in\ the\ \[proc\]\ and\ \[lambda\]\ command\ (I\ know\ we\ don't\ have\ lambda...\ but\ still\ there\ is\ a\ way\ Tcl\ users\ already\ think\ about\nit\ and\ should\ change).\n\ \nBasically,\ to\ set\ a\ closure\ variable,\ there\ is\ to\ write\ the\ following\ command:\n======\n\ closure\ set\ x\ 10\n======\nthis\ will\ set\ 'x'\ inside\ the\ closure\ of\ the\ current\ procedure.\ This\ 'x'\nwill\ be\ persistent\ accross\ different\ calls\ of\ this\ procedure,\ and\ all\nthis\ environment\ will\ be\ destroied\ once\ the\ procedure\ itself\ is\ destroied.\ The\ procedure\ can\ test\ for\ the\ existence\ of\ a\ closure\ variable\ with\ \[\[closure\ exists\ x\]\],\ can\ get\ the\ value\ with\ \[\[closure\ get\ x\]\]\nand\ so\ on.\n\ \nThe\ change\ required\ to\ the\ \[proc\]\ command,\ is\ that\ it\ can\ take\ an\ optional\ further\ argument,\ that's\ a\ Tcl\ list\ of\ key/value\ pairs\ used\nto\ inizialize\ the\ closure\ at\ procedure\ creation\ time.\n\ \nso:\n======\n\ proc\ foo\ \{\}\ \{\ ....\ \}\ \{x\ 10\ y\ 20\}\n======\nwill\ create\ the\ procedure\ foo\ with\ x=10\ and\ y=20\ inside\ the\ closure.\nThe\ same\ for\ \[lambda\].\n\ \nThe\ following\ is\ an\ example\ of\ procedure\ that\ returns\ a\ progressive\ integer\ number\ every\ time\ it's\ called:\n======\n\ proc\ counter\ \{\}\ \{\n\ \ \ \ if\ \{!\[closure\ exists\ x\]\}\ \{\n\ \ \ \ \ \ \ \ \ set\ x\ 0\n\ \ \ \ \}\n\ \ \ \ set\ x\ \[closure\ get\ x\]\n\ \ \ \ closure\ set\ x\ \[expr\ \$x+1\]\n\ \ \ \ return\ \$x\n\ \}\n======\nOf\ course\ it's\ better\ to\ use\ the\ optional\ argument\ of\ proc\ and\ write\ it\ as:\n======\n\ proc\ counter\ \{\}\ \{\n\ \ \ \ set\ x\ \[closure\ get\ x\]\n\ \ \ \ closure\ set\ x\ \[expr\ \$x+1\]\n\ \ \ \ return\ \$x\n\ \}\ \{x\ 0\}\n======\nOf\ course\ for\ this\ to\ be\ very\ useful,\ lambda\ it's\ needed.\nThis\ version\ of\ lambda,\ like\ proc,\ should\ accept\ the\ optional\nargument\ to\ initialize\ the\ closure.\ This\ is\ an\ example:\n======\n\ proc\ createAdder\ \{x\}\ \{\n\ \ \ \ lamba\ \{y\}\ \{expr\ \$y+\[closure\ get\ \$x\]\}\ \[list\ x\ \$x\]\n\ \}\n\ \n\ set\ f\ \[createAdder\ 5\]\n\ \$f\ 10\ \;#\ ->\ 15\n======\nI\ think\ that\ this\ design\ can\ do\ everything\ lexical\ scoping\ is\ able\ to\ndo,\ but\ with\ a\ command-based\ interface\ that\ plays\ better\ with\ Tcl.\n\ \nThis\ kind\ of\ closures\ will\ be\ added\ into\ the\ Jim\ interpreter,\ a\nsmall\ footprint\ Tcl\ interpreter\ I'm\ writing.\ This\ interpreter\ is\ already\nworking\ and\ I'll\ be\ happy\ to\ send\ a\ preview\ tar.gz\ to\ interested\npeople\ (the\ license\ is\ the\ APACHE2,\ so\ it's\ possible\ to\ use\ Jim\ in\ncommercial\ projects\ if\ needed).\n\nRegards,<<br>>Salvatore\ \n\nand\ then\ I\ replyed\ to\ myself\ with\ this\ message:\n\nI\ forgot\ to\ include\ a\ couple\ of\ points.\n\ \nThe\ closure\ command\ can\ also\ access\ closures\ of\ external\ procedures:\n\ \n\ \[closure\ in\ \$procName\ get/set\ x\ ...\]\ and\ so\ on.\nThis\ makes\ possible\ to\ share\ the\ environment\ if\ really\ needed.\nExample:\n======\n\ proc\ createAdder\ \{x\}\ \{\n\ \ \ \ set\ a\ \[lamba\ \{y\}\ \{expr\ \$y+\[closure\ get\ \$x\]\}\ \[list\ x\ \$x\]\]\n\ \ \ \ set\ b\ \[lamba\ \{incr\}\ \{closure\ in\ \$a\ set\ x\ \$incr\}\ \[list\ a\ \$a\]\]\n\ \ \ \ list\ \$a\ \$b\n\ \}\n======\nthis\ returns\ one\ closure\ to\ add\ and\ one\ to\ change\ the\ increment\nperformed\ by\ the\ first\ closure.\n\ \nAlso\ it\ is\ worth\ to\ note\ that\ this\ way\ to\ do\ closures\ don't\ play\nwell\ with\ functions\ as\ values\ nor\ with\ lambas\ based\ on\ auto\ expansion,\nbecause\ full\ closures\ need\ to\ be\ able\ to\ modify\ their\ environment\nso\ they\ can\ not\ be\ immutable\ values.\n\nCiao,<<br>>Salvatore\ \n\n----\n\[NEM\]\ offers\ the\ following\ as\ a\ simple\ closure-like\ thing:\n======\n\ proc\ closure\ \{name\ arglist\ body\}\ \{\n\ \ \ \ if\ \{!\[string\ match\ ::*\ \$name\]\}\ \{\n\ \ \ \ \ \ \ \ #\ Not\ fully\ qualified\n\ \ \ \ \ \ \ \ set\ ns\ \[uplevel\ 1\ namespace\ current\]\n\ \ \ \ \ \ \ \ set\ name\ \$\{ns\}::\$name\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ set\ name\ \$name\n\ \ \ \ \}\n\ \ \ \ set\ sname\ \[namespace\ tail\ \$name\]\n\ \ \ \ #\ Just\ create\ a\ proc\ as\ usual,\ but\ a\ namespace\ along\ with\ it\n\ \ \ \ namespace\ eval\ \$name\ \[list\ proc\ \$sname\ \$arglist\ \$body\]\n\ \ \ \ interp\ alias\ \{\}\ \$name\ \{\}\ \$\{name\}::\$sname\n\ \}\n======\nand\ a\ test:\n======\n\ closure\ make-counter\ \{start\}\ \{\n\ \ \ \ \ variable\ id\n\ \ \ \ \ if\ \{!\[info\ exists\ id\]\}\ \{\ set\ id\ 0\ \}\n\ \ \ \ \ incr\ id\n\ \ \ \ \ closure\ counter-\$id\ \{\{amount\ 1\}\}\ \[string\ map\ \[list\ %S\ \$start\]\ \{\n\ \ \ \ \ \ \ \ \ variable\ counter\n\ \ \ \ \ \ \ \ \ if\ \{!\[info\ exists\ counter\]\}\ \{\ set\ counter\ %S\ \}\n\ \ \ \ \ \ \ \ \ incr\ counter\ \$amount\n\ \ \ \ \ \}\]\n\ \ \ \ \ return\ \[namespace\ current\]::counter-\$id\n\ \}\n======\nCould\ do\ with\ a\ bit\ of\ tarting\ up,\ and\ it's\ not\ as\ powerful\ as\ closures\ in\ Scheme,\ which\ get\ a\ lot\ of\ their\ power\ from\ lexical\ scoping.\ Still,\ it\ goes\ quite\ a\ long\ way,\ I\ think.\ Oh,\ and\ you\ can\ do\ drop-dead\ simple\ \[ensemble\]s\ too:\n======\n\ (tile)\ 57\ %\ closure\ MyEnsemble\ \{method\ args\}\ \{\n\ \n\ \ \ closure\ say\ \{message\}\ \{\ puts\ \"Say:\ \$message\"\ \}\n\ \ \ closure\ sing\ \{message\}\ \{\ puts\ \"Sing:\ \$message!\"\ \}\n\ \n\ \ \ \$method\ \{expand\}\$args\n\ \}\n\ ::::MyEnsemble\n\ (tile)\ 58\ %\ MyEnsemble\n\ wrong\ #\ args:\ should\ be\ \"::::MyEnsemble::MyEnsemble\ method\ ...\"\n\ (tile)\ 59\ %\ MyEnsemble\ say\ Hello\n\ Say:\ Hello\n\ (tile)\ 60\ %\ MyEnsemble\ sing\ \"Tra-la-la\"\n\ Sing:\ Tra-la-la!\n======\n----\n\[Sarnold\]\ 2010-Feb-5:\ Here\ is\ my\ own\ implementation\ of\ simple\ closures.\ To\ use\ them\ you\ will\ have\ to\ store\ them\ in\ a\ variable\ and\ pass\ its\ name\ to\ a\ custom\ applyc\ (apply-closure)\ proc,\ which\ saves\ the\ environment\ in\ the\ variable\ holding\ the\ closure.\ The\ closure\ proc\ creates\ a\ closure\ (a\ list)\ by\ passing\ to\ it\ a\ variable\ list\ for\ the\ environment.\ (this\ is\ AFAIK\ the\ way\ you\ create\ closures\ in\ PHP)\n\n======\npackage\ require\ Tcl\ 8.5\n\nproc\ closure\ \{arglist\ args\}\ \{\n\ \ \ \ \ \ \ \ #\ returns\ a\ list\ of\ 4\ elements:\n\ \ \ \ \ \ \ \ #\ -\ the\ argument\ list\ of\ apply\n\ \ \ \ \ \ \ \ #\ -\ the\ closure\ var\ list\n\ \ \ \ \ \ \ \ #\ -\ the\ closure\ vars\ initial\ values\ (to\ be\ updated\ by\ applyc)\n\ \ \ \ \ \ \ \ #\ -\ the\ body\n\ \ \ \ \ \ \ \ switch\ --\ \[llength\ \$args\]\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 1\ \{return\ \[list\ \$arglist\ \"\"\ \"\"\ \[lindex\ \$args\ 0\]\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2\ \{lassign\ \$args\ varlist\ body\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ default\ \{error\ \"bad\ arguments\ to\ proc\ closure\"\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ if\ \{\[llength\ \$varlist\]==0\}\ \{return\ \[list\ \$arglist\ \"\"\ \"\"\ \$body\]\}\n\ \ \ \ \ \ \ \ foreach\ var\ \$varlist\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ data\ \[uplevel\ 1\ set\ \$var\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ body\ \"upvar\ 1\ closure_\$var\ \$var\\n\$body\"\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ list\ \$arglist\ \$varlist\ \$data\ \$body\n\}\n\nproc\ applyc\ \{name\ args\}\ \{\n\ \ \ \ \ \ \ \ upvar\ 1\ \$name\ _closure\n\ \ \ \ \ \ \ \ lassign\ \$_closure\ arglist\ varlist\ data\ body\n\ \ \ \ \ \ \ \ foreach\ var\ \$varlist\ val\ \$data\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ closure_\$var\ \$val\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ #\ call\ the\ lambda\n\ \ \ \ \ \ \ \ set\ res\ \[apply\ \[list\ \$arglist\ \$body\]\ \{*\}\$args\]\n\ \ \ \ \ \ \ \ #\ variable\ updates\ are\ saved\ in\ local\ vars\n\ \ \ \ \ \ \ \ foreach\ var\ \$varlist\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ retrieve\ them\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ lappend\ values\ \[set\ closure_\$var\]\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ #\ save\ them\ as\ third\ element\ of\ _closure\n\ \ \ \ \ \ \ \ lset\ _closure\ 2\ \$values\n\ \ \ \ \ \ \ \ set\ res\n\}\n\n\nset\ x\ 1\nset\ accu\ \[closure\ \{num\}\ \{x\}\ \{incr\ x\ \$num\}\]\nputs\ \$accu\nputs\ \[applyc\ accu\ 2\]\nputs\ \[applyc\ accu\ 3\]\;#should\ increase\ value\nproc\ lam\ \{lam\}\ \{applyc\ lam\ 2\}\nputs\ \[lam\ \$accu\]\nputs\ \[lam\ \$accu\]\;#should\ print\ the\ same\n======\n\n\[NEM\]\ 2010-02-06:\ This\ is\ essentially\ how\ \[dictutils\]\ works,\ except\ that\ in\ that\ implementation\ the\ lambda\ expression\nand\ the\ variable\ environment\ (a\ \[dict\])\ are\ separate\ arguments\ to\ the\ apply\ command.\ Both\ have\ the\ nice\ property\ that\nupdates\ are\ only\ committed\ to\ the\ environment\ if\ no\ error\ is\ thrown\ in\ the\ body\ of\ the\ lambda.\ Both\ however\ need\ a\nlittle\ work\ to\ ensure\ that\ the\ lambda\ expression\ can\ be\ byte-compiled\ properly.\n\nThinking\ some\ more,\ a\ minimal\ closure\ construct\ that\ does\ the\ job\ and\ should\ be\ properly\ byte-compiled\ (but\ still\ not\nentirely\ optimised)\ is\ the\ following:\n======\nproc\ closure\ \{env\ params\ body\}\ \{\n\ \ \ \ set\ ns\ \[uplevel\ 1\ \{\ namespace\ current\ \}\]\n\ \ \ \ set\ body\ \[list\ with\ __scope__\ \$body\]\n\ \ \ \ set\ lambda\ \[list\ \$params\ \$body\ \$ns\]\n\ \ \ \ return\ \[list\ \$env\ \$lambda\]\n\}\nproc\ with\ \{scopeVar\ body\}\ \{\n\ \ \ \ uplevel\ 1\ \[list\ upvar\ 1\ \$scopeVar\ __scope__\]\n\ \ \ \ uplevel\ 1\ \[list\ dict\ with\ __scope__\ \$body\]\n\}\nproc\ applyc\ \{closureVar\ args\}\ \{\n\ \ \ \ upvar\ 1\ \$closureVar\ closure\n\ \ \ \ lassign\ \$closure\ __scope__\ lambda\n\ \ \ \ try\ \{\ apply\ \$lambda\ \{*\}\$args\ \}\ on\ ok\ result\ \{\ set\ closure\ \[list\ \$__scope__\ \$lambda\]\;\ return\ \$result\ \}\n\}\n#\ EXAMPLE\nset\ counter\ \[closure\ \{i\ 0\}\ \{\{n\ 1\}\}\ \{\ incr\ i\ \$n\ \}\]\napplyc\ counter\ \;#\ ->\ 1\napplyc\ counter\ \;#\ ->\ 2\napplyc\ counter\ 4\ \;#\ ->\ 6\ etc\n======\n----\n\[AMG\]:\ I'm\ pretty\ sure\ that\ \[sproc\]\ provides\ closures.\n\n----\nSee\ also\ \[Simple\ Closures\ and\ Objects\]\n\n<<categories>>\ Concept\ |\ Example\ |\ XOTcl\ Code} CALL {my revision Closures} CALL {::oo::Obj3671538 process revision/Closures} CALL {::oo::Obj3671536 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