Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/lassign?V=64
QUERY_STRINGV=64
CONTENT_TYPE
DOCUMENT_URI/revision/lassign
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR108.162.216.102
REMOTE_PORT27770
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR3.146.221.52
HTTP_CF_RAY876f444868f6e263-ORD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTMozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
HTTP_CF_CONNECTING_IP3.146.221.52
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 lassign '''\[http://www.tcl.tk/man/tcl/TclCmd/lassign.htm%|%lassign\]''',\ a\ \[Tcl\ Commands%|%built-in\]\ \[Tcl\]\ \[command\],\ '''unpacks'''\ a\ \[list\]\ into\ \[variable\]s.\n\n`lassign`\ became\ a\ built-in\ command\ in\ Tcl\ \[Changes\ in\ Tcl/Tk\ 8.5%|%8.5\].\n\n**\ Synopsis\ **\n\n\n\n\ \ \ \ :\ \ \ '''lassign'''\ ''list''\ ''varName''\ ?''varName''\ ...?\n\n**\ Documentation\ **\n\n\n\n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/lassign.htm%|%official\ reference\]:\ \ \ \n\n\ \ \ \[TIP\]\ \[http://purl.org/tcl/tip/57.html%|%57\]:\ \ \ proposed\ making\ the\ \[TclX\]\ `lassign`\ command\ a\ built-in\ Tcl\ command\ \n\n**\ Description\ **\n\n\n\n`lassign`\ assigns\ values\ from\ a\ \[list\]\ to\ the\ specified\ variables,\ and\n\[return\]s\ the\ remaining\ values.\ \ For\ example:\n\n======\nset\ end\ \[lassign\ \{1\ 2\ 3\ 4\ 5\}\ a\ b\ c\]\n======\n\nwill\ set\ `\$a`\ to\ `1`,\ `\$b`\ to\ `2`,\ `\$c`\ to\ `3`,\ and\ `\$end`\ to\ `4\ 5`.\n\nIn\ \[lisp\]\ parlance:\n\n======\nset\ cdr\ \[lassign\ \$mylist\ car\]\n======\n\nIf\ there\ are\ more\ ''varNames''\ than\ there\ are\ items\ in\ the\ list,\ the\ extra\nif\ there\ are\ more\ ''varNames''\ than\ there\ are\ items\ in\ the\ list,\ the\ extra\n\n======none\n%\ lassign\ \{1\ 2\}\ a\ b\ c\n%\ puts\ \$a\n1\n%\ puts\ \$b\n2\n%\ puts\ \$c\n\n%\n======\n\nIn\ Tcl\ prior\ to\ 8.5,\ `\[foreach\]`\ was\ used\ to\ achieve\ the\ functionality\ of\n`\[lassign\]`:\n\n======\nforeach\ \{var1\ var2\ var3\}\ \$list\ break\n======\nThis\ was\ unwise,\ as\ it\ would\ cause\ a\ second\ iteration\ (or\ more)\ to\ be\ done\ when\ `\$list`\ contains\ more\ than\ 3\ items\ (in\ this\ case).\ Putting\ the\ \[break\]\ in\ makes\ the\ behaviour\ predictable.\n\n\n**\ Example:\ \[Perl\]-ish\ `shift`\ **\n\n\[DKF\]\ cleverly\ points\ out\ that\ `lassign`\ makes\ a\ \[Perl\]-ish\ `shift`\ this\ easy:\n\n======\nproc\ shift\ \{\}\ \{\n\ \ \ \ global\ argv\n\ \ \ \ set\ argv\ \[lassign\ \$argv\ v\]\n\ \ \ \ return\ \$v\n\}\n======\n\nOn\ the\ other\ hand,\ \[Hemang\ Lavana\]\ observes\ that\ TclXers\ already\ have\n`\[lvarpop\]\ ::argv`,\ an\ exact\ synonym\ for\ `shift`.\n\nOn\ the\ third\ hand,\ \[RS\]\ would\ use\ our\ old\ friend\ \[K\]\ to\ code\ like\ this:\n\n======\nproc\ shift\ \{\}\ \{\n\ \ \ \ K\ \[lindex\ \$::argv\ 0\]\ \[set\ ::argv\ \[lrange\ \$::argv\[set\ ::argv\ \{\}\]\ 1\ end\]\]\n\}\n======\n\n\[Lars\ H\]:\ Then\ I\ can't\ resist\ doing\ the\ above\ without\ the\ K:\n\n======\nproc\ shift\ \{\}\ \{\n\ \ \ \ lindex\ \$::argv\ \[set\ ::argv\ \[lrange\ \$::argv\[set\ ::argv\ \{\}\]\ 1\ end\]\;\ expr\ 0\]\n\}\n======\n\n\n\n**\ Default\ Value\ **\n\n\[FM\]:\ here's\ a\ quick\ way\ to\ assign\ with\ default\ value,\ using\ `\[apply\]`:\n\n======\nproc\ args\ \{spec\ list\}\ \{\n\ \ \ \ apply\ \[list\ \$spec\ \[list\ foreach\ \{e\}\ \$spec\ \{\n\ \ \ \ \ \ \ \ uplevel\ 2\ \[list\ set\ \[lindex\ \$e\ 0\]\ \[set\ \[lindex\ \$e\ 0\]\]\]\n\ \ \ \ \}\]\]\ \{*\}\$list\n\}\nset\ L\ \{\}\nargs\ \{\{a\ 0\}\ \{b\ 0\}\ \{c\ 0\}\ args\}\ \$L\n======\n\n\[AMG\]:\ Clever.\ \ Here's\ my\ version,\ which\ actually\ uses\ `\[lassign\]`,\ plus\ it\nmatches\ `\[lassign\]`'s\ value-variable\ ordering.\ \ It\ uses\ `\[lcomp\]`\ for\ brevity.\n\n======\nproc\ args\ \{vals\ args\}\ \{\n\ \ \ \ set\ vars\ \[lcomp\ \{\$name\}\ for\ \{name\ default\}\ inside\ \$args\]\n\ \ \ \ set\ allvals\ \"\\\[list\ \[join\ \[lcomp\ \{\"\\\[set\ \[list\ \$e\]\\\]\"\}\ for\ e\ in\ \$vars\]\]\\\]\"\n\ \ \ \ apply\ \[list\ \$args\ \"uplevel\ 2\ \\\[list\ lassign\ \$allvals\ \$vars\\\]\"\]\ \{*\}\$vals\n\}\n======\n\nWithout\ `\[lcomp\]`:\n\n======\nproc\ args\ \{vals\ args\}\ \{\n\ \ \ \ lassign\ \"\"\ scr\ vars\n\ \ \ \ foreach\ varspec\ \$args\ \{\n\ \ \ \ \ \ \ \ append\ scr\ \"\ \\\[set\ \[list\ \[lindex\ \$varspec\ 0\]\]\\\]\"\n\ \ \ \ \ \ \ \ lappend\ vars\ \[lindex\ \$varspec\ 0\]\n\ \ \ \ \}\n\ \ \ \ apply\ \[list\ \$args\ \"uplevel\ 2\ \\\[list\ lassign\ \\\[list\$scr\\\]\ \$vars\\\]\"\]\ \{*\}\$vals\n\}\n======\n\nThis\ code\ reminds\ me\ of\ the\ movie\ \"Inception\"\ \[http://en.wikipedia.org/wiki/Inception_%28film%29\].\ \ It\ exists,\ creates\ itself,\ and\ operates\ at\ and\ across\ multiple\ levels\ of\ interpretation.\ \ There's\ the\ caller,\ there's\ \[\[args\]\],\ there's\ \[\[\[apply\]\]\],\ then\ there's\ the\ \[\[\[uplevel\]\ 2\]\]\ that\ goes\ back\ to\ the\ caller.\ \ The\ caller\ is\ the\ waking\ world,\ \[\[args\]\]\ is\ the\ dream,\ \[\[apply\]\]\ is\ its\ dream-within-a-dream,\ and\ \[\[uplevel\]\]\ is\ ''its''\ dream-within-a-dream\ that\ is\ used\ to\ implant\ an\ idea\ (or\ variable)\ into\ the\ waking\ world\ (the\ caller).\ \ And\ of\ course,\ the\ caller\ could\ itself\ be\ a\ child\ stack\ frame,\ so\ maybe\ reality\ is\ just\ another\ dream!\ \;^)\n\nOr\ maybe\ this\ code\ is\ a\ Matryoshka\ nesting\ doll\ \[http://en.wikipedia.org/wiki/Matryoshka\]\ whose\ innermost\ doll\ contains\ the\ outside\ doll.\ \;^)\n\nOkay,\ now\ that\ I've\ put\ a\ cross-cap\ in\ reality\ \[http://en.wikipedia.org/wiki/Cross_cap\],\ let\ me\ demonstrate\ how\ \[\[args\]\]\ is\ used:\n\n======\nargs\ \{1\ 2\ 3\}\ a\ b\ c\ \ \ \ \ \ \ \ \ \ \;#\ a=1\ b=2\ c=3\nargs\ \{1\ 2\}\ a\ b\ \{c\ 3\}\ \ \ \ \ \ \ \ \;#\ a=1\ b=2\ c=3\nargs\ \{\}\ \{a\ 1\}\ \{b\ 2\}\ \{c\ 3\}\ \ \ \;#\ a=1\ b=2\ c=3\nargs\ \{1\ 2\ 3\ 4\ 5\}\ a\ b\ c\ args\ \;#\ a=1\ b=2\ c=3\ args=\{4\ 5\}\n======\n\n\[FM\]:\ to\ conform\ to\ the\ \[AMG\]\ (and\ `lassign`)\ syntax.\n\n======\nproc\ args\ \{values\ args\}\ \{\n\ \ \ \ apply\ \[list\ \$args\ \[list\ foreach\ e\ \$args\ \{\n\ \ \ \ \ \ \ \ uplevel\ 2\ \[list\ set\ \[lindex\ \$e\ 0\]\ \[set\ \[lindex\ \$e\ 0\]\]\]\n\ \ \ \ \}\]\]\ \{*\}\$values\n\}\n======\n\nboth\ versions\ seem\ to\ have\ the\ same\ speed.\n\n\[PYK\],\ 2015-03-06,\ wonders\ why\ `lassign`\ decided\ to\ mess\ with\ variable\ values\nthat\ were\ already\ set,\ preventing\ default\ values\ from\ being\ set\ beforehand:\n\n======\n#warning,\ hypothetical\ semantics\nset\ color\ green\nlassign\ 15\ size\ color\nset\ color\ \;#\ ->\ green\n======\n\n\[AMG\]:\ I'm\ pretty\ sure\ this\ behavior\ is\ imported\ from\ \[\[\[foreach\]\]\]\ which\ does\ the\ same\ thing.\ \ \[\[foreach\]\]\ is\ often\ used\ as\ a\ substitute\ for\ \[\[lassign\]\]\ on\ older\ Tcl.\nSo,\ what\ to\ do\ when\ there\ are\ more\ variable\ names\ than\ list\ elements?\ \ I\ can\ think\ of\ four\ approaches:\n\ \ \ *\ Set\ the\ extras\ to\ empty\ string.\ \ This\ is\ current\ \[\[foreach\]\]\ and\ \[\[lassign\]\]\ behavior.\n\n\[CMcC\]\ 2005-11-14:\ I\ may\ be\ just\ exceptionally\ grumpy\ this\ morning,\ but\ the\nbehavior\ of\ supplying\ default\ empty\ values\ to\ extra\ variables\ means\ you\ can't\ndistinguish\ between\ a\ trailing\ var\ with\ no\ matching\ value,\ and\ one\ with\ a\ value\nof\ the\ empty\ string.\ \ Needs\ an\ option,\ `-greedy`\ or\ something,\ to\ distinguish\nbetween\ the\ two\ cases.\ \ Oh,\ ''and''\ it\ annoys\ me\ that\ `\[lset\]`\ is\ already\ntaken,\ because\ `\[lassign\]`\ doesn't\ resonate\ well\ with\ `\[set\]`.\n\n\[Kristian\ Scheibe\]:\ I\ agree\ with\ CMcC\ on\ both\ counts\ -\ supplying\ a\ default\ empty\ value\ when\n\[KS\]:\ I\ agree\ with\ CMcC\ on\ both\ counts\ -\ supplying\ a\ default\ empty\ value\ when\nbetter\ than\ `lassign`/`set`.\ \ However,\ I\ have\ a\ few\ other\ tweaks\ I\ would\nsuggest,\ then\ I'll\ tie\ it\ all\ together\ with\ code\ to\ do\ what\ I\ suggest.\ \ \n\nFirst,\ there\ is\ a\ fundamental\ asymmetry\ between\ the\ `\[set\]`\ and\ `\[lassign\]`\nFirst,\ there\ is\ a\ fundamental\ assymetry\ between\ the\ `\[set\]`\ and\ `\[lassign\]`\nIn\ fact,\ most\ computer\ languages\ use\ the\ idiom\ of\ right\ to\ left\ for\ assignment.\nHowever,\ there\ are\ certain\ advantages\ to\ the\ left\ to\ right\ behavior\ of\n`lassign`\ (in\ Tcl).\ \ For\ example,\ when\ assigning\ a\ list\ of\ variables\ to\ the\ncontents\ of\ args.\ \ Using\ the\ right\ to\ left\ idiom\ would\ require\ `\[eval\]`.\ \ \n\nStill,\ the\ right-to-left\ behavior\ also\ has\ its\ benefits.\ \ It\ allows\ you\ to\nperform\ computations\ on\ the\ values\ before\ performing\ the\ assignment.\ \ Take,\ for\nexample,\ this\ definition\ of\ factorial\ (borrowed\ from\ \[Tail\ call\ optimization\]):\n\n======\nproc\ fact0\ n\ \{\nproc\ fact0\ \{n\}\ \{\n\ \ \ \ while\ \{\$n\ >\ 1\}\ \{\n\ \ \ \ \ \ \ \ set\ result\ \[expr\ \{\$result\ *\ \$n\}\]\n\ \ \ \ \ \ \ \ set\ n\ \[expr\ \{\$n\ -\ 1\}\]\n\ \ \ \ \}\n\ \ \ \ return\ \$result\n\}\n======\n\nNow,\ with\ `lassign`\ as\ currently\ implemented,\ we\ can\ \"improve\"\ this\ as\ follows:\n\n======\nproc\ fact0\ n\ \{\nproc\ fact0\ \{n\}\ \{\n\ \ \ \ while\ \{\$n\ >\ 1\}\ \{\n\ \ \ \ \ \ \ \ lassign\ \[list\ \[expr\ \{\$result\ *\ \$n\}\]\ \[expr\ \{\$n\ -\ 1\}\]\]\ result\ n\n\ \ \ \ \}\n\ \ \ \ return\ \$result\n\}\n======\n\nI'm\ hard-pressed\ to\ believe\ that\ this\ is\ better.\ \ However,\ if\ we\ changed\nlassign\ to\ be\ `lassign\ vars\ args`,\ we\ can\ write\ this\ as:\n\n======\nproc\ fact0\ n\ \{\nproc\ fact0\ \{\ n\ \}\ \{\n\ \ \ \ while\ \{\$n\ >\ 1\}\ \{\n\ \ \ \ \ \ \ \ lassign\ \{result\ n\}\ \[expr\ \{\$result\ *\ \$n\}\]\ \[expr\ \{\$n\ -\ 1\}\ \]\n\ \ \ \ \}\n\ \ \ \ return\ \$result\n\}\n======\n\nTo\ my\ eye,\ at\ least,\ this\ is\ much\ more\ readable.\ \ \n\nSo,\ I\ suggest\ that\ we\ use\ two\ procedures:\ `lassign`\ and\ `lassignr`\ (where\ \"r\"\nstands\ for\ \"reverse\").\ \ `lassign`\ would\ be\ used\ for\ the\ \"standard\"\ behavior:\nright\ to\ left.\ \ lassignr\ would\ then\ be\ used\ for\ left\ to\ right.\ \ This\ is\nbackwards\ from\ the\ way\ it\ is\ defined\ above\ for\ TclX\ and\ Tcl\ 8.5.\ \ Nonetheless,\nthis\ behavior\ aligns\ better\ with\ our\ training\ and\ intuition.\ \ \n\nAlso,\ this\ provides\ a\ couple\ of\ other\ benefits.\ \ First,\ the\ parallel\ to\ set\ is\nmuch\ more\ obvious.\ \ lassign\ and\ set\ both\ copy\ from\ right\ to\ left\ (of\ course,\ we\nare\ still\ left\ with\ the\ asymmetry\ in\ their\ names\ -\ I'll\ get\ to\ that\ later).\nare\ still\ left\ with\ the\ assymetry\ in\ their\ names\ -\ I'll\ get\ to\ that\ later).\nhave\ a\ value\ supplied\ is\ bad\ form\;\ this\ is\ not\ what\ set\ does!\ \ If\ you\ enter\n`set\ a`\ you\ get\ the\ value\ of\ `\$a`,\ you\ don't\ assign\ the\ empty\ string\ to\ `a`.\nlassign\ should\ not\ either.\ \ If\ you\ want\ to\ assign\ the\ empty\ string\ using\ set\nyou\ would\ enter:\n\n======\nset\ a\ \{\}\n======\n\nWith\ lassign,\ you\ would\ do\ something\ similar:\n\n======\nlassign\ \{a\ b\ c\}\ 1\ \{\}\n======\n\nHere,\ `\$a`\ gets\ `1`,\ `\$b`\ gets\ the\ empty\ string,\ and\ `\$c`\ is\ not\ touched.\ \ This\nbehavior\ nicely\ parallels\ that\ of\ `\[set\]`,\ except\ that\ `\[set\]`\ returns\ the\ new\nvalue,\ and\ `lassign`\ returns\ the\ remaining\ values.\ \ So,\ let's\ take\ another\ step\nin\ that\ direction\;\ we'll\ have\ `lassign`\ and\ `lassignr`\ return\ the\ \"used\"\ values\ninstead.\ \ \n\nBut\ this\ destroys\ a\ nice\ property\ of\ `lassign`.\ \ Can\ we\ recover\ that\ property?\nAlmost.\ \ We\ can\ do\ what\ `\[proc\]`\ does\;\ we\ can\ use\ the\ \"args\"\ variable\ name\ to\nindicate\ a\ variable\ that\ sucks\ up\ all\ the\ remaining\ items.\ \ So,\ now\ we\ get:\n\n======\n\ \ \ \ lassign\ \{a\ b\ args\}\ 1\ 2\ 3\ 4\ 5\ 6\n`\$a`\ gets\ `1`,\ `\$b`\ gets\ `2`,\ and\ args\ gets\ `3\ 4\ 5\ 6`.\ \ Of\ course,\ we\ would\nmake\ `lassignr`\ work\ similarly:\n\n======\nlassignr\ \{1\ 2\ 3\ 4\ 5\ 6\}\ a\ b\ args\n======\n\nBut,\ now\ that\ we\ have\ one\ of\ the\ nice\ behaviors\ of\ the\ proc\ \"assignment\",\ what\nabout\ that\ other\ useful\ feature:\ default\ values?\ \ We\ can\ do\ that\ as\ well.\ \ So,\nif\ a\ value\ is\ not\ provided,\ then\ the\ default\ value\ is\ used:\n\n======\nlassign\ \{a\ \{b\ 2\}\}\ one\n======\n\n`\$b`\ gets\ the\ value\ `2`.\ \ This\ also\ provides\ for\ the\ assignment\ of\ an\ empty\nlist\ to\ a\ variable\ if\ the\ value\ is\ not\ provided.\ \ So,\ those\ who\ liked\ that\nbehavior\ can\ have\ their\ wish\ as\ well:\n\n======\nlassign\ \{a\ \{b\ \{\}\}\}\ one\n======\n\nBut\ simple\ defaults\ are\ not\ always\ adequate.\ \ This\ only\ provides\ for\ constants.\nIf\ something\ beyond\ that\ is\ required,\ then\ explicit\ lists\ are\ needed.\ \ For\nexample:\n\n======\nlassign\ \[list\ a\ \[list\ b\ \$defaultb\]\]\ one\n======\n\nThis\ gets\ to\ be\ ugly,\ so\ we\ make\ one\ more\ provision:\ we\ allow\ variable\nreferences\ within\ the\ defaults:\ \ \n\n======\nlassign\ \{a\ \{b\ \$defaultb\}\}\ one\n======\n\nNow,\ this\ really\ begins\ to\ provide\ the\ simplicity\ and\ power\ that\ we\ should\nexpect\ from\ a\ general\ purpose\ utility\ routine.\ \ And,\ it\ parallels\ other\nbehaviors\ within\ Tcl\ (`\[proc\]`\ and\ `\[set\]`)\ well\ so\ that\ it\ feels\ natural.\ \ \nbehaviors\ within\ Tcl\ (proc\ and\ set)\ well\ so\ that\ it\ feels\ natural.\ \ \nBut\ we're\ still\ left\ with\ this\ `lassign`/`\[set\]`\ dichotomy.\ \ We\ can't\ rename\n`lassign`\ to\ be\ `lset`\ without\ potentially\ breaking\ someone's\ code,\ \ But\ notice\nthat\ lassign\ now\ provides\ features\ that\ `\[set\]`\ does\ not.\ \ So,\ instead,\ let's\ncreate\ an\ assign\ procedure\ that\ provides\ these\ same\ features,\ but\ only\ for\ a\nsingle\ value:\n\n======\nassign\ \{x\ 3\}\ 7\n======\n\nSets\ x\ to\ 7.\ \ If\ no\ value\ is\ provided,\ x\ will\ be\ 3.\ \ \n\nSo,\ we\ now\ have\ three\ functions,\ `assign`,\ `lassign`,\ and\ `lassignr`,\ that\ncollectively\ provide\ useful\ and\ powerful\ features\ that,\ used\ wisely,\ can\ make\nyour\ code\ more\ readable\ and\ maintainable.\ \ You\ could\ argue\ that\ you\ only\ \"need\"\none\ of\ these\ (pick\ one)\ -\ the\ others\ are\ easily\ constructed\ from\ whichever\ is\nchosen.\ \ However,\ having\ all\ three\ provides\ symmetry\ and\ flexibility.\ \ \n\nI\ have\ provided\ the\ definitions\ of\ these\ functions\ below.\ \ The\ implementation\nis\ less\ interesting\ than\ the\ simple\ power\ these\ routines\ provide.\ \ I'm\ certain\nthat\ many\ of\ you\ can\ improve\ these\ implementations.\ \ And,\ if\ you\ don't\ like\ my\nrationale\ on\ the\ naming\ of\ `lassignr`\;\ then\ you\ can\ swap\ the\ names.\ \ It's\ easy\nto\ change\ other\ aspects\ as\ well\;\ for\ example,\ if\ you\ still\ want\ lassign\ to\nreturn\ the\ unused\ values,\ it's\ relatively\ easy\ to\ modify\ these\ routines.\ \ \n\n======\nproc\ assign\ \{var\ args\}\ \{\n\ \ \ \ if\ \{\[llength\ \$var\]\ >\ 1\}\ \{\n\ \ \ \ \ \ \ \ uplevel\ set\ \$var\n\ \ \ \ \}\n\ \ \ \ uplevel\ set\ \[lindex\ \$var\ 0\]\ \$args\n\}\n\nproc\ lassign\ \{vars\ args\}\ \{\n\ \ \ \ if\ \{\ (\[lindex\ \$vars\ end\]\ eq\ \"args\")\ &&\ (\[\n\ \ \ \ \ \ \ \ llength\ \$args\]\ >\ \[llength\ \$vars\])\}\ \{\n\n\ \ \ \ \ \ \ \ set\ last\ \[expr\ \{\[llength\ \$vars\]\ -\ 1\}\]\n\ \ \ \ \ \ \ \ set\ args\ \[lreplace\ \$args\ \$last\ end\ \[lrange\ \$args\ \$last\ end\]\]\n\ \ \ \ \}\n\n\ \ \ \ #This\ is\ required\ so\ that\ we\ can\ distinguish\ between\ the\ value\ \{\}\ and\ no\n\ \ \ \ #value\n\ \ \ \ foreach\ val\ \$args\ \{lappend\ vals\ \[list\ \$val\]\}\n\ \ \ \ foreach\ var\ \$vars\ val\ \$vals\ \{\n\ \ \ \ \ \ \ \ lappend\ res\ \[uplevel\ assign\ \[list\ \$var\]\ \$val\]\n\ \ \ \ \}\n\ \ \ \ return\ \$res\n\}\n\nproc\ lassignr\ \{vals\ args\}\ \{\n\ \ \ \ uplevel\ lassign\ \[list\ \$args\]\ \$vals\n\}\n======\n\n\[slebetman\]:\ KS,\ your\ proposal\ seems\ to\ illustrate\ that\ you\ don't\ ''get''\ the\nidea\ of\ `lassign`.\ For\ several\ years\ now\ I\ have\ used\ my\ own\ homegrown\ proc,\n`unlist`,\ that\ has\ the\ exact\ same\ syntax\ and\ semantics\ of\ `lassign`.\ The\nsemantics\ behind\ `lassign`\ is\ not\ like\ `\[set\]`\ at\ all\ but\ more\ like\ `\[scan\]`\nwhere\ the\ semantics\ in\ most\ programming\ languages\ (at\ least\ in\ C\ and\ Python)\ is\nindeed\ assignment\ from\ left\ to\ right.\ The\ general\ use\ of\ a\ ''scanning''\nfunction\ like\ `lassign`\ is\ that\ given\ an\ opaque\ list\ (one\ that\ you\ did\ not\ncreate)\ split\ it\ into\ individual\ variables.\n\nIf\ you\ really\ understand\ the\ semantics\ `lassign`\ was\ trying\ to\ achieve\ then\ you\nwouldn't\ have\ proposed\ your:\n\n======\nlassign\ vars\ args\n======\n\nTo\ achieve\ the\ semantics\ of\ `lassign`\ but\ with\ right\ to\ left\ assignment\ you\nshould\ have\ proposed:\n\n======\nlassign\ vars\ list\n======\n\nOf\ course,\ your\ proposal\ above\ can\ work\ with\ Tcl8.5\ using\ \[\{*\}\]:\n\n======\nlassign\ \{var1\ var2\ var3\}\ \{*\}\$list\n======\n\nBut\ that\ means\ for\ 90%\ of\ cases\ where\ you\ would\ use\ `lassign`\ you\ will\ have\ to\nalso\ use\ \[\{*\}\].\ Actually\ Tcl8.4\ already\ has\ a\ command\ which\ does\ what\ lassign\nis\ supposed\ to\ do\ but\ with\ a\ syntax\ that\ assigns\ from\ right\ to\ left:\n`\[foreach\]`.\ \ Indeed,\ my\ home-grown\ `unlist`\ is\ simply\ a\ wrapper\ around\n`\[foreach\]`\ as\ demonstrated\ by\ \[sbron\]\ above.\ With\ 8.4,\ if\ you\ want\nlassign-like\ functionality\ you\ would\ do:\n\n======\nforeach\ \{var1\ var2\ var3\}\ \$list\ \{\}\n======\n\n\[Kristian\ Scheibe\]:\ \[slebetman\],\ you're\ right,\ I\ did\ not\ ''get''\ that\ the\ semantics\ of\n\[KS\]:\ \[slebetman\],\ you're\ right,\ I\ did\ not\ ''get''\ that\ the\ semantics\ of\nand\ not\ `\[set\]`\ (which\ is\ a\ synonym\ for\ `assign`).\ \ Most\ languages\ refer\ to\ the\noperation\ of\ putting\ a\ value\ into\ a\ variable\ as\ \"assignment\",\ and,\ with\ only\nspecialized\ exception,\ this\ is\ done\ right-to-left.\ \ I'm\ certain\ that\ others\nhave\ made\ this\ same\ mistake\;\ in\ fact,\ I\ count\ myself\ in\ good\ company,\ since\ the\nauthors\ of\ the\ lassign\ \[TIP\]\ \[http://purl.org/tcl/tip/57.html%|%57\]\ for\ Tcl\ 8.5\nmake\ the\ same\ assumption:\n\nIt\ would\ be\ more\ logical\ if\ the\ developer\ could\ write\ the\ following:\n\n======\nset\ \{x\ y\}\ \[LocateFeature\ \$featureID\]\n======\n\nor\n\n======\nmset\ \{x\ y\}\ \[LocateFeature\ \$featureID\]\n======\n\nSo,\ you\ see,\ when\ \[TIP\]\ \[http://www.tcl.tk/cgi-bin/tct/tip/57.html%|%#57\]\ was\nwritten,\ the\ thinking\ was\ in\ terms\ of\ right-to-left\ semantics\ (and,\ as\ a\nsynonym\ to\ \[set\]).\ \ The\ fact\ that\ they\ decided\ to\ go\ with\ the\ left-to-right\nsemantics\ was\ likely\ due\ to\ the\ issue\ that\ you\ point\ out\ about\ requiring\ an\n`\[eval\]`\ or\ `\[\{*\}\]`,\ not\ that\ they\ were\ thinking\ in\ terms\ of\ `\[scan\]`.\n\nBut,\ your\ point\ does\ suggest\ that\ a\ better\ name\ for\ `lassign`\ with\nleft-to-right\ semantics\ is\ '''`lscan`'''.\ \ However,\ I\ was\ not\ ignorant\ of\ the\nconcern\ with\ requiring\ `\[eval\]`\ or\ `\[\{*\}\]`.\ \ I\ was\ not\ proposing\n''eliminating''\ the\ left-to-right\ semanitcs,\ but\ adding\ the\ right-to-left\nsemantics.\ \ What\ was\ left\ was\ more\ a\ discussion\ of\ proper\ naming.\ \ I\ think\ that\nyou\ have\ helped\ to\ show\ that\ '''lassign'''\ should\ be\ used\ for\ right-to-left\nsemantics,\ and\ '''`lscan`'''\ for\ left-to-right.\ \ \n\nYou\ also\ did\ not\ ''get''\ that\ I\ had\ much\ more\ to\ say\ than\ simply\ whether\n`lassign`\ should\ be\ left-to-right\ or\ right-to-left.\ \ For\ example,\ I\ made\ a\nproposal\ to\ allow\ for\ default\ values\ to\ be\ supplied\ when\ no\ value\ is\ available\nin\ the\ scan/assignment,\ in\ the\ manner\ of\ `\[proc\]`.\ \ \n\nThis\ is\ not\ a\ trivial\ concern.\ \ Take,\ for\ example,\ the\ behaviors\ of\ `\[scan\]`\nand\ `\[regexp\]`.\ \ `\[regexp\]`\ assigns\ `\{\}`\ to\ a\ variable\ argument\ if\ there\ is\ no\nmatching\ value\ in\ the\ string\ (but,\ only\ if\ the\ match\ succeeded).\ \ However,\n`\[scan\]`\ only\ assigns\ values\ to\ those\ variables\ for\ which\ it\ finds\ a\ match\;\ an\nunmatched\ variable\ is\ not\ touched.\ \ \n\nThis\ leads\ to\ two\ different\ idioms\ for\ providing\ default\ values.\ \ The\ following\nexample,\ based\ on\ an\ example\ in\ \[http://www.tcl.tk/man/tcl8.4/TclCmd/scan.htm\],\nuses\ `\[scan\]`\ and\ `\[regexp\]`\ to\ parse\ a\ simple\ color\ specification\ of\ the\ form\n#RRGGBB,\ where\ RR,\ GG,\ and\ BB\ are\ 2-digit\ hex\ numbers.\ \ If\ a\ value\ is\ missing\n(eg,\ #5004),\ then\ it\ defaults\ to\ 80.\ \ \n\n======\n##\ \ Using\ \[scan\]\nset\ r\ 80\nset\ g\ 80\nset\ b\ 80\nscan\ \$rgb\ #%2x%2x%2x\ r\ g\ b\nset\ resultRgb\ \[list\ \$r\ \$g\ \$b\]\n\n##\ \ Using\ \[regexp\]\nregexp\ \{\$#(..)?(..)?(..)?^\}\ \$rgb\ r\ g\ b\nif\ \{!\ \[llength\ \$r\]\}\ \{set\ r\ 80\}\nif\ \{!\ \[llength\ \$g\]\}\ \{set\ g\ 80\}\nif\ \{!\ \[llength\ \$b\]\}\ \{set\ b\ 80\}\nset\ resultRgb\ \[list\ \$r\ \$g\ \$b\]\n======\n\nAs\ you\ can\ see,\ the\ idioms\ required\ are\ different\ in\ each\ case.\ \ If,\ as\ you're\ndeveloping\ code,\ you\ start\ with\ the\ `\[scan\]`\ approach,\ then\ decide\ you\ need\ to\nsupport\ something\ more\ sophisticated\ (eg,\ you\ want\ to\ have\ decimal,\ octal,\ or\nhex\ numbers),\ then\ you\ need\ to\ remember\ to\ change\ not\ just\ the\ parsing,\ but\ the\nmethod\ of\ assigning\ defaults\ as\ well.\ \ \n\nThis\ also\ demonstrates\ again\ that\ providing\ a\ default\ value\ (eg,\ `\{\}`)\ when\ no\nvalue\ is\ provided\ really\ ought\ to\ be\ defined\ by\ the\ application\ and\ not\ the\noperation.\ \ The\ method\ of\ using\ defaults\ with\ `\[scan\]`\ is\ more\ straightforward\n(and\ amenable\ to\ using\ `\[lassign\]`\ or\ `\[lscan\]`)\ than\ the\ method\ with\n`\[regexp\]`.\ \ \n\nThe\ solution\ that\ I\ proposed\ was\ to\ make\ applying\ defaults\ similar\ to\ the\ way\nthat\ defaults\ are\ handled\ with\ `\[proc\]`:\ `\{var\ dflt\}`.\ \ In\ fact,\ I\ would\ go\ a\nstep\ farther\ and\ suggest\ that\ this\ idiom\ should\ be\ available\ to\ all\ Tcl\noperations\ that\ assign\ values\ to\ variables\ (including\ `\[scan\]`\ and\ `\[regexp\]`).\nBut,\ I\ think\ that\ this\ is\ unlikely\ to\ occur,\ and\ is\ beyond\ the\ scope\ of\ what\ I\nwas\ discussing.\ \ \n\nThe\ real\ point\ of\ my\ original\ posting\ was\ to\ demonstrate\ the\ utility,\nflexibility,\ power,\ and\ readability\ or\ using\ this\ idiom.\ \ I\ think\ it's\ a\ shame\nto\ limit\ that\ idiom\ to\ `\[proc\]`.\ \ The\ most\ general\ application\ of\ it\ is\ to\ use\nit\ for\ assignment,\ which\ is\ what\ I\ showed.\ \ \n\n\[slebetman\]:\ I\ agree\ with\ the\ defaults\ mechanism.\ Especially\ since\ we're\ so\nused\ to\ using\ it\ in\ `\[proc\]`.\ I\ wish\ we\ have\ it\ in\ all\ commands\ that\ assigns\nvalues\ to\ multiple\ variables:\n\n======\nlassign\ \$foo\ \{a\ 0\}\ \{b\ \{\}\}\ \{c\ none\}\nscan\ \$rgb\ #%2x%2x%2x\ \{r\ 80\}\ \{g\ 80\}\ \{b\ 80\}\nregexp\ \{\$#(..)?(..)?(..)?^\}\ \$rgb\ \{r\ 80\}\ \{g\ 80\}\ \{b\ 80\}\nforeach\ \{x\ \{y\ 0\}\ \{z\ 100\}\}\ \$argv\ \{..\}\n======\n\nI\ think\ such\ commands\ should\ check\ if\ the\ variable\ it\ is\ assigning\ to\ is\ a\ pair\nof\ words\ of\ which\ the\ second\ word\ is\ the\ default\ value.\ Assigning\ an\ empty\nstring\ have\ always\ seemed\ to\ me\ too\ much\ like\ the\ hackish\ NULL\ value\ trick\ in\n\[C\]\ (the\ number\ of\ times\ I\ had\ to\ restructure\ apps\ because\ the\ customer\ninsisted\ that\ zero\ is\ a\ valid\ value\ and\ should\ not\ signify\ undefined...).\n\nThe\ only\ downside\ I\ can\ think\ of\ is\ that\ this\ breaks\ apps\ with\ spaces\ in\nvariable\ names.\ But\ then\ again,\ most\ of\ us\ are\ used\ to\ not\ writing\ spaces\ in\nvariable\ names\ and\ we\ are\ used\ to\ this\ syntax\ in\ `\[proc\]`.\n\nBTW,\ I\ also\ think\ `lassign`\ is\ a\ bad\ name\ for\ this\ operation.\ It\ makes\ much\nmore\ sense\ if\ we\ instead\ use\ the\ name\ `lassign`\ to\ mean\ '''assign\ \"things\"\ to\ a\nlist'''\ which\ fits\ your\ syntax\ proposal.\ My\ personal\ preference\ is\ still\n'''`unlist`'''\ (when\ we\ finally\ get\ 8.5\ I'll\ be\ doing\ an\ `interp\ alias\ \{\}\nunlist\ \{\}\ lassign`).\ '''`lscan`'''\ doesn't\ sound\ right\ to\ me\ but\ `lsplit`\nsounds\ just\ right\ for\ '''splitting\ a\ list\ into\ individual\ variables'''.\n\n\[DKF\]:\ The\ name\ comes\ from\ \[TclX\].\ Choosing\ a\ different\ name\ or\ argument\ syntax\nto\ that\ very\ well\ known\ piece\ of\ code\ is\ not\ worth\ it\;\ just\ gratuitous\nincompatability.\n\n----\n\nfine\ just\ the\ way\ it\ is,\ `\[lset\]`\ is\ already\ taken,\ anything-'''scan'''\ sounds\nlike\ it\ does\ a\ heck\ of\ a\ lot\ more\ than\ just\ assigning\ words\ to\ variables,\ and\nthe\ concept\ of\ `\[proc\]`-like\ default\ values\ just\ makes\ me\ shudder...\ \ Even\ in\nthe\ definition\ of\ a\ `\[proc\]`!\ \ \;)\n\nSomething\ I\ ''would''\ like\ to\ see,\ is\ an\ '''lrassign'''\ that\ does\ the\n''left-to-right''\ thing,\ and\ ''maybe''\ some\ variant\ or\ option\ to\ `lassign`\ that\ntakes\ a\ second\ list\ of\ ''default''\ values:\n\n======\nlassign-with-defs\ defaultsList\ valuesList\ ?variable\ ...?\n======\n\nwhere\ the\ defaults\ list\ would\ be\ empty-string-extended\ to\ the\ number\ of\nvariables\ given\ (any\ extra\ defaults\ would\ simply\ be\ ignored),\ the\ values\ list\nwouldn't\ (any\ extra\ values\ would\ be\ returned\ as\ per\ usual),\ so\ you'd\ end\ up\nwith:\n\n======\nlassign-with-defs\ \{1\ 2\ 3\}\ \{a\ \{\}\}\ w\ x\ y\ z\n======\n\nbeing\ the\ equivalent\ of:\n\n======\nset\ w\ a\ \ \ \ \;#\ from\ values\ list\nset\ x\ \{\}\ \ \ \;#\ also\ from\ values\ list\nset\ y\ 3\ \ \ \ \;#\ 3rd\ default\ value\ carried\ through\nset\ z\ \{\}\ \ \ \;#\ empty-string\ expanded\ defaults\n#\ with\ both\ arguments\ consumed,\ and\ empty\ string\ is\ returned\n======\n\nThe\ old\ filling-with-empty-strings\ `\[lassign\]`\ behaviour\ would\ thus\ be\ achieved\nby\ simply\ giving\ it\ an\ empty\ default\ values\ list,\ and\ the\ whole\ thing\ would\ be\nabsolutely\ fabulous.\ \ \;)\n\nOf\ course,\ the\ catch\ is\ that\ if\ you\ simply\ take\ away\ the\nfilling-with-empty-strings\ behaviour\ from\ `\[lassign\]`,\ then\ the\ defaults\ncapability\ is\ created\ by\ simply\ doing\ two\ `\[lassign\]`s.\ \ A\ little\ wasteful,\nperhaps\ (possibly\ problematic\ if\ variable\ write\ traces\ are\ involved),\ but\ still\nbetter\ than\ most\ of\ the\ alternatives.\ \ (Perhaps\ a\ third\ argument\ to\ `\[lrepeat\]`\nwould\ fulfill\ the\ empty-string-filling\ requirement\ by\ accepting\ an\ initial\nlist,\ and\ repeatedly\ appending\ the\ specified\ ''item''\ until\ the\ list\ contains\nat\ least\ ''count''\ words?\ \ I\ can\ imagine\ several\ occasions\ where\ that\ could\ be\nhandy.)\n\n----\n\[Ed\ Hume\]:\ I\ think\ the\ syntax\ of\ `lassign`\ is\ not\ as\ useful\ as\ having\ the\ value\nlist\ and\ the\ variable\ name\ list\ being\ of\ similar\ structure:\n\ \n======\nvset\ \{value1\ value2\ value3\ ...\}\ \{name1\ name2\ name3\ ...\}\n======\n\nI\ have\ provided\ an\ `lset`\ command\ since\ Tcl\ 7.6\ in\ my\ toolset\ which\ was\ renamed\nto\ vset\ with\ Tcl\ 8.4.\ \ Having\ both\ the\ names\ and\ values\ as\ vectors\ allows\ you\nto\ easily\ pass\ both\ to\ other\ procedures\ without\ resorting\ to\ a\ variable\ number\nof\ arguments.\ \ It\ is\ a\ common\ idiom\ to\ assign\ each\ row\ of\ table\ data\ to\ a\ list\nof\ column\ names\ and\ work\ with\ it:\n\n======\nforeach\ row\ \$rows\ \{\n\ \ \ \ vset\ \$row\ \$cols\n\ \ \ \ #\ now\ each\ column\ name\ is\ defined\ with\ the\ data\ of\ the\ table\ row\n\ \ \ \ #\ ...\n\}\n======\n\nA\ second\ significant\ advantage\ of\ this\ syntax\ is\ that\ the\ structure\ of\ the\nnames\ and\ the\ values\ are\ not\ limited\ to\ vectors.\ \ The\ vset\ command\ is\ actually\na\ simplified\ case\ of\ the\ rset\ command\ which\ does\ a\ recursive\ set\ of\ nested\ data\nstructures:\n\n======\nrset\ \{1\ 2\ 3\}\ \{a\ b\ c\}\n#\ \$a\ is\ 1,\ \$b\ is\ 2,\ ...\nrset\ \{\{1.1\ 1.2\ 1.3\}\ 2\ \{3.1\ 3.2\}\}\ \{\{a\ b\ c\}\ d\ \{e\ f\}\}\n#\ \$a\ is\ 1.1,\ \$b\ is\ 1.2,\ \$f\ is\ 3.2,....\n======\n\nThe\ syntax\ of\ `vset`\ and\ `rset`\ lend\ themselves\ to\ providing\ an\ optional\ third\nargument\ to\ provide\ default\ values\ in\ the\ case\ where\ empty\ values\ are\ not\ndesired.\ So\ this\ is\ a\ cleaner\ implementation\ of\ frederic's\nlassign-with-defaults\ -\ the\ defaults\ values\ can\ have\ the\ usual\ empty\ string\ndefault.\n\nNow\ that\ Tcl\ has\ the\ \[\{*\}%|%expansion\]\ operator,\ the\ difference\ between\n`lassign`\ and\ `vset`\ is\ not\ as\ important\ as\ it\ was,\ but\ I\ do\ think\ `vset`\ is\ a\nlot\ more\ powerful.\n\n\[DKF\]:\ Ultimately,\ we\ went\ for\ the\ option\ that\ we\ did\ because\ that\ was\ what\n\[TclX\]\ used.\ However,\ a\ side-benefit\ is\ that\ it\ also\ makes\ compiling\ the\ncommand\ to\ bytecode\ much\ easier\ than\ it\ would\ have\ been\ with\ `vset`.\ (Command\ncompilers\ are\ rather\ tricky\ to\ write\ when\ they\ need\ to\ parse\ apart\ arguments.)\n\n**\ Script\ Implementation\ **\n\nBoth\ the\ built-in\ `lassign`\ and\ the\ \[TclX\]\ `lassign`\ are\ faster\ than\ the\nscripted\ implementations\ presented\ below.\n\n\[KPV\]:\ For\ those\ who\ want\ to\ use\ \[\[lassign\]\]\ before\ Tcl\ 8.5,\ and\ without\ngetting\ \[TclX\],\ here's\ a\ tcl-only\ version\ of\ `lassign`:\n\n======\nif\ \{\[namespace\ which\ lassign\]\ eq\ \{\}\}\ \{\n\ \ \ \ proc\ lassign\ \{values\ args\}\ \{\n\ \ \ \ \ \ \ \ set\ vlen\ \[llength\ \$values\]\n\ \ \ \ \ \ \ \ set\ alen\ \[llength\ \$args\]\n\n\ \ \ \ \ \ \ \ #\ Make\ lists\ equal\ length\n\ \ \ \ \ \ \ \ for\ \{set\ i\ \$vlen\}\ \{\$i\ <\ \$alen\}\ \{incr\ i\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ lappend\ values\ \{\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ uplevel\ 1\ \[list\ foreach\ \$args\ \$values\ break\]\n\ \ \ \ \ \ \ \ return\ \[lrange\ \$values\ \$alen\ end\]\n\ \ \ \ \}\n\}\n======\n\n\[jcw\]:\ Couldn't\ resist\ rewriting\ in\ a\ style\ I\ prefer.\ \ Chaq'un\ son\ gout\ -\ a\nmatter\ of\ taste\ -\ of\ course:\n\n======\nif\ \{\[info\ procs\ lassign\]\ eq\ \{\}\}\ \{\n\ \ \ \ proc\ lassign\ \{values\ args\}\ \{\n\ \ \ \ \ \ \ \ while\ \{\[llength\ \$values\]\ <\ \[llength\ \$args\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ lappend\ values\ \{\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ uplevel\ 1\ \[list\ foreach\ \$args\ \$values\ break\]\n\ \ \ \ \ \ \ \ lrange\ \$values\ \[llength\ \$args\]\ end\n\ \ \ \ \}\n\}\n======\n\n\[KPV\]:\ But\ from\ an\ efficiency\ point\ of\ view,\ you're\ calling\ `\[llength\]`\ way\ too\nmany\ times--every\ iteration\ through\ the\ `\[while\]`\ loop\ does\ two\ unnecessary\ncalls.\ How\ about\ this\ version\ --\ your\ style,\ but\ more\ efficient:\n\n======\nif\ \{\[namespace\ which\ lassign\]\ eq\ \{\}\}\ \{\n\ \ \ \ proc\ lassign\ \{values\ args\}\ \{\n\ \ \ \ \ \ \ \ set\ alen\ \[llength\ \$args\]\n\ \ \ \ \ \ \ \ set\ vlen\ \[llength\ \$values\]\n\ \ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \ while\ \{\[incr\ vlen\]\ <=\ \$alen\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ lappend\ values\ \{\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ uplevel\ 1\ \[list\ foreach\ \$args\ \$values\ break\]\n\ \ \ \ \ \ \ \ lrange\ \$values\ \$alen\ end\n\ \ \ \ \}\n\}\n======\n\n\[jcw\]\ interjects:\ Keith...\ are\ you\ sure\ `\[llength\]`\ is\ slower?\ (be\ sure\ to\ test\ninside\ a\ `\[proc\]`\ body)\n\n\[kpv\]\ continues:\ It\ must\ be\ my\ assembler/C\ background\ but\ I\ see\ those\ function\ncalls,\ especially\ the\ one\ returning\ a\ constant\ value\ and\ wince.\ \ But\ you're\ncorrect,\ calling\ llength\ is\ no\ slower\ than\ accessing\ a\ variable.\ It\ guess\ the\nbyte\ compiler\ is\ optimizing\ out\ the\ actual\ call.\n\n\[DKF\]:\ `\[llength\]`\ is\ indeed\ bytecoded.\n\n\[sbron\]:\ I\ see\ no\ reason\ to\ massage\ the\ values\ list\ at\ all.\ `\[foreach\]`\ will\ do\nexactly\ the\ same\ thing\ even\ if\ the\ values\ list\ is\ shorter\ than\ the\ \[args\]\ list.\nI.e.\ this\ should\ be\ all\ that's\ needed:\n\n======\nif\ \{\[namespace\ which\ lassign\]\ eq\ \{\}\}\ \{\n\ \ \ proc\ lassign\ \{values\ args\}\ \{\n\ \ \ \ \ \ \ uplevel\ 1\ \[list\ foreach\ \$args\ \$values\ break\]\n\ \ \ \ \ \ \ lrange\ \$values\ \[llength\ \$args\]\ end\n\ \ \ \}\n\}\n======\n\n\[RS\]:\ Yup\ -\ that's\ the\ minimality\ I\ like\ :^)\n\nThis\ version\ does\ not\ work\ as\ described\ in\ the\ documentation\ for\ lassign\ for\nthis\ case:\n\n======\n%\ lassign\ \[list\]\ a\ b\ c\n%\ set\ a\ncan't\ read\ \"a\":\ no\ such\ variable\n======\n\n\[sbron\]:\ You\ are\ right,\ I\ just\ noticed\ that\ myself\ too.\ Improved\ version:\n\n======\nif\ \{\[namespace\ which\ lassign\]\ eq\ \{\}\}\ \{\n\ \ \ proc\ lassign\ \{values\ args\}\ \{\n\ \ \ \ \ \ \ uplevel\ 1\ \[list\ foreach\ \$args\ \[linsert\ \$values\ end\ \{\}\]\ break\]\n\ \ \ \ \ \ \ lrange\ \$values\ \[llength\ \$args\]\ end\n\ \ \ \}\n\}\n======\n\n\[AMG\]:\ I\ prefer\ to\ use\ `\[catch\]`\ to\ check\ for\ a\ command's\ existence.\ \ Not\ only\nwill\ `\[catch\]`\ check\ if\ the\ command\ exists,\ but\ it\ can\ also\ check\ if\ it\nsupports\ an\ \[ensemble\]\ subcommand,\ an\ option,\ or\ some\ syntax.\ \ Plus\ it\ works\nwith\ `\[interp\ alias\]`,\ a\ clear\ advantage\ over\ `\[info\ commands\]`.\n\n======\nif\ \{\[catch\ \{lassign\ \{\}\}\]\}\ \{\n\ \ \ \ proc\ lassign\ \{list\ args\}\ \{\n\ \ \ \ proc\ lassign\ \{vals\ args\}\ \{\n\ \ \ \ \ \ \ \ lappend\ vals\ \"\"\n\ \ \ \ \ \ \ \ uplevel\ 1\ \[list\ foreach\ \$args\ \$vals\ break\]\n\ \ \ \ \ \ \ \ lrange\ \$vals\ \[llength\ \$args\]\ end-1\n\}\n======\n\n\n**\ Open\ Questions\ **\n\n\[JMN\]:\ tclX\ doesn't\ seem\ to\ use\ a\ separate\ namespace\ for\ its\ commands\ so\ if\ we\ndo\ a\ 'package\ require\ tclX'\ in\ Tcl\ 8.5+,\ which\ version\ of\ a\ command\ such\ as\nlassign\ will\ end\ up\ being\ used?\nlassign\ will\ end\ up\ being\ used?\ \ \n=== regexp2} CALL {my render lassign '''\[http://www.tcl.tk/man/tcl/TclCmd/lassign.htm%|%lassign\]''',\ a\ \[Tcl\ Commands%|%built-in\]\ \[Tcl\]\ \[command\],\ '''unpacks'''\ a\ \[list\]\ into\ \[variable\]s.\n\n`lassign`\ became\ a\ built-in\ command\ in\ Tcl\ \[Changes\ in\ Tcl/Tk\ 8.5%|%8.5\].\n\n**\ Synopsis\ **\n\n\n\n\ \ \ \ :\ \ \ '''lassign'''\ ''list''\ ''varName''\ ?''varName''\ ...?\n\n**\ Documentation\ **\n\n\n\n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/lassign.htm%|%official\ reference\]:\ \ \ \n\n\ \ \ \[TIP\]\ \[http://purl.org/tcl/tip/57.html%|%57\]:\ \ \ proposed\ making\ the\ \[TclX\]\ `lassign`\ command\ a\ built-in\ Tcl\ command\ \n\n**\ Description\ **\n\n\n\n`lassign`\ assigns\ values\ from\ a\ \[list\]\ to\ the\ specified\ variables,\ and\n\[return\]s\ the\ remaining\ values.\ \ For\ example:\n\n======\nset\ end\ \[lassign\ \{1\ 2\ 3\ 4\ 5\}\ a\ b\ c\]\n======\n\nwill\ set\ `\$a`\ to\ `1`,\ `\$b`\ to\ `2`,\ `\$c`\ to\ `3`,\ and\ `\$end`\ to\ `4\ 5`.\n\nIn\ \[lisp\]\ parlance:\n\n======\nset\ cdr\ \[lassign\ \$mylist\ car\]\n======\n\nIf\ there\ are\ more\ ''varNames''\ than\ there\ are\ items\ in\ the\ list,\ the\ extra\nif\ there\ are\ more\ ''varNames''\ than\ there\ are\ items\ in\ the\ list,\ the\ extra\n\n======none\n%\ lassign\ \{1\ 2\}\ a\ b\ c\n%\ puts\ \$a\n1\n%\ puts\ \$b\n2\n%\ puts\ \$c\n\n%\n======\n\nIn\ Tcl\ prior\ to\ 8.5,\ `\[foreach\]`\ was\ used\ to\ achieve\ the\ functionality\ of\n`\[lassign\]`:\n\n======\nforeach\ \{var1\ var2\ var3\}\ \$list\ break\n======\nThis\ was\ unwise,\ as\ it\ would\ cause\ a\ second\ iteration\ (or\ more)\ to\ be\ done\ when\ `\$list`\ contains\ more\ than\ 3\ items\ (in\ this\ case).\ Putting\ the\ \[break\]\ in\ makes\ the\ behaviour\ predictable.\n\n\n**\ Example:\ \[Perl\]-ish\ `shift`\ **\n\n\[DKF\]\ cleverly\ points\ out\ that\ `lassign`\ makes\ a\ \[Perl\]-ish\ `shift`\ this\ easy:\n\n======\nproc\ shift\ \{\}\ \{\n\ \ \ \ global\ argv\n\ \ \ \ set\ argv\ \[lassign\ \$argv\ v\]\n\ \ \ \ return\ \$v\n\}\n======\n\nOn\ the\ other\ hand,\ \[Hemang\ Lavana\]\ observes\ that\ TclXers\ already\ have\n`\[lvarpop\]\ ::argv`,\ an\ exact\ synonym\ for\ `shift`.\n\nOn\ the\ third\ hand,\ \[RS\]\ would\ use\ our\ old\ friend\ \[K\]\ to\ code\ like\ this:\n\n======\nproc\ shift\ \{\}\ \{\n\ \ \ \ K\ \[lindex\ \$::argv\ 0\]\ \[set\ ::argv\ \[lrange\ \$::argv\[set\ ::argv\ \{\}\]\ 1\ end\]\]\n\}\n======\n\n\[Lars\ H\]:\ Then\ I\ can't\ resist\ doing\ the\ above\ without\ the\ K:\n\n======\nproc\ shift\ \{\}\ \{\n\ \ \ \ lindex\ \$::argv\ \[set\ ::argv\ \[lrange\ \$::argv\[set\ ::argv\ \{\}\]\ 1\ end\]\;\ expr\ 0\]\n\}\n======\n\n\n\n**\ Default\ Value\ **\n\n\[FM\]:\ here's\ a\ quick\ way\ to\ assign\ with\ default\ value,\ using\ `\[apply\]`:\n\n======\nproc\ args\ \{spec\ list\}\ \{\n\ \ \ \ apply\ \[list\ \$spec\ \[list\ foreach\ \{e\}\ \$spec\ \{\n\ \ \ \ \ \ \ \ uplevel\ 2\ \[list\ set\ \[lindex\ \$e\ 0\]\ \[set\ \[lindex\ \$e\ 0\]\]\]\n\ \ \ \ \}\]\]\ \{*\}\$list\n\}\nset\ L\ \{\}\nargs\ \{\{a\ 0\}\ \{b\ 0\}\ \{c\ 0\}\ args\}\ \$L\n======\n\n\[AMG\]:\ Clever.\ \ Here's\ my\ version,\ which\ actually\ uses\ `\[lassign\]`,\ plus\ it\nmatches\ `\[lassign\]`'s\ value-variable\ ordering.\ \ It\ uses\ `\[lcomp\]`\ for\ brevity.\n\n======\nproc\ args\ \{vals\ args\}\ \{\n\ \ \ \ set\ vars\ \[lcomp\ \{\$name\}\ for\ \{name\ default\}\ inside\ \$args\]\n\ \ \ \ set\ allvals\ \"\\\[list\ \[join\ \[lcomp\ \{\"\\\[set\ \[list\ \$e\]\\\]\"\}\ for\ e\ in\ \$vars\]\]\\\]\"\n\ \ \ \ apply\ \[list\ \$args\ \"uplevel\ 2\ \\\[list\ lassign\ \$allvals\ \$vars\\\]\"\]\ \{*\}\$vals\n\}\n======\n\nWithout\ `\[lcomp\]`:\n\n======\nproc\ args\ \{vals\ args\}\ \{\n\ \ \ \ lassign\ \"\"\ scr\ vars\n\ \ \ \ foreach\ varspec\ \$args\ \{\n\ \ \ \ \ \ \ \ append\ scr\ \"\ \\\[set\ \[list\ \[lindex\ \$varspec\ 0\]\]\\\]\"\n\ \ \ \ \ \ \ \ lappend\ vars\ \[lindex\ \$varspec\ 0\]\n\ \ \ \ \}\n\ \ \ \ apply\ \[list\ \$args\ \"uplevel\ 2\ \\\[list\ lassign\ \\\[list\$scr\\\]\ \$vars\\\]\"\]\ \{*\}\$vals\n\}\n======\n\nThis\ code\ reminds\ me\ of\ the\ movie\ \"Inception\"\ \[http://en.wikipedia.org/wiki/Inception_%28film%29\].\ \ It\ exists,\ creates\ itself,\ and\ operates\ at\ and\ across\ multiple\ levels\ of\ interpretation.\ \ There's\ the\ caller,\ there's\ \[\[args\]\],\ there's\ \[\[\[apply\]\]\],\ then\ there's\ the\ \[\[\[uplevel\]\ 2\]\]\ that\ goes\ back\ to\ the\ caller.\ \ The\ caller\ is\ the\ waking\ world,\ \[\[args\]\]\ is\ the\ dream,\ \[\[apply\]\]\ is\ its\ dream-within-a-dream,\ and\ \[\[uplevel\]\]\ is\ ''its''\ dream-within-a-dream\ that\ is\ used\ to\ implant\ an\ idea\ (or\ variable)\ into\ the\ waking\ world\ (the\ caller).\ \ And\ of\ course,\ the\ caller\ could\ itself\ be\ a\ child\ stack\ frame,\ so\ maybe\ reality\ is\ just\ another\ dream!\ \;^)\n\nOr\ maybe\ this\ code\ is\ a\ Matryoshka\ nesting\ doll\ \[http://en.wikipedia.org/wiki/Matryoshka\]\ whose\ innermost\ doll\ contains\ the\ outside\ doll.\ \;^)\n\nOkay,\ now\ that\ I've\ put\ a\ cross-cap\ in\ reality\ \[http://en.wikipedia.org/wiki/Cross_cap\],\ let\ me\ demonstrate\ how\ \[\[args\]\]\ is\ used:\n\n======\nargs\ \{1\ 2\ 3\}\ a\ b\ c\ \ \ \ \ \ \ \ \ \ \;#\ a=1\ b=2\ c=3\nargs\ \{1\ 2\}\ a\ b\ \{c\ 3\}\ \ \ \ \ \ \ \ \;#\ a=1\ b=2\ c=3\nargs\ \{\}\ \{a\ 1\}\ \{b\ 2\}\ \{c\ 3\}\ \ \ \;#\ a=1\ b=2\ c=3\nargs\ \{1\ 2\ 3\ 4\ 5\}\ a\ b\ c\ args\ \;#\ a=1\ b=2\ c=3\ args=\{4\ 5\}\n======\n\n\[FM\]:\ to\ conform\ to\ the\ \[AMG\]\ (and\ `lassign`)\ syntax.\n\n======\nproc\ args\ \{values\ args\}\ \{\n\ \ \ \ apply\ \[list\ \$args\ \[list\ foreach\ e\ \$args\ \{\n\ \ \ \ \ \ \ \ uplevel\ 2\ \[list\ set\ \[lindex\ \$e\ 0\]\ \[set\ \[lindex\ \$e\ 0\]\]\]\n\ \ \ \ \}\]\]\ \{*\}\$values\n\}\n======\n\nboth\ versions\ seem\ to\ have\ the\ same\ speed.\n\n\[PYK\],\ 2015-03-06,\ wonders\ why\ `lassign`\ decided\ to\ mess\ with\ variable\ values\nthat\ were\ already\ set,\ preventing\ default\ values\ from\ being\ set\ beforehand:\n\n======\n#warning,\ hypothetical\ semantics\nset\ color\ green\nlassign\ 15\ size\ color\nset\ color\ \;#\ ->\ green\n======\n\n\[AMG\]:\ I'm\ pretty\ sure\ this\ behavior\ is\ imported\ from\ \[\[\[foreach\]\]\]\ which\ does\ the\ same\ thing.\ \ \[\[foreach\]\]\ is\ often\ used\ as\ a\ substitute\ for\ \[\[lassign\]\]\ on\ older\ Tcl.\nSo,\ what\ to\ do\ when\ there\ are\ more\ variable\ names\ than\ list\ elements?\ \ I\ can\ think\ of\ four\ approaches:\n\ \ \ *\ Set\ the\ extras\ to\ empty\ string.\ \ This\ is\ current\ \[\[foreach\]\]\ and\ \[\[lassign\]\]\ behavior.\n\n\[CMcC\]\ 2005-11-14:\ I\ may\ be\ just\ exceptionally\ grumpy\ this\ morning,\ but\ the\nbehavior\ of\ supplying\ default\ empty\ values\ to\ extra\ variables\ means\ you\ can't\ndistinguish\ between\ a\ trailing\ var\ with\ no\ matching\ value,\ and\ one\ with\ a\ value\nof\ the\ empty\ string.\ \ Needs\ an\ option,\ `-greedy`\ or\ something,\ to\ distinguish\nbetween\ the\ two\ cases.\ \ Oh,\ ''and''\ it\ annoys\ me\ that\ `\[lset\]`\ is\ already\ntaken,\ because\ `\[lassign\]`\ doesn't\ resonate\ well\ with\ `\[set\]`.\n\n\[Kristian\ Scheibe\]:\ I\ agree\ with\ CMcC\ on\ both\ counts\ -\ supplying\ a\ default\ empty\ value\ when\n\[KS\]:\ I\ agree\ with\ CMcC\ on\ both\ counts\ -\ supplying\ a\ default\ empty\ value\ when\nbetter\ than\ `lassign`/`set`.\ \ However,\ I\ have\ a\ few\ other\ tweaks\ I\ would\nsuggest,\ then\ I'll\ tie\ it\ all\ together\ with\ code\ to\ do\ what\ I\ suggest.\ \ \n\nFirst,\ there\ is\ a\ fundamental\ asymmetry\ between\ the\ `\[set\]`\ and\ `\[lassign\]`\nFirst,\ there\ is\ a\ fundamental\ assymetry\ between\ the\ `\[set\]`\ and\ `\[lassign\]`\nIn\ fact,\ most\ computer\ languages\ use\ the\ idiom\ of\ right\ to\ left\ for\ assignment.\nHowever,\ there\ are\ certain\ advantages\ to\ the\ left\ to\ right\ behavior\ of\n`lassign`\ (in\ Tcl).\ \ For\ example,\ when\ assigning\ a\ list\ of\ variables\ to\ the\ncontents\ of\ args.\ \ Using\ the\ right\ to\ left\ idiom\ would\ require\ `\[eval\]`.\ \ \n\nStill,\ the\ right-to-left\ behavior\ also\ has\ its\ benefits.\ \ It\ allows\ you\ to\nperform\ computations\ on\ the\ values\ before\ performing\ the\ assignment.\ \ Take,\ for\nexample,\ this\ definition\ of\ factorial\ (borrowed\ from\ \[Tail\ call\ optimization\]):\n\n======\nproc\ fact0\ n\ \{\nproc\ fact0\ \{n\}\ \{\n\ \ \ \ while\ \{\$n\ >\ 1\}\ \{\n\ \ \ \ \ \ \ \ set\ result\ \[expr\ \{\$result\ *\ \$n\}\]\n\ \ \ \ \ \ \ \ set\ n\ \[expr\ \{\$n\ -\ 1\}\]\n\ \ \ \ \}\n\ \ \ \ return\ \$result\n\}\n======\n\nNow,\ with\ `lassign`\ as\ currently\ implemented,\ we\ can\ \"improve\"\ this\ as\ follows:\n\n======\nproc\ fact0\ n\ \{\nproc\ fact0\ \{n\}\ \{\n\ \ \ \ while\ \{\$n\ >\ 1\}\ \{\n\ \ \ \ \ \ \ \ lassign\ \[list\ \[expr\ \{\$result\ *\ \$n\}\]\ \[expr\ \{\$n\ -\ 1\}\]\]\ result\ n\n\ \ \ \ \}\n\ \ \ \ return\ \$result\n\}\n======\n\nI'm\ hard-pressed\ to\ believe\ that\ this\ is\ better.\ \ However,\ if\ we\ changed\nlassign\ to\ be\ `lassign\ vars\ args`,\ we\ can\ write\ this\ as:\n\n======\nproc\ fact0\ n\ \{\nproc\ fact0\ \{\ n\ \}\ \{\n\ \ \ \ while\ \{\$n\ >\ 1\}\ \{\n\ \ \ \ \ \ \ \ lassign\ \{result\ n\}\ \[expr\ \{\$result\ *\ \$n\}\]\ \[expr\ \{\$n\ -\ 1\}\ \]\n\ \ \ \ \}\n\ \ \ \ return\ \$result\n\}\n======\n\nTo\ my\ eye,\ at\ least,\ this\ is\ much\ more\ readable.\ \ \n\nSo,\ I\ suggest\ that\ we\ use\ two\ procedures:\ `lassign`\ and\ `lassignr`\ (where\ \"r\"\nstands\ for\ \"reverse\").\ \ `lassign`\ would\ be\ used\ for\ the\ \"standard\"\ behavior:\nright\ to\ left.\ \ lassignr\ would\ then\ be\ used\ for\ left\ to\ right.\ \ This\ is\nbackwards\ from\ the\ way\ it\ is\ defined\ above\ for\ TclX\ and\ Tcl\ 8.5.\ \ Nonetheless,\nthis\ behavior\ aligns\ better\ with\ our\ training\ and\ intuition.\ \ \n\nAlso,\ this\ provides\ a\ couple\ of\ other\ benefits.\ \ First,\ the\ parallel\ to\ set\ is\nmuch\ more\ obvious.\ \ lassign\ and\ set\ both\ copy\ from\ right\ to\ left\ (of\ course,\ we\nare\ still\ left\ with\ the\ asymmetry\ in\ their\ names\ -\ I'll\ get\ to\ that\ later).\nare\ still\ left\ with\ the\ assymetry\ in\ their\ names\ -\ I'll\ get\ to\ that\ later).\nhave\ a\ value\ supplied\ is\ bad\ form\;\ this\ is\ not\ what\ set\ does!\ \ If\ you\ enter\n`set\ a`\ you\ get\ the\ value\ of\ `\$a`,\ you\ don't\ assign\ the\ empty\ string\ to\ `a`.\nlassign\ should\ not\ either.\ \ If\ you\ want\ to\ assign\ the\ empty\ string\ using\ set\nyou\ would\ enter:\n\n======\nset\ a\ \{\}\n======\n\nWith\ lassign,\ you\ would\ do\ something\ similar:\n\n======\nlassign\ \{a\ b\ c\}\ 1\ \{\}\n======\n\nHere,\ `\$a`\ gets\ `1`,\ `\$b`\ gets\ the\ empty\ string,\ and\ `\$c`\ is\ not\ touched.\ \ This\nbehavior\ nicely\ parallels\ that\ of\ `\[set\]`,\ except\ that\ `\[set\]`\ returns\ the\ new\nvalue,\ and\ `lassign`\ returns\ the\ remaining\ values.\ \ So,\ let's\ take\ another\ step\nin\ that\ direction\;\ we'll\ have\ `lassign`\ and\ `lassignr`\ return\ the\ \"used\"\ values\ninstead.\ \ \n\nBut\ this\ destroys\ a\ nice\ property\ of\ `lassign`.\ \ Can\ we\ recover\ that\ property?\nAlmost.\ \ We\ can\ do\ what\ `\[proc\]`\ does\;\ we\ can\ use\ the\ \"args\"\ variable\ name\ to\nindicate\ a\ variable\ that\ sucks\ up\ all\ the\ remaining\ items.\ \ So,\ now\ we\ get:\n\n======\n\ \ \ \ lassign\ \{a\ b\ args\}\ 1\ 2\ 3\ 4\ 5\ 6\n`\$a`\ gets\ `1`,\ `\$b`\ gets\ `2`,\ and\ args\ gets\ `3\ 4\ 5\ 6`.\ \ Of\ course,\ we\ would\nmake\ `lassignr`\ work\ similarly:\n\n======\nlassignr\ \{1\ 2\ 3\ 4\ 5\ 6\}\ a\ b\ args\n======\n\nBut,\ now\ that\ we\ have\ one\ of\ the\ nice\ behaviors\ of\ the\ proc\ \"assignment\",\ what\nabout\ that\ other\ useful\ feature:\ default\ values?\ \ We\ can\ do\ that\ as\ well.\ \ So,\nif\ a\ value\ is\ not\ provided,\ then\ the\ default\ value\ is\ used:\n\n======\nlassign\ \{a\ \{b\ 2\}\}\ one\n======\n\n`\$b`\ gets\ the\ value\ `2`.\ \ This\ also\ provides\ for\ the\ assignment\ of\ an\ empty\nlist\ to\ a\ variable\ if\ the\ value\ is\ not\ provided.\ \ So,\ those\ who\ liked\ that\nbehavior\ can\ have\ their\ wish\ as\ well:\n\n======\nlassign\ \{a\ \{b\ \{\}\}\}\ one\n======\n\nBut\ simple\ defaults\ are\ not\ always\ adequate.\ \ This\ only\ provides\ for\ constants.\nIf\ something\ beyond\ that\ is\ required,\ then\ explicit\ lists\ are\ needed.\ \ For\nexample:\n\n======\nlassign\ \[list\ a\ \[list\ b\ \$defaultb\]\]\ one\n======\n\nThis\ gets\ to\ be\ ugly,\ so\ we\ make\ one\ more\ provision:\ we\ allow\ variable\nreferences\ within\ the\ defaults:\ \ \n\n======\nlassign\ \{a\ \{b\ \$defaultb\}\}\ one\n======\n\nNow,\ this\ really\ begins\ to\ provide\ the\ simplicity\ and\ power\ that\ we\ should\nexpect\ from\ a\ general\ purpose\ utility\ routine.\ \ And,\ it\ parallels\ other\nbehaviors\ within\ Tcl\ (`\[proc\]`\ and\ `\[set\]`)\ well\ so\ that\ it\ feels\ natural.\ \ \nbehaviors\ within\ Tcl\ (proc\ and\ set)\ well\ so\ that\ it\ feels\ natural.\ \ \nBut\ we're\ still\ left\ with\ this\ `lassign`/`\[set\]`\ dichotomy.\ \ We\ can't\ rename\n`lassign`\ to\ be\ `lset`\ without\ potentially\ breaking\ someone's\ code,\ \ But\ notice\nthat\ lassign\ now\ provides\ features\ that\ `\[set\]`\ does\ not.\ \ So,\ instead,\ let's\ncreate\ an\ assign\ procedure\ that\ provides\ these\ same\ features,\ but\ only\ for\ a\nsingle\ value:\n\n======\nassign\ \{x\ 3\}\ 7\n======\n\nSets\ x\ to\ 7.\ \ If\ no\ value\ is\ provided,\ x\ will\ be\ 3.\ \ \n\nSo,\ we\ now\ have\ three\ functions,\ `assign`,\ `lassign`,\ and\ `lassignr`,\ that\ncollectively\ provide\ useful\ and\ powerful\ features\ that,\ used\ wisely,\ can\ make\nyour\ code\ more\ readable\ and\ maintainable.\ \ You\ could\ argue\ that\ you\ only\ \"need\"\none\ of\ these\ (pick\ one)\ -\ the\ others\ are\ easily\ constructed\ from\ whichever\ is\nchosen.\ \ However,\ having\ all\ three\ provides\ symmetry\ and\ flexibility.\ \ \n\nI\ have\ provided\ the\ definitions\ of\ these\ functions\ below.\ \ The\ implementation\nis\ less\ interesting\ than\ the\ simple\ power\ these\ routines\ provide.\ \ I'm\ certain\nthat\ many\ of\ you\ can\ improve\ these\ implementations.\ \ And,\ if\ you\ don't\ like\ my\nrationale\ on\ the\ naming\ of\ `lassignr`\;\ then\ you\ can\ swap\ the\ names.\ \ It's\ easy\nto\ change\ other\ aspects\ as\ well\;\ for\ example,\ if\ you\ still\ want\ lassign\ to\nreturn\ the\ unused\ values,\ it's\ relatively\ easy\ to\ modify\ these\ routines.\ \ \n\n======\nproc\ assign\ \{var\ args\}\ \{\n\ \ \ \ if\ \{\[llength\ \$var\]\ >\ 1\}\ \{\n\ \ \ \ \ \ \ \ uplevel\ set\ \$var\n\ \ \ \ \}\n\ \ \ \ uplevel\ set\ \[lindex\ \$var\ 0\]\ \$args\n\}\n\nproc\ lassign\ \{vars\ args\}\ \{\n\ \ \ \ if\ \{\ (\[lindex\ \$vars\ end\]\ eq\ \"args\")\ &&\ (\[\n\ \ \ \ \ \ \ \ llength\ \$args\]\ >\ \[llength\ \$vars\])\}\ \{\n\n\ \ \ \ \ \ \ \ set\ last\ \[expr\ \{\[llength\ \$vars\]\ -\ 1\}\]\n\ \ \ \ \ \ \ \ set\ args\ \[lreplace\ \$args\ \$last\ end\ \[lrange\ \$args\ \$last\ end\]\]\n\ \ \ \ \}\n\n\ \ \ \ #This\ is\ required\ so\ that\ we\ can\ distinguish\ between\ the\ value\ \{\}\ and\ no\n\ \ \ \ #value\n\ \ \ \ foreach\ val\ \$args\ \{lappend\ vals\ \[list\ \$val\]\}\n\ \ \ \ foreach\ var\ \$vars\ val\ \$vals\ \{\n\ \ \ \ \ \ \ \ lappend\ res\ \[uplevel\ assign\ \[list\ \$var\]\ \$val\]\n\ \ \ \ \}\n\ \ \ \ return\ \$res\n\}\n\nproc\ lassignr\ \{vals\ args\}\ \{\n\ \ \ \ uplevel\ lassign\ \[list\ \$args\]\ \$vals\n\}\n======\n\n\[slebetman\]:\ KS,\ your\ proposal\ seems\ to\ illustrate\ that\ you\ don't\ ''get''\ the\nidea\ of\ `lassign`.\ For\ several\ years\ now\ I\ have\ used\ my\ own\ homegrown\ proc,\n`unlist`,\ that\ has\ the\ exact\ same\ syntax\ and\ semantics\ of\ `lassign`.\ The\nsemantics\ behind\ `lassign`\ is\ not\ like\ `\[set\]`\ at\ all\ but\ more\ like\ `\[scan\]`\nwhere\ the\ semantics\ in\ most\ programming\ languages\ (at\ least\ in\ C\ and\ Python)\ is\nindeed\ assignment\ from\ left\ to\ right.\ The\ general\ use\ of\ a\ ''scanning''\nfunction\ like\ `lassign`\ is\ that\ given\ an\ opaque\ list\ (one\ that\ you\ did\ not\ncreate)\ split\ it\ into\ individual\ variables.\n\nIf\ you\ really\ understand\ the\ semantics\ `lassign`\ was\ trying\ to\ achieve\ then\ you\nwouldn't\ have\ proposed\ your:\n\n======\nlassign\ vars\ args\n======\n\nTo\ achieve\ the\ semantics\ of\ `lassign`\ but\ with\ right\ to\ left\ assignment\ you\nshould\ have\ proposed:\n\n======\nlassign\ vars\ list\n======\n\nOf\ course,\ your\ proposal\ above\ can\ work\ with\ Tcl8.5\ using\ \[\{*\}\]:\n\n======\nlassign\ \{var1\ var2\ var3\}\ \{*\}\$list\n======\n\nBut\ that\ means\ for\ 90%\ of\ cases\ where\ you\ would\ use\ `lassign`\ you\ will\ have\ to\nalso\ use\ \[\{*\}\].\ Actually\ Tcl8.4\ already\ has\ a\ command\ which\ does\ what\ lassign\nis\ supposed\ to\ do\ but\ with\ a\ syntax\ that\ assigns\ from\ right\ to\ left:\n`\[foreach\]`.\ \ Indeed,\ my\ home-grown\ `unlist`\ is\ simply\ a\ wrapper\ around\n`\[foreach\]`\ as\ demonstrated\ by\ \[sbron\]\ above.\ With\ 8.4,\ if\ you\ want\nlassign-like\ functionality\ you\ would\ do:\n\n======\nforeach\ \{var1\ var2\ var3\}\ \$list\ \{\}\n======\n\n\[Kristian\ Scheibe\]:\ \[slebetman\],\ you're\ right,\ I\ did\ not\ ''get''\ that\ the\ semantics\ of\n\[KS\]:\ \[slebetman\],\ you're\ right,\ I\ did\ not\ ''get''\ that\ the\ semantics\ of\nand\ not\ `\[set\]`\ (which\ is\ a\ synonym\ for\ `assign`).\ \ Most\ languages\ refer\ to\ the\noperation\ of\ putting\ a\ value\ into\ a\ variable\ as\ \"assignment\",\ and,\ with\ only\nspecialized\ exception,\ this\ is\ done\ right-to-left.\ \ I'm\ certain\ that\ others\nhave\ made\ this\ same\ mistake\;\ in\ fact,\ I\ count\ myself\ in\ good\ company,\ since\ the\nauthors\ of\ the\ lassign\ \[TIP\]\ \[http://purl.org/tcl/tip/57.html%|%57\]\ for\ Tcl\ 8.5\nmake\ the\ same\ assumption:\n\nIt\ would\ be\ more\ logical\ if\ the\ developer\ could\ write\ the\ following:\n\n======\nset\ \{x\ y\}\ \[LocateFeature\ \$featureID\]\n======\n\nor\n\n======\nmset\ \{x\ y\}\ \[LocateFeature\ \$featureID\]\n======\n\nSo,\ you\ see,\ when\ \[TIP\]\ \[http://www.tcl.tk/cgi-bin/tct/tip/57.html%|%#57\]\ was\nwritten,\ the\ thinking\ was\ in\ terms\ of\ right-to-left\ semantics\ (and,\ as\ a\nsynonym\ to\ \[set\]).\ \ The\ fact\ that\ they\ decided\ to\ go\ with\ the\ left-to-right\nsemantics\ was\ likely\ due\ to\ the\ issue\ that\ you\ point\ out\ about\ requiring\ an\n`\[eval\]`\ or\ `\[\{*\}\]`,\ not\ that\ they\ were\ thinking\ in\ terms\ of\ `\[scan\]`.\n\nBut,\ your\ point\ does\ suggest\ that\ a\ better\ name\ for\ `lassign`\ with\nleft-to-right\ semantics\ is\ '''`lscan`'''.\ \ However,\ I\ was\ not\ ignorant\ of\ the\nconcern\ with\ requiring\ `\[eval\]`\ or\ `\[\{*\}\]`.\ \ I\ was\ not\ proposing\n''eliminating''\ the\ left-to-right\ semanitcs,\ but\ adding\ the\ right-to-left\nsemantics.\ \ What\ was\ left\ was\ more\ a\ discussion\ of\ proper\ naming.\ \ I\ think\ that\nyou\ have\ helped\ to\ show\ that\ '''lassign'''\ should\ be\ used\ for\ right-to-left\nsemantics,\ and\ '''`lscan`'''\ for\ left-to-right.\ \ \n\nYou\ also\ did\ not\ ''get''\ that\ I\ had\ much\ more\ to\ say\ than\ simply\ whether\n`lassign`\ should\ be\ left-to-right\ or\ right-to-left.\ \ For\ example,\ I\ made\ a\nproposal\ to\ allow\ for\ default\ values\ to\ be\ supplied\ when\ no\ value\ is\ available\nin\ the\ scan/assignment,\ in\ the\ manner\ of\ `\[proc\]`.\ \ \n\nThis\ is\ not\ a\ trivial\ concern.\ \ Take,\ for\ example,\ the\ behaviors\ of\ `\[scan\]`\nand\ `\[regexp\]`.\ \ `\[regexp\]`\ assigns\ `\{\}`\ to\ a\ variable\ argument\ if\ there\ is\ no\nmatching\ value\ in\ the\ string\ (but,\ only\ if\ the\ match\ succeeded).\ \ However,\n`\[scan\]`\ only\ assigns\ values\ to\ those\ variables\ for\ which\ it\ finds\ a\ match\;\ an\nunmatched\ variable\ is\ not\ touched.\ \ \n\nThis\ leads\ to\ two\ different\ idioms\ for\ providing\ default\ values.\ \ The\ following\nexample,\ based\ on\ an\ example\ in\ \[http://www.tcl.tk/man/tcl8.4/TclCmd/scan.htm\],\nuses\ `\[scan\]`\ and\ `\[regexp\]`\ to\ parse\ a\ simple\ color\ specification\ of\ the\ form\n#RRGGBB,\ where\ RR,\ GG,\ and\ BB\ are\ 2-digit\ hex\ numbers.\ \ If\ a\ value\ is\ missing\n(eg,\ #5004),\ then\ it\ defaults\ to\ 80.\ \ \n\n======\n##\ \ Using\ \[scan\]\nset\ r\ 80\nset\ g\ 80\nset\ b\ 80\nscan\ \$rgb\ #%2x%2x%2x\ r\ g\ b\nset\ resultRgb\ \[list\ \$r\ \$g\ \$b\]\n\n##\ \ Using\ \[regexp\]\nregexp\ \{\$#(..)?(..)?(..)?^\}\ \$rgb\ r\ g\ b\nif\ \{!\ \[llength\ \$r\]\}\ \{set\ r\ 80\}\nif\ \{!\ \[llength\ \$g\]\}\ \{set\ g\ 80\}\nif\ \{!\ \[llength\ \$b\]\}\ \{set\ b\ 80\}\nset\ resultRgb\ \[list\ \$r\ \$g\ \$b\]\n======\n\nAs\ you\ can\ see,\ the\ idioms\ required\ are\ different\ in\ each\ case.\ \ If,\ as\ you're\ndeveloping\ code,\ you\ start\ with\ the\ `\[scan\]`\ approach,\ then\ decide\ you\ need\ to\nsupport\ something\ more\ sophisticated\ (eg,\ you\ want\ to\ have\ decimal,\ octal,\ or\nhex\ numbers),\ then\ you\ need\ to\ remember\ to\ change\ not\ just\ the\ parsing,\ but\ the\nmethod\ of\ assigning\ defaults\ as\ well.\ \ \n\nThis\ also\ demonstrates\ again\ that\ providing\ a\ default\ value\ (eg,\ `\{\}`)\ when\ no\nvalue\ is\ provided\ really\ ought\ to\ be\ defined\ by\ the\ application\ and\ not\ the\noperation.\ \ The\ method\ of\ using\ defaults\ with\ `\[scan\]`\ is\ more\ straightforward\n(and\ amenable\ to\ using\ `\[lassign\]`\ or\ `\[lscan\]`)\ than\ the\ method\ with\n`\[regexp\]`.\ \ \n\nThe\ solution\ that\ I\ proposed\ was\ to\ make\ applying\ defaults\ similar\ to\ the\ way\nthat\ defaults\ are\ handled\ with\ `\[proc\]`:\ `\{var\ dflt\}`.\ \ In\ fact,\ I\ would\ go\ a\nstep\ farther\ and\ suggest\ that\ this\ idiom\ should\ be\ available\ to\ all\ Tcl\noperations\ that\ assign\ values\ to\ variables\ (including\ `\[scan\]`\ and\ `\[regexp\]`).\nBut,\ I\ think\ that\ this\ is\ unlikely\ to\ occur,\ and\ is\ beyond\ the\ scope\ of\ what\ I\nwas\ discussing.\ \ \n\nThe\ real\ point\ of\ my\ original\ posting\ was\ to\ demonstrate\ the\ utility,\nflexibility,\ power,\ and\ readability\ or\ using\ this\ idiom.\ \ I\ think\ it's\ a\ shame\nto\ limit\ that\ idiom\ to\ `\[proc\]`.\ \ The\ most\ general\ application\ of\ it\ is\ to\ use\nit\ for\ assignment,\ which\ is\ what\ I\ showed.\ \ \n\n\[slebetman\]:\ I\ agree\ with\ the\ defaults\ mechanism.\ Especially\ since\ we're\ so\nused\ to\ using\ it\ in\ `\[proc\]`.\ I\ wish\ we\ have\ it\ in\ all\ commands\ that\ assigns\nvalues\ to\ multiple\ variables:\n\n======\nlassign\ \$foo\ \{a\ 0\}\ \{b\ \{\}\}\ \{c\ none\}\nscan\ \$rgb\ #%2x%2x%2x\ \{r\ 80\}\ \{g\ 80\}\ \{b\ 80\}\nregexp\ \{\$#(..)?(..)?(..)?^\}\ \$rgb\ \{r\ 80\}\ \{g\ 80\}\ \{b\ 80\}\nforeach\ \{x\ \{y\ 0\}\ \{z\ 100\}\}\ \$argv\ \{..\}\n======\n\nI\ think\ such\ commands\ should\ check\ if\ the\ variable\ it\ is\ assigning\ to\ is\ a\ pair\nof\ words\ of\ which\ the\ second\ word\ is\ the\ default\ value.\ Assigning\ an\ empty\nstring\ have\ always\ seemed\ to\ me\ too\ much\ like\ the\ hackish\ NULL\ value\ trick\ in\n\[C\]\ (the\ number\ of\ times\ I\ had\ to\ restructure\ apps\ because\ the\ customer\ninsisted\ that\ zero\ is\ a\ valid\ value\ and\ should\ not\ signify\ undefined...).\n\nThe\ only\ downside\ I\ can\ think\ of\ is\ that\ this\ breaks\ apps\ with\ spaces\ in\nvariable\ names.\ But\ then\ again,\ most\ of\ us\ are\ used\ to\ not\ writing\ spaces\ in\nvariable\ names\ and\ we\ are\ used\ to\ this\ syntax\ in\ `\[proc\]`.\n\nBTW,\ I\ also\ think\ `lassign`\ is\ a\ bad\ name\ for\ this\ operation.\ It\ makes\ much\nmore\ sense\ if\ we\ instead\ use\ the\ name\ `lassign`\ to\ mean\ '''assign\ \"things\"\ to\ a\nlist'''\ which\ fits\ your\ syntax\ proposal.\ My\ personal\ preference\ is\ still\n'''`unlist`'''\ (when\ we\ finally\ get\ 8.5\ I'll\ be\ doing\ an\ `interp\ alias\ \{\}\nunlist\ \{\}\ lassign`).\ '''`lscan`'''\ doesn't\ sound\ right\ to\ me\ but\ `lsplit`\nsounds\ just\ right\ for\ '''splitting\ a\ list\ into\ individual\ variables'''.\n\n\[DKF\]:\ The\ name\ comes\ from\ \[TclX\].\ Choosing\ a\ different\ name\ or\ argument\ syntax\nto\ that\ very\ well\ known\ piece\ of\ code\ is\ not\ worth\ it\;\ just\ gratuitous\nincompatability.\n\n----\n\nfine\ just\ the\ way\ it\ is,\ `\[lset\]`\ is\ already\ taken,\ anything-'''scan'''\ sounds\nlike\ it\ does\ a\ heck\ of\ a\ lot\ more\ than\ just\ assigning\ words\ to\ variables,\ and\nthe\ concept\ of\ `\[proc\]`-like\ default\ values\ just\ makes\ me\ shudder...\ \ Even\ in\nthe\ definition\ of\ a\ `\[proc\]`!\ \ \;)\n\nSomething\ I\ ''would''\ like\ to\ see,\ is\ an\ '''lrassign'''\ that\ does\ the\n''left-to-right''\ thing,\ and\ ''maybe''\ some\ variant\ or\ option\ to\ `lassign`\ that\ntakes\ a\ second\ list\ of\ ''default''\ values:\n\n======\nlassign-with-defs\ defaultsList\ valuesList\ ?variable\ ...?\n======\n\nwhere\ the\ defaults\ list\ would\ be\ empty-string-extended\ to\ the\ number\ of\nvariables\ given\ (any\ extra\ defaults\ would\ simply\ be\ ignored),\ the\ values\ list\nwouldn't\ (any\ extra\ values\ would\ be\ returned\ as\ per\ usual),\ so\ you'd\ end\ up\nwith:\n\n======\nlassign-with-defs\ \{1\ 2\ 3\}\ \{a\ \{\}\}\ w\ x\ y\ z\n======\n\nbeing\ the\ equivalent\ of:\n\n======\nset\ w\ a\ \ \ \ \;#\ from\ values\ list\nset\ x\ \{\}\ \ \ \;#\ also\ from\ values\ list\nset\ y\ 3\ \ \ \ \;#\ 3rd\ default\ value\ carried\ through\nset\ z\ \{\}\ \ \ \;#\ empty-string\ expanded\ defaults\n#\ with\ both\ arguments\ consumed,\ and\ empty\ string\ is\ returned\n======\n\nThe\ old\ filling-with-empty-strings\ `\[lassign\]`\ behaviour\ would\ thus\ be\ achieved\nby\ simply\ giving\ it\ an\ empty\ default\ values\ list,\ and\ the\ whole\ thing\ would\ be\nabsolutely\ fabulous.\ \ \;)\n\nOf\ course,\ the\ catch\ is\ that\ if\ you\ simply\ take\ away\ the\nfilling-with-empty-strings\ behaviour\ from\ `\[lassign\]`,\ then\ the\ defaults\ncapability\ is\ created\ by\ simply\ doing\ two\ `\[lassign\]`s.\ \ A\ little\ wasteful,\nperhaps\ (possibly\ problematic\ if\ variable\ write\ traces\ are\ involved),\ but\ still\nbetter\ than\ most\ of\ the\ alternatives.\ \ (Perhaps\ a\ third\ argument\ to\ `\[lrepeat\]`\nwould\ fulfill\ the\ empty-string-filling\ requirement\ by\ accepting\ an\ initial\nlist,\ and\ repeatedly\ appending\ the\ specified\ ''item''\ until\ the\ list\ contains\nat\ least\ ''count''\ words?\ \ I\ can\ imagine\ several\ occasions\ where\ that\ could\ be\nhandy.)\n\n----\n\[Ed\ Hume\]:\ I\ think\ the\ syntax\ of\ `lassign`\ is\ not\ as\ useful\ as\ having\ the\ value\nlist\ and\ the\ variable\ name\ list\ being\ of\ similar\ structure:\n\ \n======\nvset\ \{value1\ value2\ value3\ ...\}\ \{name1\ name2\ name3\ ...\}\n======\n\nI\ have\ provided\ an\ `lset`\ command\ since\ Tcl\ 7.6\ in\ my\ toolset\ which\ was\ renamed\nto\ vset\ with\ Tcl\ 8.4.\ \ Having\ both\ the\ names\ and\ values\ as\ vectors\ allows\ you\nto\ easily\ pass\ both\ to\ other\ procedures\ without\ resorting\ to\ a\ variable\ number\nof\ arguments.\ \ It\ is\ a\ common\ idiom\ to\ assign\ each\ row\ of\ table\ data\ to\ a\ list\nof\ column\ names\ and\ work\ with\ it:\n\n======\nforeach\ row\ \$rows\ \{\n\ \ \ \ vset\ \$row\ \$cols\n\ \ \ \ #\ now\ each\ column\ name\ is\ defined\ with\ the\ data\ of\ the\ table\ row\n\ \ \ \ #\ ...\n\}\n======\n\nA\ second\ significant\ advantage\ of\ this\ syntax\ is\ that\ the\ structure\ of\ the\nnames\ and\ the\ values\ are\ not\ limited\ to\ vectors.\ \ The\ vset\ command\ is\ actually\na\ simplified\ case\ of\ the\ rset\ command\ which\ does\ a\ recursive\ set\ of\ nested\ data\nstructures:\n\n======\nrset\ \{1\ 2\ 3\}\ \{a\ b\ c\}\n#\ \$a\ is\ 1,\ \$b\ is\ 2,\ ...\nrset\ \{\{1.1\ 1.2\ 1.3\}\ 2\ \{3.1\ 3.2\}\}\ \{\{a\ b\ c\}\ d\ \{e\ f\}\}\n#\ \$a\ is\ 1.1,\ \$b\ is\ 1.2,\ \$f\ is\ 3.2,....\n======\n\nThe\ syntax\ of\ `vset`\ and\ `rset`\ lend\ themselves\ to\ providing\ an\ optional\ third\nargument\ to\ provide\ default\ values\ in\ the\ case\ where\ empty\ values\ are\ not\ndesired.\ So\ this\ is\ a\ cleaner\ implementation\ of\ frederic's\nlassign-with-defaults\ -\ the\ defaults\ values\ can\ have\ the\ usual\ empty\ string\ndefault.\n\nNow\ that\ Tcl\ has\ the\ \[\{*\}%|%expansion\]\ operator,\ the\ difference\ between\n`lassign`\ and\ `vset`\ is\ not\ as\ important\ as\ it\ was,\ but\ I\ do\ think\ `vset`\ is\ a\nlot\ more\ powerful.\n\n\[DKF\]:\ Ultimately,\ we\ went\ for\ the\ option\ that\ we\ did\ because\ that\ was\ what\n\[TclX\]\ used.\ However,\ a\ side-benefit\ is\ that\ it\ also\ makes\ compiling\ the\ncommand\ to\ bytecode\ much\ easier\ than\ it\ would\ have\ been\ with\ `vset`.\ (Command\ncompilers\ are\ rather\ tricky\ to\ write\ when\ they\ need\ to\ parse\ apart\ arguments.)\n\n**\ Script\ Implementation\ **\n\nBoth\ the\ built-in\ `lassign`\ and\ the\ \[TclX\]\ `lassign`\ are\ faster\ than\ the\nscripted\ implementations\ presented\ below.\n\n\[KPV\]:\ For\ those\ who\ want\ to\ use\ \[\[lassign\]\]\ before\ Tcl\ 8.5,\ and\ without\ngetting\ \[TclX\],\ here's\ a\ tcl-only\ version\ of\ `lassign`:\n\n======\nif\ \{\[namespace\ which\ lassign\]\ eq\ \{\}\}\ \{\n\ \ \ \ proc\ lassign\ \{values\ args\}\ \{\n\ \ \ \ \ \ \ \ set\ vlen\ \[llength\ \$values\]\n\ \ \ \ \ \ \ \ set\ alen\ \[llength\ \$args\]\n\n\ \ \ \ \ \ \ \ #\ Make\ lists\ equal\ length\n\ \ \ \ \ \ \ \ for\ \{set\ i\ \$vlen\}\ \{\$i\ <\ \$alen\}\ \{incr\ i\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ lappend\ values\ \{\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ uplevel\ 1\ \[list\ foreach\ \$args\ \$values\ break\]\n\ \ \ \ \ \ \ \ return\ \[lrange\ \$values\ \$alen\ end\]\n\ \ \ \ \}\n\}\n======\n\n\[jcw\]:\ Couldn't\ resist\ rewriting\ in\ a\ style\ I\ prefer.\ \ Chaq'un\ son\ gout\ -\ a\nmatter\ of\ taste\ -\ of\ course:\n\n======\nif\ \{\[info\ procs\ lassign\]\ eq\ \{\}\}\ \{\n\ \ \ \ proc\ lassign\ \{values\ args\}\ \{\n\ \ \ \ \ \ \ \ while\ \{\[llength\ \$values\]\ <\ \[llength\ \$args\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ lappend\ values\ \{\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ uplevel\ 1\ \[list\ foreach\ \$args\ \$values\ break\]\n\ \ \ \ \ \ \ \ lrange\ \$values\ \[llength\ \$args\]\ end\n\ \ \ \ \}\n\}\n======\n\n\[KPV\]:\ But\ from\ an\ efficiency\ point\ of\ view,\ you're\ calling\ `\[llength\]`\ way\ too\nmany\ times--every\ iteration\ through\ the\ `\[while\]`\ loop\ does\ two\ unnecessary\ncalls.\ How\ about\ this\ version\ --\ your\ style,\ but\ more\ efficient:\n\n======\nif\ \{\[namespace\ which\ lassign\]\ eq\ \{\}\}\ \{\n\ \ \ \ proc\ lassign\ \{values\ args\}\ \{\n\ \ \ \ \ \ \ \ set\ alen\ \[llength\ \$args\]\n\ \ \ \ \ \ \ \ set\ vlen\ \[llength\ \$values\]\n\ \ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \ while\ \{\[incr\ vlen\]\ <=\ \$alen\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ lappend\ values\ \{\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ uplevel\ 1\ \[list\ foreach\ \$args\ \$values\ break\]\n\ \ \ \ \ \ \ \ lrange\ \$values\ \$alen\ end\n\ \ \ \ \}\n\}\n======\n\n\[jcw\]\ interjects:\ Keith...\ are\ you\ sure\ `\[llength\]`\ is\ slower?\ (be\ sure\ to\ test\ninside\ a\ `\[proc\]`\ body)\n\n\[kpv\]\ continues:\ It\ must\ be\ my\ assembler/C\ background\ but\ I\ see\ those\ function\ncalls,\ especially\ the\ one\ returning\ a\ constant\ value\ and\ wince.\ \ But\ you're\ncorrect,\ calling\ llength\ is\ no\ slower\ than\ accessing\ a\ variable.\ It\ guess\ the\nbyte\ compiler\ is\ optimizing\ out\ the\ actual\ call.\n\n\[DKF\]:\ `\[llength\]`\ is\ indeed\ bytecoded.\n\n\[sbron\]:\ I\ see\ no\ reason\ to\ massage\ the\ values\ list\ at\ all.\ `\[foreach\]`\ will\ do\nexactly\ the\ same\ thing\ even\ if\ the\ values\ list\ is\ shorter\ than\ the\ \[args\]\ list.\nI.e.\ this\ should\ be\ all\ that's\ needed:\n\n======\nif\ \{\[namespace\ which\ lassign\]\ eq\ \{\}\}\ \{\n\ \ \ proc\ lassign\ \{values\ args\}\ \{\n\ \ \ \ \ \ \ uplevel\ 1\ \[list\ foreach\ \$args\ \$values\ break\]\n\ \ \ \ \ \ \ lrange\ \$values\ \[llength\ \$args\]\ end\n\ \ \ \}\n\}\n======\n\n\[RS\]:\ Yup\ -\ that's\ the\ minimality\ I\ like\ :^)\n\nThis\ version\ does\ not\ work\ as\ described\ in\ the\ documentation\ for\ lassign\ for\nthis\ case:\n\n======\n%\ lassign\ \[list\]\ a\ b\ c\n%\ set\ a\ncan't\ read\ \"a\":\ no\ such\ variable\n======\n\n\[sbron\]:\ You\ are\ right,\ I\ just\ noticed\ that\ myself\ too.\ Improved\ version:\n\n======\nif\ \{\[namespace\ which\ lassign\]\ eq\ \{\}\}\ \{\n\ \ \ proc\ lassign\ \{values\ args\}\ \{\n\ \ \ \ \ \ \ uplevel\ 1\ \[list\ foreach\ \$args\ \[linsert\ \$values\ end\ \{\}\]\ break\]\n\ \ \ \ \ \ \ lrange\ \$values\ \[llength\ \$args\]\ end\n\ \ \ \}\n\}\n======\n\n\[AMG\]:\ I\ prefer\ to\ use\ `\[catch\]`\ to\ check\ for\ a\ command's\ existence.\ \ Not\ only\nwill\ `\[catch\]`\ check\ if\ the\ command\ exists,\ but\ it\ can\ also\ check\ if\ it\nsupports\ an\ \[ensemble\]\ subcommand,\ an\ option,\ or\ some\ syntax.\ \ Plus\ it\ works\nwith\ `\[interp\ alias\]`,\ a\ clear\ advantage\ over\ `\[info\ commands\]`.\n\n======\nif\ \{\[catch\ \{lassign\ \{\}\}\]\}\ \{\n\ \ \ \ proc\ lassign\ \{list\ args\}\ \{\n\ \ \ \ proc\ lassign\ \{vals\ args\}\ \{\n\ \ \ \ \ \ \ \ lappend\ vals\ \"\"\n\ \ \ \ \ \ \ \ uplevel\ 1\ \[list\ foreach\ \$args\ \$vals\ break\]\n\ \ \ \ \ \ \ \ lrange\ \$vals\ \[llength\ \$args\]\ end-1\n\}\n======\n\n\n**\ Open\ Questions\ **\n\n\[JMN\]:\ tclX\ doesn't\ seem\ to\ use\ a\ separate\ namespace\ for\ its\ commands\ so\ if\ we\ndo\ a\ 'package\ require\ tclX'\ in\ Tcl\ 8.5+,\ which\ version\ of\ a\ command\ such\ as\nlassign\ will\ end\ up\ being\ used?\nlassign\ will\ end\ up\ being\ used?\ \ \n===} CALL {my revision lassign} CALL {::oo::Obj4121737 process revision/lassign} CALL {::oo::Obj4121735 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