Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/switch?V=95
QUERY_STRINGV=95
CONTENT_TYPE
DOCUMENT_URI/revision/switch
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.70.130.177
REMOTE_PORT26384
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR52.14.0.24
HTTP_CF_RAY8754557dbf522bff-ORD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTclaudebot
HTTP_CF_CONNECTING_IP52.14.0.24
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 switch '''\[http://www.tcl.tk/man/tcl/TclCmd/switch.htm%|%switch\]''',\ a\ \[Tcl\ Commands%|%built-in\]\ \[Tcl\]\ \[command\],\ uses\ patterns\ to\ select\ a\ script,\ and\ then\ \[eval%|%evaluates\]\ that\ script.\nCommands%|%built-in\]\ \[Tcl\]\ \[command\],\ evaluates\ one\ of\ several\ scripts,\ndepending\ on\ a\ given\ value.\n\n\n**\ Synopsis\ **\n**\ See\ Also\ **\n\n\ \ \ \[ranged\ switch\]:\ \ \ a\ range-aware\ lookalike\ to\ `switch`\n\n\ \ \ \[switch-regexp\]:\ \ \ `switch`\ with\ `\[regexp\]`\ variable\ capturing\n\n\n\n\n\ \ \ \ :\ \ \ '''switch'''\ ?''options''?\ ''string\ pattern\ body''\ ?''pattern\ body\ ...''?\ \n\ \ \ \ :\ \ \ '''switch'''\ ?''options''?\ ''string\ pattern\ body''\ ?''pattern\ body\ ...''?\ \n\n\ \ \ \ :\ \ \ '''switch'''\ ?''options''?\ ''string''\ \{''pattern\ body''\ ?''pattern\ body\ ...?\}\n\n\n\n**\ Documentation\ \ **\n\n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/switch.htm%|%official\ reference\]:\ \ \ \n\n\n\n**\ Description\ **\n\n`switch`\ supersedes\ `\[case\]`.\n\nWhen\ the\ ''pattern\ body''\ arguments\ are\ presented\ as\ separate\ arguments\ rather\nthan\ as\ one\ single\ argument,\ and\ ''string''\ starts\ with\ or\ could\ possibly\nis\ not\ incorrectly\ treated\ as\ an\ option.\ \n\n======\nswitch\ --\ \$foo\ \{...\}\ \ \;#\ robust\ for\ all\ values\ of\ foo\n======\n\nIn\ Tcl\ versions\ prior\ to\ \[Changes\ in\ Tcl/Tk\ 8.5%|%8.5\],\ \ `--`\ should\ be\ used\nin\ any\ case.\n\nWith\ exactly\ one\ argument,\ that\ argument\ is\ a\ \[dict%|%dictionary\]\ of\ patterns\nIn\ the\ form\ of\ `switch`\ where\ all\ patterns\ and\ bodies\ are\ in\ the\ last\ argument,\ this\ argument\ is\ technically\ a\ string\ which\ will\ be\ parsed\ by\ Tcl\ as\ a\ `\[list\]`.\ The\ rules\ for\ how\ a\ string\ is\ parsed\ as\ a\ list\ can\ be\ found\ on\ the\ `\[list\]`\ page.\ \n`switch`\ only\ performs\ string\ comparison,\ so\ it\ isn't\ ideal\ for\ numeric\ncomparison.\ \ That\ said,\ `switch`\ almost\ always\ \"just\ works\"\ for\ the\ numeric\ncases\ because\ string\ comparison\ is\ a\ natural\ surrogate\ for\ equality\ testing\ of\nintegers,\ and\ the\ cost\ of\ creating\ a\ string\ representation\ of\ an\ integer\ is\nusually\ nominal\ in\ the\ grand\ scheme\ of\ a\ Tcl\ script.\ \ `\[if\]`\ is\ always\navailable\ for\ numeric\ or\ other\ more\ complex\ tests.\n\n\n\n**\ Examples\ **\n\nCoding\ style\ for\ switch\ is\ tricky.\ \ Recently\ on\ \[comp.lang.tcl\]\ there\ was\nan\ exchange\ about\ getting\ `switch`\ to\ work\ right.\ \ The\ user\ had\ originally\ntyped:\n\n======\nswitch\ \$::errorCode\ \{\n\ \ \ \ \$NOTFOUND\ \{\n\ \ \ \ \ \ \ \ puts\ \{page\ not\ found\}\n\ \ \ \ \}\n\ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ puts\ \"Program\ encountered\ code\ \$::errorCode\"\n\ \ \ \ \ \ \ \ break\n\ \ \ \ \}\n\}\n======\n\nand\ was\ frustrated\ because\ the\ application\ kept\ taking\ the\ default\ branch.\n\n\[PYK\]\ 2014-05-29:\ \[scripted\ list\]\ can\ make\ this\ syntax\ work,\ and\ even\ allows\ comments:\n\[PYK\]\ 2014-05-29:\ \[scripted\ list\]\ can\ make\ this\ syntax\ work:\n======\nswitch\ \$::errorCode\ \[sl\ \{\n\ \ \ \ #todo:\ offer\ a\ list\ of\ similar\ pages\n\ \ \ \ \ \ \ \ puts\ \{page\ not\ found\}\n\ \ \ \ \}\n\ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ puts\ \"Program\ encountered\ code\ \$::errorCode\"\n\ \ \ \ \ \ \ \ break\n\ \ \ \ \}\n\}\]\n======\n\nA\ well-known\ Tcl\ pundit\ suggested:\n\n======\nswitch\ \$::errorCode\ \"\n\ \ \ \ \$NOTFOUND\ \{\n\ \ \ \ \ \ \ \ puts\ \"page\ not\ found\ \"\n\ \ \ \ \}\n\ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ puts\ \"Program\ encountered\ code\ \$::errorCode\"\n\ \ \ \ \}\n\"\n======\nso\ that\ Tcl\ had\ a\ chance\ to\ substitue\ `\$NOTFOUND`.\n\n''\[AMG\]:\ The\ quotes\ don't\ match\ up\ the\ way\ you\ expect.\ \ This\ is\ because\ braces\ inside\ \"quoted\"\ words\ don't\ have\ any\ special\ power.\ \ the\ second\ argument\ to\ switch\ starts\ with\ a\ line\ break,\ ends\ with\ the\ space\ following\ puts,\ and\ has\ the\ word\ \"page\"\ illegally\ appended\ to\ it,\ resulting\ in\ an\ \"extra\ characters\ after\ close-quote\"\ error.''\n\nHowever,\ the\ follow\ up,\ by\ \[Ken\ Jones\]\ said\ it\ best:\n\nyou\ don't\ want\ that\ (unless\ you're\ doing\ some\ very,\ very,\ very\ntricky\ stuff).\ Quoting\ switch's\ pattern/action\ block\ with\ `\"\"`\ allows\nsubstitutions\ within\ the\ entire\ argument.\ So,\ yes\ you\ get\ `\$URL_NOT_FOUND`\nsubstituted.\ But\ you\ also\ get\ the\ contents\ of\ the\ actions\nsubstituted\ before\ switch\ even\ gets\ called.\n\n\[lexfiend\]:\ I\ think\ the\ following\ example\ illustrates\ Ken's\ point\ better:\n\n======\n#\ GOTCHA\ -\ You're\ dead\ no\ matter\ what\ you\ do\nset\ TriggerBomb\ 0\nset\ DefuseBomb\ 1\nset\ WaitAMinuteWhileIThinkThisThrough\ 2\nset\ Action\ \$WaitAMinuteWhileIThinkThisThrough\ninterp\ alias\ \{\}\ SendToBomb\ \{\}\ puts\nswitch\ \$Action\ \"\n\ \ \ \ \$TriggerBomb\ \{\n\ \ \ \ \ \ \ \ set\ result\ \[SendToBomb\ boom\]\n\ \ \ \ \}\n\ \ \ \ \$DefuseBomb\ \{\n\ \ \ \ \ \ \ \ set\ result\ \[SendToBomb\ shutdown\]\n\ \ \ \ \}\n\"\n======\n\nInstead,\ we\ want\ the\ syntax\ of\ `switch`\ where\ the\ \nInstead,\ we\ the\ syntax\ of\ `switch`\ where\ the\ \nrather\ than\ a\ single\ list\ of\ alternating\ pattern/body\ items.\ Here's\ a\ncorrectly\ working\ example\ of\ the\ above\ code:\n\n======\nset\ NOTFOUND\ value\nset\ errorCode\ nonsense\n\nswitch\ --\ \$::errorCode\ \\\n\ \ \ \ \$NOTFOUND\ \{\n\ \ \ \ \ \ \ \ puts\ \{page\ not\ found\}\n\ \ \ \ \}\ \\\n\ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ puts\ \"Program\ encountered\ code\ \$::errorCode\"\n\ \ \ \ \}\n======\n\n\[KBK\]:\ I\ dislike\ both\ of\ these.\ \ I\ tend\ to\ think\ of\ a\ switch\ as\ a\nselection\ among\ fixed\ alternatives,\ and\ substitution\ in\ the\ cases\nconfuses\ me.\ \ I'd\ have\ just\ written:\n\n======\nif\ \{\$::errorcode\ eq\ \$NOTFOUND\}\ \{\n\ \ \ \ puts\ \{page\ not\ found\}\n\}\ else\ \{\n\ \ \ \ puts\ \"Program\ encountered\ code\ \$::errorCode\"\n\}\n======\n\n\[RHS\]:\ I\ find\ that\ when\ I\ need\ substitution\ for\ switch\ values,\ formatting\ it\ like\ the\ following\ looks\ cleaner:\n\n======\nswitch\ --\ \$::errorCode\ \$NOTFOUND\ \{\n\ \ \ \ puts\ \{page\ not\ found\}\n\}\ \$value1\ \{\n\ \ \ puts\ blah\n\}\ default\ \{\n\ \ \ puts\ \"Program\ encountered\ code\ \$::errorCode\"\n\}\n======\n\n\[DKF\]:\ With\ 8.6,\ I'd\ be\ using\ `\[try\]`\ for\ this\ particular\ problem\ instead\ of\ using\ `switch`\ to\ pick\ through\ \[errorCode%|%\$::errorCode\]\ after\ `\[catch\]`\ returned,\ but\ YMMV.\n\n----\n\n\[LV\]:\ The\ above\ sample\ was,\ of\ course,\ intended\ to\ be\ brief,\ and\ didn't\ show\ the\ other\ several\ dozen\ switch\ cases.\ \ For\ a\ single\ comparison,\ I\ agree\ with\ \[KBK\].\ \ But\ if\ I\ have\ more\ than\ one\ or\ two\ of\ these\ types\ of\ comparisons,\ then\ I\ know\ ''I''\ prefer\ a\ switch.\n\n----\n\nHow's\ this\ for\ a\ silly\ compromise.\nNicely\ aligns\ the\ dispatch\ conditions\ and\ removes\ the\ confusing\ barrage\ of\ backslashes.\n\n======\nif\ 0\ \{\n\}\ elseif\ \{\$state\ eq\ \$INIT_STATE\}\ \{\n\ \ \ puts\ init\n\}\ elseif\ \{\$state\ eq\ \$CLEANING_STATE\}\ \{\n\ \ \ puts\ cleaning\n\}\ elseif\ \{\$state\ eq\ \$DONE_STATE\}\ \{\n\ \ \ puts\ done\n\}\n======\n\n----\n\nThe\ silliness\ continues...\ this\ actually\ works\ though\ I'm\ not\ sure\ of\ the\ side\ effects.\n\n======\nproc\ dispatch\ \{thevar\ args\}\ \{\n\ \ \ \ set\ pass1\ \[uplevel\ subst\ \$args\]\n\ \ \ \ set\ pass2\ \"switch\ \\\$\$thevar\ \\\{\ \$pass1\ \\\}\"\n\ \ \ \ uplevel\ \$pass2\n\}\n\nset\ INIT_STATE\ init\nset\ CLEANING_STATE\ cleaning\nset\ DONE_STATE\ done\n\nset\ state\ \$INIT_STATE\n\ndispatch\ state\ \{\n\ \ \ \ \$INIT_STATE\ \{\n\ \ \ \ \ \ \ \ puts\ init\n\ \ \ \ \ \ \ \ set\ nextstate\ \$DONE_STATE\n\ \ \ \ \}\n\ \ \ \ \$CLEANING_STATE\ \{\n\ \ \ \ \ \ \ \ puts\ cleaning\n\ \ \ \ \}\n\ \ \ \ \$DONE_STATE\ \{\n\ \ \ \ \ \ \ \ puts\ done\n\ \ \ \ \}\n\ \ \ \ default\ \{\n\ \ \ \ \}\n\}\nputs\ \"next\ state\ \$nextstate\"\n======\n\n\[PYK\]\ 2014-05-30:\ The\ code\ above\ is\ not\ robust\ due\ to\ the\ use\ of\ `\[subst\]`\n.\n\n\n======\ndict\ set\ body\ \[list\ \$INIT_STATE\]\ \{\n\n\[PZ\]:\ Using\ `default`\ alternative\ with\ `-regexp`:\n\n======\nset\ a\ x\nswitch\ -regexp\ --\ \$a\ \{\n\ \ \ \ y\ \{\n\ \ \ \ \ \ \ \ puts\ y\n\ \ \ \ \}\n\ \ \ \ \{\}\ \{\n\ \ \ \ \ \ \ \ puts\ z\n\ \ \ \ \}\n\ \ \ \ \n\ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ puts\ \$a\n\ \ \ \ \}\n\}\n======\n\nreturns:\n\n======none\nz\n======\n\nThis\ is\ because\ `\{\}`\ matches\ the\ \[empty\ string\]\ that\ implicitly\ exists\ at\ both\nends\ of\ a\ string\ and\ between\ every\ character\ in\ a\ string.\n\n\n\n**\ Match\ Abbreviations\ **\n\nWith\ `switch\ -regexp`,\ you\ can\ specify\ abbreviations\ of\ a\ flag\ to\ be\ switched\ on\ like\ this:\n\n======\nswitch\ -regexp\ --\ \$variable\ \{\n\ \ \ \ -h(e(lp?)?)?\ \ \ \ \ \ \ \ \ \ \ \ \ \{...\}\n\ \ \ \ -h|-he|-hel|-help|-ayuda\ \{...\}\n\ \ \ \ -\\\\?\ \{...\}\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \;\$\ Match\ -?\ flag\n\ \ \ \ \{(?x)\ -\ |\ -h\ |\ -help\}\ \{do\ stuff\}\ \;#\ extended\ RE\ syntax\n\}\n======\n\nwithout\ the\ -regexp,\ you\ would\ write:\n\n======\nswitch\ --\ \$variable\ \{\n\ \ \ \ -h\ -\ -he\ -\ -hel\ -\ -help\ \{...\}\n\}\n======\n\n----\n\n\[LV\]:\ I\ really\ find\ using\ `-`\ as\ a\ separator\ between\ switch\ case\ alternatives\ to\ be\ counter-intuitive\ .\nnormally\ one\ uses\ `|`\ for\ that\ sort\ of\ thing.\n\n\[glennj\]:\ It\ might\ be\ clearer\ if\ more\ whitespace\ is\ used:\n\n======\nswitch\ --\ \$variable\ \{\n\ \ \ \ -h\ \ \ \ -\ \n\ \ \ \ -he\ \ \ -\ \n\ \ \ \ -hel\ \ -\ \n\ \ \ \ -help\ \{...\}\n\}\n======\n\n\n\n**\ `-regexp`\ and\ backrefs\ **\n\n\[SB\]\ 2003-05-21:\ When\ I\ use\ `switch\ -regexp`,\ Tcl\ already\ use\ regexp\ once\ to\ enter\ the\ proper\ clause.\ How\ can\ the\ match\ pattern\ be\ accessed\ from\ within\ the\ clause,\ if\ possible,\ and\ is\ switch\ `-regexp`\ able\ to\ use\ ()\ match\ variables?\ I\ think\ perl\ store\ the\ regexp\ matches\ in\ global\ variables\ \$1\ ..\ \$9\ \n(The\ following\ example\ is\ not\ valid,\ only\ for\ illustrating\ question)\n\n======\nswitch\ -regexp\ --\ \$somevar\ \{\n\ \ \ \ \{^(\\S+)\\s+(\\S+)\}\ \{puts\ \"You\ hit\ matches\ \$1\ and\ \$2\"\}\n\ \ \ \ \{^(\\d+)\\s+(\\d+)\}\ \{puts\ \"You\ hit\ number\ matches\ \$1\ and\ \$2\"\}\n\}\n======\n\n\[KBK\]\ -\ You\ can't.\ \ However,\ that\ form\ of\ `switch`\ is\ no\ slower\ than\ the\ corresponding\ `\[if\]\ ...\ \[elseif\]`,\ \nso\ you\ can\ do:\n\n======\nif\ \{\[regexp\ \{^(\\S+)\\s+(\\S+)\$\}\ \$somevar\ ->\ part1\ part2\]\}\ \{\n\ \ \ \ \ puts\ \"You\ hit\ matches\ \$part1\ and\ \$part2\"\n\}\ elseif\ \{\[regexp\ \{^(\\d+)\\s+(\\d+)\}\ ->\ part1\ part2\]\}\ \{\n\ \ \ \ \ puts\ \"You\ hit\ number\ matches\ \$part1\ and\ \$part2\"\n\}\n======\n\n\[hkoba\]\ 2005-03-18:\ Hmm,\ how\ about\ \[switch-regexp\]?\n\n\[DKF\]:\ With\ 8.5,\ you\ can\ tell\ `switch`\ to\ store\ the\ re-matched\ values\ instead\ of\ discarding\ them.\n\n\n\n**\ Delimiting\ the\ Options\ **\n\n\[LES\]:\ So,\ if\ it\ is\ so\ good\ a\ practice\ ALWAYS\ to\ call\ switch\ as\ \"switch\ --\"\ (the\ switch\ to\ end\ all\ switches),\ why\ can't\ the\ core\ code\ already\ cope\ with\ that?\n\n\[MG\]:\ That's\ not\ really\ specific\ to\ switch\ -\ it's\ really\ good\ practice\ with\ ''all''\ commands\ that\ take\ ''-something''\ args,\ and\ show\ the\ end\ of\ those\ with\ '--',\ to\ include\ the\ --.\ And\ I\ think\ the\ reason\ the\ core\ can't\ handle\ is\ that\ sometimes\ you\ may\ actually\ want\ the\ behaviour\ that\ occurs\ when\ you\ don't\ give\ `--`.\n\n\[LV\]:\ because\ technically\ the\ rule\ isn't\ \"ALWAYS\ call\ switch\ as\ `switch\ --`\".\nThe\ rule\ is\ \"ALWAYS\ call\ switch\ with\ `--`\ after\ the\ last\ of\ the\ switch\nflags\".\ \ If\ you\ are\ using\ switch\ without\ a\ flag,\ then\ it\ would\ be\ \"`switch\ --`\".\nThink\ of\ code\ like\ this:\n\n======\nset\ arg\ \{something\ entered\ by\ the\ user\}\nswitch\ \$arg\ \{\n\ \ \ \ --first_thing\ \{do\ something\}\n\ \ \ \ --second_thing\ \{do\ something\ else\}\n\ \ \ \ default\ \{do\ the\ last\ thing\}\n\}\n======\n\nNow,\ if\ the\ user\ happens\ to\ type\ in\ `--first_thing`,\ the\ program\nraises\ the\ error:\n\n======none\nbad\ option\ \"--first_thing\":\ must\ be\ -exact,\ -glob,\ -regexp,\ or\ --\n======\n\nbecause\ there\ was\ no\ `--`\ between\ the\ switch\ and\ the\ variable\ being\nexamined.\ Not\ only\ that,\ but\ if\ the\ user\ happens\ to\ type\ in\ `-exact`,\nthe\ error\ raised\ is:\n\n======none\nwrong\ #\ args:\ should\ be\ \"switch\ ?switches?\ string\ pattern\ body\ ...\ ?default\ body?\"\n======\n\nbecause\ of\ the\ missing\ `--`.\ \ Two\ potential\ error\ situations\ -\ and\nthe\ core\ switch\ command\ can't\ handle\ either,\ because\ by\ the\ time\ it\ is\ncalled,\ any\ information\ about\ where\ the\ first\ argument\ is\ already\ gone.\n\n\[RS\]:\ The\ need\ for\ `--`\ seems\ to\ exist\ only\ for\ ''switch''.\ Other\ commands\ don't\ get\ confused\ by\ parameters\ that\ look\ like\ switches\ but\ aren't:\n\n======none\n%\ lsearch\ -foo\ -bar\n-1\n======\n\nThen\ again,\ `\[regexp\]`\ has\ the\ same\ need\ for\ `--`:\n\n======none\n%\ regexp\ -foo\ -bar\nbad\ switch\ \"-foo\":\ must\ be\ -all,\ -about,\ -indices,\ -inline,\ -expanded,\ -line,\ -linestop,\ -lineanchor,\ -nocase,\ -start,\ or\ --\n======\n\nYax:\ `\[lsearch\]`\ assumes\ the\ form\ of\ arguments\ by\ the\ argument\ count,\ and\ its\ quite\ probable\ that\ all\ commands\ that\ take\ fixed\ args\ after\ options\ do.\ Any\ commands\ (such\ as\ regexp)\ that\ can\ take\ an\ arbitrarily\ varying\ number\ of\ args\ and\ have\ switches\ probably\ also\ suffer\ this\ issue.\n\n\n\n**\ `\[break\]`\ **\n\n\[LV\]:\ When\ I\ try\ to\ use\ a\ break\ inside\ a\ `switch`\ script,\ I\ get\ the\ error\n\n======none\ninvoked\ \"break\"\ outside\ of\ a\ loop\n\ \ \ \ while\ executing\n\"switch\ \n======\n\nIs\ there\ an\ equivalent\ to\ `\[break\]`\ for\ switch?\n\n\[YSK\]:\ How\ about\ trapping\ `switch`\ in\ `\[while\]\ 1`:\n\n======\nwhile\ 1\ \{\n\ \ \ \ switch\ \$cond\ \{\n\ \ \ \ \ \ \ \ case1\ \{\n\ \ \ \ \ \ \ \ \ \ \ if\ \{\$fault\}\ \{puts\ NG\;\ break\}\n\ \ \ \ \ \ \ \ \ \ \ puts\ OK\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ \ \ \ puts\ OK\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ break\n\}\n======\n\n\[MG\]\ Hrm,\ I\ thought\ `\[break\]`\ worked\ in\ switches,\ too.\ But\ it\ seems\ that\ Tcl's\ \[switch\]\ doesn't\ fall\ through\ by\ default:\n\n======\nswitch\ -glob\ --\ foo\ \\\n\ \ \ \ f*\ \{puts\ match1\}\ \\\n\ \ \ \ *o*\ \{puts\ match2\}\ \\\n\ \ \ \ default\ \{puts\ nomatch\}\n======\n\nOnly\ the\ \"match1\"\ is\ shown,\ and\ then\ it\ stops,\ there's\ no\ \"match2\".\ So\ no\ `\[break\]`\ is\ needed,\ it'll\ stop\ when\ a\ match\ is\ found\ anyway.\ That\ means,\ in\ something\ like\n\n======\nswitch\ -glob\ --\ \$string\ \\\n\ \ \ \ f*\ \{puts\ foo\}\n\ \ \ \ b*\ \{puts\ bar\}\n\ \ \ \ *z*\ \{#\ do\ nothing\}\n\ \ \ \ default\ \{puts\ \{something\ else\}\}\n======\n\nthe\ \"#\ do\ nothing\"\ case\ has\ the\ same\ effect\ as\ a\ `\[break\]`\ in\ a\ switch\ in\ \[C\]\ would.\n\n\[LV\]\ without\ `\[break\]`,\ it\ means\ that\ one\ has\ to\ code\ carefully\ to\ avoid\ the\ cases\ where\ one\ normally\ would\ use\ it.\ For\ instance,\ in\ other\ languages,\ one\ might\ code\n\n======\nswitch\ \$variable\ \{\ncase1\ \{do\ this\;\ break\}\ncase2\ \{do\ that\;\ break\}\ncase3\ \{if\ today\ is\ Monday,\ do\ the\ other\;\ break\;\ if\ tomorrow\ is\ the\ 14th,\ do\ something\ else\;\ break\;\}\ndefault\ \{if\ an\ error,\ say\ so\ and\ break\;\ do\ the\ last\ thing,\ break\;\}\n======\n\nIn\ Tcl,\ one\ would\ recode\ using\ `\[if%|%else\]`\ or\ `\[if%|%elseif\]`\ or\ fiddling\nwith\ state\ variables,\ etc.\ to\ accomplish\ the\ same\ thing.\n\n\n\n**\ Using\ the\ Return\ Value\ of\ `switch`\ **\n\n\[RS\]\ 2005-05-30:\ Unlike\ in\ \[C\],\ \[Tcl\]'s\ `\[switch\]`\ returns\ its\ last\ evaluated\ result,\ \nso\ it\ can\ be\ used\ as\ a\ function.\ Given\ this\ simple\ \[identity\ function%|%identity\]\n\n======\nproc\ is\ x\ \{set\ x\}\n======\n\nwe\ can\ code\ the\ following\ \"digit\ classifier\"\ quite\ elegantly:\n\n======\nforeach\ num\ \{0\ 1\ 2\ 3\ 4\ 5\ 6\ 7\ 8\ 9\}\ \{\n\ \ \ \ set\ type\ \[switch\ --\ \$num\ \{\n\ \ \ \ \ \ \ \ 1\ -\ 9\ \ \ \ \ \ \ \ \ \{is\ odd\}\n\ \ \ \ \ \ \ \ 2\ -\ 3\ -\ 5\ -\ 7\ \{is\ prime\}\n\ \ \ \ \ \ \ \ 0\ -\ 4\ -\ 6\ -\ 8\ \{is\ even\}\n\ \ \ \ \}\]\n\ \ \ \ puts\ \"\$num\ is\ \$type\"\n\}\n======\n\nwhich\ displays\n\n======none\n0\ is\ even\n1\ is\ odd\n2\ is\ prime\n3\ is\ prime\n4\ is\ even\n5\ is\ prime\n6\ is\ even\n7\ is\ prime\n8\ is\ even\n9\ is\ odd\n======\n\n\[AMG\]:\ See\ \[identity\ function\ \]\ for\ more\ discussion\ of\ this\ pattern.\ \ The\ simplest\ way\ to\ do\ it\ is\ with\n\[AMG\]:\ See\ \[identify\ function\ \]\ for\ more\ discussion\ of\ this\ pattern.\ \ The\ simplest\ way\ to\ do\ it\ is\ with\n\n\n**\ History\ **\n\nFirst\ announced\ by\ \[JO\]\ for\ Tcl\ 7.0\ in\ \[https://groups.google.com/d/msg/comp.lang.tcl/u1pATk0ytWM/8uStOsyBrLYJ%|%Advice\ wanted:\ \"case\"\ command\ and\ regexps\],\ \[comp.lang.tcl\],1993-06-05\n\n\n\n**\ Compilation\ Notes\ **\n\n\[DKF\]:\ In\ Tcl\ \[Changes\ in\ Tcl/Tk\ 8.5%|%8.5\],\ `switch`\ is\ \[bytecode%|%byte-compiled\]\ if\ reasonably\ possible.\ The\ \"reasonably\ possible\"\ part\ means\ that\ you\ do\ have\ to\ be\ doing\ either\ '''`-exact`'''\ or\ '''`-glob`'''\ matching,\ and\ the\ bodies\ of\ the\ arms\ have\ to\ be\ compilable\ (as\ usual).\ With\ '''`-regexp`'''\ matching,\ that\ always\ goes\ to\ the\ \"interpreted\"\ version\ (though\ by\ compensation,\ there\ are\ some\ other\ new\ goodies\ (see\ `-matchvar`\ and\ `-indexvar`,\ for\ instance)\ available).\n\nIn\ most\ cases,\ the\ switch\ is\ compiled\ to\ (effectively)\ a\ sequence\ of\ `\[if\]`\ commands.\ However,\ in\ some\ special\ cases,\ i.e.\ '''`-exact`'''\ matching\ of\ constant\ terms,\ a\ jump\ table\ is\ built\ instead,\ which\ is\ considerably\ more\ efficient,\ especially\ for\ terms\ other\ than\ the\ first\ one.\n\n\n**\ Bug:\ `-indexvar`\ Indexes\ Off\ By\ One\ **\n**\ Bug:\ `-indexvar`\ indexess\ off\ by\ one\ **\n\[TJE\]:\ Why\ are\ the\ ranges\ placed\ in\ a\ `switch`\ statement's\ `-indexvar`\ target\ inclusive\ of\ the\ character\ AFTER\ the\ match?\ \ This\ differs\ from\ the\ behavior\ of\ regexp's\ `-indices`\ option,\ which\ seems\ quite\ odd\ to\ me.\ \ For\ example:\n\n======\n%\ set\ line\ \{foo\ bar\}\nfoo\ bar\n%\ regexp\ -inline\ -indices\ foo\ \$line\n\{0\ 2\}\n%\ switch\ -regexp\ -indexvar\ index\ --\ \$line\ foo\ \{set\ index\}\n\{0\ 3\}\n======\n\nDoesn't\ that\ seem\ odd?\ \ 'Tis\ not\ at\ all\ what\ I'd\ expected...\n\n\[PYK\]\ 2014-05-30:\ If\ this\ really\ happened,\ it\ must\ have\ been\ a\ bug\ in\ some\nversion\ of\ Tcl.\ The\ current\ version\ behaves\ as\ expected,\ returnint\ `\{0\ 2\}`.\n\n\n\n**\ Comments\ in\ Switch\ Statements\ **\n\nComments\ can\ be\ placed\ in\ the\ bodies\ of\ `switch`:\n\n======\nswitch\ \$x\ \{\n\ \ \ \ 1\ \{\n\ \ \ \ \ \ \ \ #comment\ goes\ here\n\ \ \ \ \ \ \ \ ...\n\ \ \ \ \}\n\ \ \ \ 2\ \{\n\ \ \ \ \ \ \ \ #comment\ goes\ here\n\ \ \ \ \ \ \ \ ...\n\ \ \ \ \}\n\}\n======\n\n----\n\n\[Wookie\]:\ I\ have\ a\ large\ switch\ and\ wanted\ comments\ for\ blocks\ of\ statements\ e.g.\n\n======\nswitch\ -exact\ --\ \$test\ \{\n\ \ \ \ #\ Comment\ for\ first\ block\n\ \ \ \ Test1\ \{do\ stuff...\}\n\ \ \ \ Test2\ \{do\ stuff...\}\n\ \ \n\ \ \ \ #\ Comment\ for\ second\ block\n\ \ \ \ Test3\ \{do\ stuff...\}\n\ \ \ \ Test4\ \{do\ stuff...\}\n\ \ \n\ \ \ \ #\ Comment\ for\ default\n\ \ \ \ NONE\ -\n\ \ \ \ default\ \{SomeCleanUpProc...\}\n\}\n======\n\nYou\ get\ the\ error:\n\ \ \ \"extra\ switch\ pattern\ with\ no\ body,\ this\ may\ be\ due\ to\ a\ comment\ incorrectly\ placed\ outside\ of\ a\ switch\ body\ -\ see\ the\ \"switch\"\ documentation\"\n\nAs\ Tcl\ `switch`\ statements\ don't\ seem\ to\ care\ that\ there\ are\ multiple\ definitions\ of\ a\ statement,\ I\ rewrote\ the\ code\ as:\ \n======\nswitch\ -exact\ --\ \$test\ \{\n\ \ \ \ COMMENT\ \{#\ Comment\ for\ first\ block\}\n\ \ \ \ Test1\ \{do\ stuff...\}\n\ \ \ \ Test2\ \{do\ stuff...\}\n\ \ \n\ \ \ \ COMMENT\ \{#\ Comment\ for\ second\ block\}\n\ \ \ \ Test3\ \{do\ stuff...\}\n\ \ \ \ Test4\ \{do\ stuff...\}\n\ \ \n\ \ \ \ COMMENT\ \{#\ Comment\ for\ default\}\n\ \ \ \ NONE\ -\n\ \ \ \ default\ \{clean\ up\ stuff...\}\n\}\ \n======\n\nIf\ COMMENT\ is\ passed\ in\ it\ simply\ calls\ the\ first\ COMMENT\ in\ the\ switch,\ which\ does\ nothing.\ If\ COMMENT\ is\ a\ valid\ statement\ it\ would\ have\ to\ be\ dealt\ with\ in\ the\ first\ block.\n\n\[PYK\]\ 2014-09-17:\ \ A\ \[scripted\ list\]\ is\ another\ option.\n\n\n\n\[AMG\]:\ Unlike\ \[C\]'s\ switch,\ which\ does\ numeric\ comparisons,\ \[Tcl\]\ switch\ performs\ `\[string\]`\ comparisons.\ \ This\ can\ make\ a\ big\ difference\ in\ your\ program\ if\ you\ are\ dealing\ with\ numbers\ that\ are\ formatted\ in\ different\ ways.\n\n======\nset\ number\ 0x5\nswitch\ --\ \$number\ \{\n\ \ \ \ 5\ \ \ \ \ \ \ \{puts\ five!\}\n\ \ \ \ default\ \{puts\ unknown\}\n\}\n======\n\nYou\ may\ instead\ consider\ a\ long\ `\[if\]`/`\[elseif\]`\ chain,\ but\ maybe\ this\ won't\ \[bytecode\]\ as\ well.\ \ Alternately,\ force\ the\ \[format%|%formatting\]\ to\ be\ consistent:\n\n======\nset\ number\ 0x5\nswitch\ --\ \[format\ %d\ \$number\]\ \{\n5\ \ \ \ \ \ \ \{puts\ five!\}\ndefault\ \{puts\ unknown\}\n\}\n======\n\n\n\n**\ Performance\ of\ `-regexp`\ **\n**\ Performance\ of\ `-regexp`\ **\[DrASK\]:\n\[DrASK\]:\n\n======\nswitch\ -exact\ --\ \$value\ \{\n\ \ \ \ a\ -\ b\ -\ c\ match\n\}\n\nswitch\ -regexp\ --\ \$value\ \{\n\ \ \ \ \[abc\]\ match\n\}\n======\n\n\[Lars\ H\]:\ Comments\ by\ \[DKF\]\ above\ suggest\ that\ the\ answer\ should\ be\ yes,\ but\ why\ not\ check\ for\ yourself?\ `\[time\]`\ it!\n\nAlso\ note\ that\ the\ two\ \[switch\]es\ aren't\ exactly\ equivalent:\ the\ latter\ checks\ whether\ the\ \$value\ ''contains''\ a,\ b,\ or\ c,\ not\ whether\ it\ ''is''.\ To\ do\ that,\ you\ need\ to\ change\ the\ regexp\ pattern\ as\ follows:\n\n======\nswitch\ -regexp\ --\ \$value\ \{\n\ \ \ ^\[abc\]\$\ \{match\}\n\}\n======\n\n\[DrASK\]:\ Yeah,\ I\ failed\ to\ mention\ that\ `\$value`\ is\ known\ to\ be\ a\ single\ character.\ Thanks.\ Here\ is\ the\ test\ and\ the\ results:\n\n======\nproc\ exact\ value\ \{\n\ \ \ \ switch\ -exact\ --\ \$value\ \{\n\ \ \ \ \ \ \ \ a\ -\ b\ -\ c\ \{return\ true\}\n\ \ \ \ \ \ \ \ default\ \{return\ false\}\n\ \ \ \ \}\n\}\n\nproc\ re\ value\ \{\n\ \ \ \ switch\ -regexp\ --\ \$value\ \{\n\ \ \ \ \ \ \ \ \[abc\]\ \{return\ true\}\n\ \ \ \ \ \ \ \ default\ \{return\ false\}\n\ \ \ \ \}\n\}\n\nproc\ first\ value\ \{\n\ \ \ \ return\ \[expr\ \{\[string\ first\ \$value\ abc\]\ !=\ -1\}\]\n\}\n\nproc\ multi\ \{type\ value\}\ \{\n\ \ \ \ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100\}\ \{incr\ i\}\ \{\n\ \ \ \ \ \ \ \ \$type\ \$value\n\ \ \ \ \}\n\}\n\nforeach\ type\ \{exact\ re\ first\}\ \{\n\ \ \ \ foreach\ value\ \{a\ b\ c\ d\}\ \{\n\ \ \ \ \ \ \ \ puts\ \"\$type\ \$value\ \[errortime\ \{multi\ \$type\ \$value\}\ 10000\ 100\]\"\n\ \ \ \ \}\n\}\n======\n======none\nexact\ a\ 66\ +/-\ 0\ microseconds\ per\ iteration\nexact\ b\ 67\ +/-\ 0\ microseconds\ per\ iteration\nexact\ c\ 67\ +/-\ 0\ microseconds\ per\ iteration\nexact\ d\ 66\ +/-\ 0\ microseconds\ per\ iteration\nregexp\ a\ 151\ +/-\ 0\ microseconds\ per\ iteration\nregexp\ b\ 140\ +/-\ 0\ microseconds\ per\ iteration\nregexp\ c\ 142\ +/-\ 0\ microseconds\ per\ iteration\nregexp\ d\ 121\ +/-\ 0\ microseconds\ per\ iteration\nfirst\ a\ 71\ +/-\ 0\ microseconds\ per\ iteration\nfirst\ b\ 71\ +/-\ 0\ microseconds\ per\ iteration\nfirst\ c\ 71\ +/-\ 0\ microseconds\ per\ iteration\nfirst\ d\ 70\ +/-\ 0\ microseconds\ per\ iteration\n======\n\nIt's\ interesting\ to\ note\ the\ dropoff\ when\ `\[regexp\]`\ hit\ the\ default\ case.\ But\ `-regexp`\ is\ clearly\ is\ 2-2.5x\ slower.\ I\ used\ \[MAK\]'s\ \[How\ to\ Measure\ Performance%|%errortime\ proc\]\ for\ timing.\n\n\[ferrieux\]:\ Indeed,\ timing\ shows\ that\ the\ jump\ table\ is\ roughly\ 3x\ faster\ than\ `if..elseif..elseif`,\ which\ is\ itself\ 1.25x\ faster\ than\ `\[regexp\]`.\ Notice\ that\ the\ `\[regexp\]`\ compilation\ overhead\ is\ not\ in\ the\ picture,\ since\ it\ is\ cached.\ Not\ sure\ whether\ we\ should\ worry\ about\ the\ 1.25...\n\n\n**\ An\ Implementation\ in\ Tcl\ **\n\n\[rwm\]:\ I\ recently\ needed\ to\ run\ some\ \[Changes\ in\ Tcl/Tk\ 8.5%|%8.5\]\ code\ in\ \[Changes\ in\ Tcl/Tk\ 8.4%|%8.4\].\ \ I\ wrote\ the\ following\ code\ to\ mimic\ the\ 8.5\ switch\ in\ 8.4.\ (I\ looked\ for\ but\ could\ not\ find\ a\ compatibility\ library...)\ Note\ the\ many\ errors\ for\ cases\ that\ I\ did\ not\ need.\ \ Maybe\ someone\ else\ will\ cover\ fix/post\ those\ \;)\ \ Feel\ free\ to\ edit/move\ this\ as\ appropriate.\n\n======\nproc\ switch_8.5\ args\}\ \{\n\ \ \ \ ##\ this\ is\ an\ 8.4\ version\ of\ the\ 8.5\ switch\ (incomplete)\n\ \ \ \ if\ \{\[llength\ \$args\]\ <\ 2\}\ \{\n\ \ \ \ \ \ \ \ error\ \"usage:\ switch\ ?options?\ string\ \{pattern\ body\ ?pattern\ body\ ...?\}\"\n\ \ \ \ \}\n\ \ \ \ set\ type\ exact\n\ \ \ \ while\ \{\[string\ match\ -*\ \[lindex\ \$args\ 0\]\]\}\ \{\n\ \ \ \ \ \ \ \ set\ option\ \[lindex\ \$args\ 0\]\n\ \ \ \ \ \ \ \ set\ args\ \[lrange\ \$args\ 1\ end\]\n\ \ \ \ \ \ \ \ switch\ --\ \$option\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ -exact\ \ \ \ \{set\ type\ exact\}\n\ \ \ \ \ \ \ \ \ \ \ \ -nocase\ \ \ \{set\ type\ nocase\}\n\ \ \ \ \ \ \ \ \ \ \ \ -glob\ \ \ \ \ \{set\ type\ glob\}\n\ \ \ \ \ \ \ \ \ \ \ \ -regexp\ \ \ \{set\ type\ regexp\}\n\ \ \ \ \ \ \ \ \ \ \ \ -matchvar\ \{set\ matchvar\ \[lindex\ \$args\ 0\]\;\ set\ args\ \[lrange\ \$args\ 1\ end\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ -indexvar\ \{error\ \"unimplemented\"\}\n\ \ \ \ \ \ \ \ \ \ \ \ --\ break\n\ \ \ \ \ \ \ \ \ \ \ \ default\ \{error\ \"bad\ switch\ option=\$option\"\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ set\ string\ \[lindex\ \$args\ 0\]\n\ \ \ \ if\ \{\[llength\ \$args\]\ ==\ 2\}\ \{\n\ \ \ \ \ \ \ \ set\ body\ \[lindex\ \$args\ 1\]\n\ \ \ \ \}\ else\ \{\ \n\ \ \ \ \ \ \ \ set\ body\ \[lrange\ \$args\ 1\ end\]\n\ \ \ \ \}\n\ \ \ \ switch\ --\ \$type\ \{\n\ \ \ \ \ \ \ \ exact\ \ \{error\ unimplemented\}\n\ \ \ \ \ \ \ \ nocase\ \{error\ unimplemented\}\n\ \ \ \ \ \ \ \ glob\ \ \ \{error\ unimplemented\}\n\ \ \ \ \ \ \ \ regexp\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ foreach\ \{rexp\ script\}\ \$body\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$rexp\ eq\ \{default\}\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ uplevel\ 1\ \$script\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ break\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[regexp\ --\ \$rexp\ \$string\ match\ 1\ 2\ 3\ 4\ 5\ 6\ 7\ 8\ 9\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[info\ exists\ matchvar\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ upvar\ \$matchvar\ m\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ m\ \[list\ \$match\ \$1\ \$2\ \$3\ \$4\ \$5\ \$6\ \$7\ \$8\ \$9\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ uplevel\ 1\ \$script\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ unset\ m\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ uplevel\ 1\ \$script\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ break\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ default\ \{error\ \"internal\ type=\$type\ error\"\}\n\ \ \ \ \}\n\}\n======\n\n\n\n**\ A\ Dynamic\ `switch`\ **\n\n\[neb\]:\ ddd\ asked\ about\ https://groups.google.com/d/msg/comp.lang.tcl/tsNZHbu_K0A/8yTwNFjgOu8J%|%an\ expandable\ switch\ statements%|%.\ I'm\ putting\ some\ of\ the\ answers\ here,\ because\ I\ intend\ to\ possibly\ use\ them\ =\]\n\n\[Schelte\ Bron\]\ said:\ The\ `switch`\ command\ (at\ least\ in\ the\ format\ you\ used)\ takes\ a\ list\ as\ its\ last\ argument.\ So\ you\ can\ simply\ put\ that\ into\ a\ variable\ and\ use\ the\ normal\ list\ operations\ to\ manipulate\ it:\n\n======\nset\ switch\ \{\n\ \ \ a*b\ \ \ \ \ -\n\ \ \ b\ \ \ \ \ \ \ \{expr\ 1\}\n\ \ \ a*\ \ \ \ \ \ \{expr\ 2\}\n\ \ \ default\ \{expr\ 3\}\n\}\n\nswitch\ -glob\ aaab\ \$switch\n\nset\ switch\ \[linsert\ \$switch\ end-2\ c\ \{expr\ 4\}\]\n\nswitch\ -glob\ c\ \$switch\n======\n\n\[DKF\]\ said:\ I'd\ do\ it\ like\ this,\ using\ the\ alternate\ form\ of\ `\[switch\]`:\n\n======\nset\ defs\ \{\n\ \ \ \ a*b\ \ \ \ \ -\n\ \ \ \ b\ \ \ \ \ \ \ \{expr\ 1\}\n\ \ \ \ a*\ \ \ \ \ \ \{expr\ 2\}\n\}\n\nswitch\ -glob\ --\ \$value\ \{*\}\$defs\ default\ \{\n\ \ \ \ expr\ 3\n\}\n======\n\nLike\ that,\ adding\ another\ clause\ is\ just\ this:\n\n======\nlappend\ defs\ c\ \{expr\ 4\}\n======\n\nYet\ you\ won't\ disrupt\ the\ special\ handling\ of\ `default`,\ which\ has\ to\ be\ the\ last\ clause.\ (You\ could\ also\ put\ the\ default\ handling\ script\ in\ its\ own\ variable,\ or\ other\ arbitrarily\ complex\ solution.\ Your\ call.)\ \n\n\n**\ A\ Misunderstanding\ **\n\nSomeone\ wrote:\n\nThere\ is\ a\ typo\ in\ the\ current\ switch.html\ documenation.\ \ The\ original\ code\ looks\ like:\n\n======\nset\ foo\ abc\nswitch\ abc\ a\ -\ b\ \{expr\ 1\}\ \$foo\ \{expr\ 2\}\ default\ \{expr\ 3\}\n======\n\nIt\ should\ read:\n\n======\nswitch\ abc\ \{a\ -\ b\}\ \{expr\ 1\}\ \$foo\ \{expr\ 2\}\ default\ \{expr\ 3\}\n======\n\n2014-04-11:\ I\ don't\ think\ it's\ a\ typo,\ because\ it's\ valid,\ if\ a\ little\ contrived,\ code.\ \ The\ original\ code\ means\ that\ if\ `abc`\ were\ equal\ to\ `a`\ ''or''\ `\"b\"`,\ the\ result\ would\ be\ `1`.\ However,\ if\ you\ really\ want\ to\ match\ against\ the\ string\ `a\ -\ b`,\ then\ you\ need\ to\ enclose\ it\ in\ quotes\ or\ braces.\n\[PL\]\ 2014-04-11:\ I\ don't\ think\ it's\ a\ typo,\ because\ it's\ valid,\ if\ a\ little\ contrived,\ code.\ \ The\ original\ code\ means\ that\ if\ `abc`\ were\ equal\ to\ `a`\ ''or''\ `\"b\"`,\ the\ result\ would\ be\ `1`.\ However,\ if\ you\ really\ want\ to\ match\ against\ the\ string\ `a\ -\ b`,\ then\ you\ need\ to\ enclose\ it\ in\ quotes\ or\ braces.\n\n\n**\ Discussion\ **\n\n\[LV\]:\ Can\ someone\ help\ me\ with\ switch?\ I\ have\ what\ seems\ like\ a\ simple\nbit\ of\ code,\ but\ it\ doesn't\ work\ as\ I\ expected.\ So\ I\ need\ help\ adjusting\nmy\ expectation\ (and\ my\ code!).\n\n======\n#!\ /usr/tcl84/bin/tclsh\n\nset\ ::expert\ no\nset\ ::usage\ \"USAGE:\ \$argv0\ arg1\ arg2\"\nset\ ::val\ XYZ\n\nforeach\ i\ \$::argv\ \{\n\ \ \ \ switch\ -exact\ --\ \$i\ in\ \{\n\ \ \ \ \ \ \ \ !\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$::expert\ eq\ \{no\}\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ ::expert\ yes\n\ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ puts\ \$::usage\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ exit\ 1\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ 1\ \{set\ \$::val\ 1\}\n\ \ \ \ \ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ puts\ \{**\ Too\ many\ values\ specified\ **\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ puts\ \{You\ will\ be\ prompted\ for\ the\ information\ **\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ ::expert\ no\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\}\n\nputs\ \$::expert\nputs\ \$::val\n\$\ ts.tcl\ 1\ 2\ !\nno\nXYZ\n======\n\nI\ was\ expecting\ to\ see\ \n\n======none\nno\ \n**\ Too\ many\ values\ specified\ **\nYou\ will\ be\ prompted\ for\ the\ information\ **\n1\n======\n\nas\ a\ result,\ since\ I\ supplied\ a\ 2\ and\ a\ !.\n\nWhat\ am\ I\ missing\ in\ this?\n\n\[RHS\]:\ There\ is\ an\ extraneous\ '''`in`'''\ there:\n\n======\nswitch\ -exact\ --\ \$i\ in\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ^^\n======\n\n\n\n<<categories>>\ Command\ |\ Control\ Structure\ |\ Tcl\ syntax\ |\ Arts\ and\ crafts\ of\ Tcl-Tk\ programming regexp2} CALL {my render switch '''\[http://www.tcl.tk/man/tcl/TclCmd/switch.htm%|%switch\]''',\ a\ \[Tcl\ Commands%|%built-in\]\ \[Tcl\]\ \[command\],\ uses\ patterns\ to\ select\ a\ script,\ and\ then\ \[eval%|%evaluates\]\ that\ script.\nCommands%|%built-in\]\ \[Tcl\]\ \[command\],\ evaluates\ one\ of\ several\ scripts,\ndepending\ on\ a\ given\ value.\n\n\n**\ Synopsis\ **\n**\ See\ Also\ **\n\n\ \ \ \[ranged\ switch\]:\ \ \ a\ range-aware\ lookalike\ to\ `switch`\n\n\ \ \ \[switch-regexp\]:\ \ \ `switch`\ with\ `\[regexp\]`\ variable\ capturing\n\n\n\n\n\ \ \ \ :\ \ \ '''switch'''\ ?''options''?\ ''string\ pattern\ body''\ ?''pattern\ body\ ...''?\ \n\ \ \ \ :\ \ \ '''switch'''\ ?''options''?\ ''string\ pattern\ body''\ ?''pattern\ body\ ...''?\ \n\n\ \ \ \ :\ \ \ '''switch'''\ ?''options''?\ ''string''\ \{''pattern\ body''\ ?''pattern\ body\ ...?\}\n\n\n\n**\ Documentation\ \ **\n\n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/switch.htm%|%official\ reference\]:\ \ \ \n\n\n\n**\ Description\ **\n\n`switch`\ supersedes\ `\[case\]`.\n\nWhen\ the\ ''pattern\ body''\ arguments\ are\ presented\ as\ separate\ arguments\ rather\nthan\ as\ one\ single\ argument,\ and\ ''string''\ starts\ with\ or\ could\ possibly\nis\ not\ incorrectly\ treated\ as\ an\ option.\ \n\n======\nswitch\ --\ \$foo\ \{...\}\ \ \;#\ robust\ for\ all\ values\ of\ foo\n======\n\nIn\ Tcl\ versions\ prior\ to\ \[Changes\ in\ Tcl/Tk\ 8.5%|%8.5\],\ \ `--`\ should\ be\ used\nin\ any\ case.\n\nWith\ exactly\ one\ argument,\ that\ argument\ is\ a\ \[dict%|%dictionary\]\ of\ patterns\nIn\ the\ form\ of\ `switch`\ where\ all\ patterns\ and\ bodies\ are\ in\ the\ last\ argument,\ this\ argument\ is\ technically\ a\ string\ which\ will\ be\ parsed\ by\ Tcl\ as\ a\ `\[list\]`.\ The\ rules\ for\ how\ a\ string\ is\ parsed\ as\ a\ list\ can\ be\ found\ on\ the\ `\[list\]`\ page.\ \n`switch`\ only\ performs\ string\ comparison,\ so\ it\ isn't\ ideal\ for\ numeric\ncomparison.\ \ That\ said,\ `switch`\ almost\ always\ \"just\ works\"\ for\ the\ numeric\ncases\ because\ string\ comparison\ is\ a\ natural\ surrogate\ for\ equality\ testing\ of\nintegers,\ and\ the\ cost\ of\ creating\ a\ string\ representation\ of\ an\ integer\ is\nusually\ nominal\ in\ the\ grand\ scheme\ of\ a\ Tcl\ script.\ \ `\[if\]`\ is\ always\navailable\ for\ numeric\ or\ other\ more\ complex\ tests.\n\n\n\n**\ Examples\ **\n\nCoding\ style\ for\ switch\ is\ tricky.\ \ Recently\ on\ \[comp.lang.tcl\]\ there\ was\nan\ exchange\ about\ getting\ `switch`\ to\ work\ right.\ \ The\ user\ had\ originally\ntyped:\n\n======\nswitch\ \$::errorCode\ \{\n\ \ \ \ \$NOTFOUND\ \{\n\ \ \ \ \ \ \ \ puts\ \{page\ not\ found\}\n\ \ \ \ \}\n\ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ puts\ \"Program\ encountered\ code\ \$::errorCode\"\n\ \ \ \ \ \ \ \ break\n\ \ \ \ \}\n\}\n======\n\nand\ was\ frustrated\ because\ the\ application\ kept\ taking\ the\ default\ branch.\n\n\[PYK\]\ 2014-05-29:\ \[scripted\ list\]\ can\ make\ this\ syntax\ work,\ and\ even\ allows\ comments:\n\[PYK\]\ 2014-05-29:\ \[scripted\ list\]\ can\ make\ this\ syntax\ work:\n======\nswitch\ \$::errorCode\ \[sl\ \{\n\ \ \ \ #todo:\ offer\ a\ list\ of\ similar\ pages\n\ \ \ \ \ \ \ \ puts\ \{page\ not\ found\}\n\ \ \ \ \}\n\ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ puts\ \"Program\ encountered\ code\ \$::errorCode\"\n\ \ \ \ \ \ \ \ break\n\ \ \ \ \}\n\}\]\n======\n\nA\ well-known\ Tcl\ pundit\ suggested:\n\n======\nswitch\ \$::errorCode\ \"\n\ \ \ \ \$NOTFOUND\ \{\n\ \ \ \ \ \ \ \ puts\ \"page\ not\ found\ \"\n\ \ \ \ \}\n\ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ puts\ \"Program\ encountered\ code\ \$::errorCode\"\n\ \ \ \ \}\n\"\n======\nso\ that\ Tcl\ had\ a\ chance\ to\ substitue\ `\$NOTFOUND`.\n\n''\[AMG\]:\ The\ quotes\ don't\ match\ up\ the\ way\ you\ expect.\ \ This\ is\ because\ braces\ inside\ \"quoted\"\ words\ don't\ have\ any\ special\ power.\ \ the\ second\ argument\ to\ switch\ starts\ with\ a\ line\ break,\ ends\ with\ the\ space\ following\ puts,\ and\ has\ the\ word\ \"page\"\ illegally\ appended\ to\ it,\ resulting\ in\ an\ \"extra\ characters\ after\ close-quote\"\ error.''\n\nHowever,\ the\ follow\ up,\ by\ \[Ken\ Jones\]\ said\ it\ best:\n\nyou\ don't\ want\ that\ (unless\ you're\ doing\ some\ very,\ very,\ very\ntricky\ stuff).\ Quoting\ switch's\ pattern/action\ block\ with\ `\"\"`\ allows\nsubstitutions\ within\ the\ entire\ argument.\ So,\ yes\ you\ get\ `\$URL_NOT_FOUND`\nsubstituted.\ But\ you\ also\ get\ the\ contents\ of\ the\ actions\nsubstituted\ before\ switch\ even\ gets\ called.\n\n\[lexfiend\]:\ I\ think\ the\ following\ example\ illustrates\ Ken's\ point\ better:\n\n======\n#\ GOTCHA\ -\ You're\ dead\ no\ matter\ what\ you\ do\nset\ TriggerBomb\ 0\nset\ DefuseBomb\ 1\nset\ WaitAMinuteWhileIThinkThisThrough\ 2\nset\ Action\ \$WaitAMinuteWhileIThinkThisThrough\ninterp\ alias\ \{\}\ SendToBomb\ \{\}\ puts\nswitch\ \$Action\ \"\n\ \ \ \ \$TriggerBomb\ \{\n\ \ \ \ \ \ \ \ set\ result\ \[SendToBomb\ boom\]\n\ \ \ \ \}\n\ \ \ \ \$DefuseBomb\ \{\n\ \ \ \ \ \ \ \ set\ result\ \[SendToBomb\ shutdown\]\n\ \ \ \ \}\n\"\n======\n\nInstead,\ we\ want\ the\ syntax\ of\ `switch`\ where\ the\ \nInstead,\ we\ the\ syntax\ of\ `switch`\ where\ the\ \nrather\ than\ a\ single\ list\ of\ alternating\ pattern/body\ items.\ Here's\ a\ncorrectly\ working\ example\ of\ the\ above\ code:\n\n======\nset\ NOTFOUND\ value\nset\ errorCode\ nonsense\n\nswitch\ --\ \$::errorCode\ \\\n\ \ \ \ \$NOTFOUND\ \{\n\ \ \ \ \ \ \ \ puts\ \{page\ not\ found\}\n\ \ \ \ \}\ \\\n\ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ puts\ \"Program\ encountered\ code\ \$::errorCode\"\n\ \ \ \ \}\n======\n\n\[KBK\]:\ I\ dislike\ both\ of\ these.\ \ I\ tend\ to\ think\ of\ a\ switch\ as\ a\nselection\ among\ fixed\ alternatives,\ and\ substitution\ in\ the\ cases\nconfuses\ me.\ \ I'd\ have\ just\ written:\n\n======\nif\ \{\$::errorcode\ eq\ \$NOTFOUND\}\ \{\n\ \ \ \ puts\ \{page\ not\ found\}\n\}\ else\ \{\n\ \ \ \ puts\ \"Program\ encountered\ code\ \$::errorCode\"\n\}\n======\n\n\[RHS\]:\ I\ find\ that\ when\ I\ need\ substitution\ for\ switch\ values,\ formatting\ it\ like\ the\ following\ looks\ cleaner:\n\n======\nswitch\ --\ \$::errorCode\ \$NOTFOUND\ \{\n\ \ \ \ puts\ \{page\ not\ found\}\n\}\ \$value1\ \{\n\ \ \ puts\ blah\n\}\ default\ \{\n\ \ \ puts\ \"Program\ encountered\ code\ \$::errorCode\"\n\}\n======\n\n\[DKF\]:\ With\ 8.6,\ I'd\ be\ using\ `\[try\]`\ for\ this\ particular\ problem\ instead\ of\ using\ `switch`\ to\ pick\ through\ \[errorCode%|%\$::errorCode\]\ after\ `\[catch\]`\ returned,\ but\ YMMV.\n\n----\n\n\[LV\]:\ The\ above\ sample\ was,\ of\ course,\ intended\ to\ be\ brief,\ and\ didn't\ show\ the\ other\ several\ dozen\ switch\ cases.\ \ For\ a\ single\ comparison,\ I\ agree\ with\ \[KBK\].\ \ But\ if\ I\ have\ more\ than\ one\ or\ two\ of\ these\ types\ of\ comparisons,\ then\ I\ know\ ''I''\ prefer\ a\ switch.\n\n----\n\nHow's\ this\ for\ a\ silly\ compromise.\nNicely\ aligns\ the\ dispatch\ conditions\ and\ removes\ the\ confusing\ barrage\ of\ backslashes.\n\n======\nif\ 0\ \{\n\}\ elseif\ \{\$state\ eq\ \$INIT_STATE\}\ \{\n\ \ \ puts\ init\n\}\ elseif\ \{\$state\ eq\ \$CLEANING_STATE\}\ \{\n\ \ \ puts\ cleaning\n\}\ elseif\ \{\$state\ eq\ \$DONE_STATE\}\ \{\n\ \ \ puts\ done\n\}\n======\n\n----\n\nThe\ silliness\ continues...\ this\ actually\ works\ though\ I'm\ not\ sure\ of\ the\ side\ effects.\n\n======\nproc\ dispatch\ \{thevar\ args\}\ \{\n\ \ \ \ set\ pass1\ \[uplevel\ subst\ \$args\]\n\ \ \ \ set\ pass2\ \"switch\ \\\$\$thevar\ \\\{\ \$pass1\ \\\}\"\n\ \ \ \ uplevel\ \$pass2\n\}\n\nset\ INIT_STATE\ init\nset\ CLEANING_STATE\ cleaning\nset\ DONE_STATE\ done\n\nset\ state\ \$INIT_STATE\n\ndispatch\ state\ \{\n\ \ \ \ \$INIT_STATE\ \{\n\ \ \ \ \ \ \ \ puts\ init\n\ \ \ \ \ \ \ \ set\ nextstate\ \$DONE_STATE\n\ \ \ \ \}\n\ \ \ \ \$CLEANING_STATE\ \{\n\ \ \ \ \ \ \ \ puts\ cleaning\n\ \ \ \ \}\n\ \ \ \ \$DONE_STATE\ \{\n\ \ \ \ \ \ \ \ puts\ done\n\ \ \ \ \}\n\ \ \ \ default\ \{\n\ \ \ \ \}\n\}\nputs\ \"next\ state\ \$nextstate\"\n======\n\n\[PYK\]\ 2014-05-30:\ The\ code\ above\ is\ not\ robust\ due\ to\ the\ use\ of\ `\[subst\]`\n.\n\n\n======\ndict\ set\ body\ \[list\ \$INIT_STATE\]\ \{\n\n\[PZ\]:\ Using\ `default`\ alternative\ with\ `-regexp`:\n\n======\nset\ a\ x\nswitch\ -regexp\ --\ \$a\ \{\n\ \ \ \ y\ \{\n\ \ \ \ \ \ \ \ puts\ y\n\ \ \ \ \}\n\ \ \ \ \{\}\ \{\n\ \ \ \ \ \ \ \ puts\ z\n\ \ \ \ \}\n\ \ \ \ \n\ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ puts\ \$a\n\ \ \ \ \}\n\}\n======\n\nreturns:\n\n======none\nz\n======\n\nThis\ is\ because\ `\{\}`\ matches\ the\ \[empty\ string\]\ that\ implicitly\ exists\ at\ both\nends\ of\ a\ string\ and\ between\ every\ character\ in\ a\ string.\n\n\n\n**\ Match\ Abbreviations\ **\n\nWith\ `switch\ -regexp`,\ you\ can\ specify\ abbreviations\ of\ a\ flag\ to\ be\ switched\ on\ like\ this:\n\n======\nswitch\ -regexp\ --\ \$variable\ \{\n\ \ \ \ -h(e(lp?)?)?\ \ \ \ \ \ \ \ \ \ \ \ \ \{...\}\n\ \ \ \ -h|-he|-hel|-help|-ayuda\ \{...\}\n\ \ \ \ -\\\\?\ \{...\}\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \;\$\ Match\ -?\ flag\n\ \ \ \ \{(?x)\ -\ |\ -h\ |\ -help\}\ \{do\ stuff\}\ \;#\ extended\ RE\ syntax\n\}\n======\n\nwithout\ the\ -regexp,\ you\ would\ write:\n\n======\nswitch\ --\ \$variable\ \{\n\ \ \ \ -h\ -\ -he\ -\ -hel\ -\ -help\ \{...\}\n\}\n======\n\n----\n\n\[LV\]:\ I\ really\ find\ using\ `-`\ as\ a\ separator\ between\ switch\ case\ alternatives\ to\ be\ counter-intuitive\ .\nnormally\ one\ uses\ `|`\ for\ that\ sort\ of\ thing.\n\n\[glennj\]:\ It\ might\ be\ clearer\ if\ more\ whitespace\ is\ used:\n\n======\nswitch\ --\ \$variable\ \{\n\ \ \ \ -h\ \ \ \ -\ \n\ \ \ \ -he\ \ \ -\ \n\ \ \ \ -hel\ \ -\ \n\ \ \ \ -help\ \{...\}\n\}\n======\n\n\n\n**\ `-regexp`\ and\ backrefs\ **\n\n\[SB\]\ 2003-05-21:\ When\ I\ use\ `switch\ -regexp`,\ Tcl\ already\ use\ regexp\ once\ to\ enter\ the\ proper\ clause.\ How\ can\ the\ match\ pattern\ be\ accessed\ from\ within\ the\ clause,\ if\ possible,\ and\ is\ switch\ `-regexp`\ able\ to\ use\ ()\ match\ variables?\ I\ think\ perl\ store\ the\ regexp\ matches\ in\ global\ variables\ \$1\ ..\ \$9\ \n(The\ following\ example\ is\ not\ valid,\ only\ for\ illustrating\ question)\n\n======\nswitch\ -regexp\ --\ \$somevar\ \{\n\ \ \ \ \{^(\\S+)\\s+(\\S+)\}\ \{puts\ \"You\ hit\ matches\ \$1\ and\ \$2\"\}\n\ \ \ \ \{^(\\d+)\\s+(\\d+)\}\ \{puts\ \"You\ hit\ number\ matches\ \$1\ and\ \$2\"\}\n\}\n======\n\n\[KBK\]\ -\ You\ can't.\ \ However,\ that\ form\ of\ `switch`\ is\ no\ slower\ than\ the\ corresponding\ `\[if\]\ ...\ \[elseif\]`,\ \nso\ you\ can\ do:\n\n======\nif\ \{\[regexp\ \{^(\\S+)\\s+(\\S+)\$\}\ \$somevar\ ->\ part1\ part2\]\}\ \{\n\ \ \ \ \ puts\ \"You\ hit\ matches\ \$part1\ and\ \$part2\"\n\}\ elseif\ \{\[regexp\ \{^(\\d+)\\s+(\\d+)\}\ ->\ part1\ part2\]\}\ \{\n\ \ \ \ \ puts\ \"You\ hit\ number\ matches\ \$part1\ and\ \$part2\"\n\}\n======\n\n\[hkoba\]\ 2005-03-18:\ Hmm,\ how\ about\ \[switch-regexp\]?\n\n\[DKF\]:\ With\ 8.5,\ you\ can\ tell\ `switch`\ to\ store\ the\ re-matched\ values\ instead\ of\ discarding\ them.\n\n\n\n**\ Delimiting\ the\ Options\ **\n\n\[LES\]:\ So,\ if\ it\ is\ so\ good\ a\ practice\ ALWAYS\ to\ call\ switch\ as\ \"switch\ --\"\ (the\ switch\ to\ end\ all\ switches),\ why\ can't\ the\ core\ code\ already\ cope\ with\ that?\n\n\[MG\]:\ That's\ not\ really\ specific\ to\ switch\ -\ it's\ really\ good\ practice\ with\ ''all''\ commands\ that\ take\ ''-something''\ args,\ and\ show\ the\ end\ of\ those\ with\ '--',\ to\ include\ the\ --.\ And\ I\ think\ the\ reason\ the\ core\ can't\ handle\ is\ that\ sometimes\ you\ may\ actually\ want\ the\ behaviour\ that\ occurs\ when\ you\ don't\ give\ `--`.\n\n\[LV\]:\ because\ technically\ the\ rule\ isn't\ \"ALWAYS\ call\ switch\ as\ `switch\ --`\".\nThe\ rule\ is\ \"ALWAYS\ call\ switch\ with\ `--`\ after\ the\ last\ of\ the\ switch\nflags\".\ \ If\ you\ are\ using\ switch\ without\ a\ flag,\ then\ it\ would\ be\ \"`switch\ --`\".\nThink\ of\ code\ like\ this:\n\n======\nset\ arg\ \{something\ entered\ by\ the\ user\}\nswitch\ \$arg\ \{\n\ \ \ \ --first_thing\ \{do\ something\}\n\ \ \ \ --second_thing\ \{do\ something\ else\}\n\ \ \ \ default\ \{do\ the\ last\ thing\}\n\}\n======\n\nNow,\ if\ the\ user\ happens\ to\ type\ in\ `--first_thing`,\ the\ program\nraises\ the\ error:\n\n======none\nbad\ option\ \"--first_thing\":\ must\ be\ -exact,\ -glob,\ -regexp,\ or\ --\n======\n\nbecause\ there\ was\ no\ `--`\ between\ the\ switch\ and\ the\ variable\ being\nexamined.\ Not\ only\ that,\ but\ if\ the\ user\ happens\ to\ type\ in\ `-exact`,\nthe\ error\ raised\ is:\n\n======none\nwrong\ #\ args:\ should\ be\ \"switch\ ?switches?\ string\ pattern\ body\ ...\ ?default\ body?\"\n======\n\nbecause\ of\ the\ missing\ `--`.\ \ Two\ potential\ error\ situations\ -\ and\nthe\ core\ switch\ command\ can't\ handle\ either,\ because\ by\ the\ time\ it\ is\ncalled,\ any\ information\ about\ where\ the\ first\ argument\ is\ already\ gone.\n\n\[RS\]:\ The\ need\ for\ `--`\ seems\ to\ exist\ only\ for\ ''switch''.\ Other\ commands\ don't\ get\ confused\ by\ parameters\ that\ look\ like\ switches\ but\ aren't:\n\n======none\n%\ lsearch\ -foo\ -bar\n-1\n======\n\nThen\ again,\ `\[regexp\]`\ has\ the\ same\ need\ for\ `--`:\n\n======none\n%\ regexp\ -foo\ -bar\nbad\ switch\ \"-foo\":\ must\ be\ -all,\ -about,\ -indices,\ -inline,\ -expanded,\ -line,\ -linestop,\ -lineanchor,\ -nocase,\ -start,\ or\ --\n======\n\nYax:\ `\[lsearch\]`\ assumes\ the\ form\ of\ arguments\ by\ the\ argument\ count,\ and\ its\ quite\ probable\ that\ all\ commands\ that\ take\ fixed\ args\ after\ options\ do.\ Any\ commands\ (such\ as\ regexp)\ that\ can\ take\ an\ arbitrarily\ varying\ number\ of\ args\ and\ have\ switches\ probably\ also\ suffer\ this\ issue.\n\n\n\n**\ `\[break\]`\ **\n\n\[LV\]:\ When\ I\ try\ to\ use\ a\ break\ inside\ a\ `switch`\ script,\ I\ get\ the\ error\n\n======none\ninvoked\ \"break\"\ outside\ of\ a\ loop\n\ \ \ \ while\ executing\n\"switch\ \n======\n\nIs\ there\ an\ equivalent\ to\ `\[break\]`\ for\ switch?\n\n\[YSK\]:\ How\ about\ trapping\ `switch`\ in\ `\[while\]\ 1`:\n\n======\nwhile\ 1\ \{\n\ \ \ \ switch\ \$cond\ \{\n\ \ \ \ \ \ \ \ case1\ \{\n\ \ \ \ \ \ \ \ \ \ \ if\ \{\$fault\}\ \{puts\ NG\;\ break\}\n\ \ \ \ \ \ \ \ \ \ \ puts\ OK\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ \ \ \ puts\ OK\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ break\n\}\n======\n\n\[MG\]\ Hrm,\ I\ thought\ `\[break\]`\ worked\ in\ switches,\ too.\ But\ it\ seems\ that\ Tcl's\ \[switch\]\ doesn't\ fall\ through\ by\ default:\n\n======\nswitch\ -glob\ --\ foo\ \\\n\ \ \ \ f*\ \{puts\ match1\}\ \\\n\ \ \ \ *o*\ \{puts\ match2\}\ \\\n\ \ \ \ default\ \{puts\ nomatch\}\n======\n\nOnly\ the\ \"match1\"\ is\ shown,\ and\ then\ it\ stops,\ there's\ no\ \"match2\".\ So\ no\ `\[break\]`\ is\ needed,\ it'll\ stop\ when\ a\ match\ is\ found\ anyway.\ That\ means,\ in\ something\ like\n\n======\nswitch\ -glob\ --\ \$string\ \\\n\ \ \ \ f*\ \{puts\ foo\}\n\ \ \ \ b*\ \{puts\ bar\}\n\ \ \ \ *z*\ \{#\ do\ nothing\}\n\ \ \ \ default\ \{puts\ \{something\ else\}\}\n======\n\nthe\ \"#\ do\ nothing\"\ case\ has\ the\ same\ effect\ as\ a\ `\[break\]`\ in\ a\ switch\ in\ \[C\]\ would.\n\n\[LV\]\ without\ `\[break\]`,\ it\ means\ that\ one\ has\ to\ code\ carefully\ to\ avoid\ the\ cases\ where\ one\ normally\ would\ use\ it.\ For\ instance,\ in\ other\ languages,\ one\ might\ code\n\n======\nswitch\ \$variable\ \{\ncase1\ \{do\ this\;\ break\}\ncase2\ \{do\ that\;\ break\}\ncase3\ \{if\ today\ is\ Monday,\ do\ the\ other\;\ break\;\ if\ tomorrow\ is\ the\ 14th,\ do\ something\ else\;\ break\;\}\ndefault\ \{if\ an\ error,\ say\ so\ and\ break\;\ do\ the\ last\ thing,\ break\;\}\n======\n\nIn\ Tcl,\ one\ would\ recode\ using\ `\[if%|%else\]`\ or\ `\[if%|%elseif\]`\ or\ fiddling\nwith\ state\ variables,\ etc.\ to\ accomplish\ the\ same\ thing.\n\n\n\n**\ Using\ the\ Return\ Value\ of\ `switch`\ **\n\n\[RS\]\ 2005-05-30:\ Unlike\ in\ \[C\],\ \[Tcl\]'s\ `\[switch\]`\ returns\ its\ last\ evaluated\ result,\ \nso\ it\ can\ be\ used\ as\ a\ function.\ Given\ this\ simple\ \[identity\ function%|%identity\]\n\n======\nproc\ is\ x\ \{set\ x\}\n======\n\nwe\ can\ code\ the\ following\ \"digit\ classifier\"\ quite\ elegantly:\n\n======\nforeach\ num\ \{0\ 1\ 2\ 3\ 4\ 5\ 6\ 7\ 8\ 9\}\ \{\n\ \ \ \ set\ type\ \[switch\ --\ \$num\ \{\n\ \ \ \ \ \ \ \ 1\ -\ 9\ \ \ \ \ \ \ \ \ \{is\ odd\}\n\ \ \ \ \ \ \ \ 2\ -\ 3\ -\ 5\ -\ 7\ \{is\ prime\}\n\ \ \ \ \ \ \ \ 0\ -\ 4\ -\ 6\ -\ 8\ \{is\ even\}\n\ \ \ \ \}\]\n\ \ \ \ puts\ \"\$num\ is\ \$type\"\n\}\n======\n\nwhich\ displays\n\n======none\n0\ is\ even\n1\ is\ odd\n2\ is\ prime\n3\ is\ prime\n4\ is\ even\n5\ is\ prime\n6\ is\ even\n7\ is\ prime\n8\ is\ even\n9\ is\ odd\n======\n\n\[AMG\]:\ See\ \[identity\ function\ \]\ for\ more\ discussion\ of\ this\ pattern.\ \ The\ simplest\ way\ to\ do\ it\ is\ with\n\[AMG\]:\ See\ \[identify\ function\ \]\ for\ more\ discussion\ of\ this\ pattern.\ \ The\ simplest\ way\ to\ do\ it\ is\ with\n\n\n**\ History\ **\n\nFirst\ announced\ by\ \[JO\]\ for\ Tcl\ 7.0\ in\ \[https://groups.google.com/d/msg/comp.lang.tcl/u1pATk0ytWM/8uStOsyBrLYJ%|%Advice\ wanted:\ \"case\"\ command\ and\ regexps\],\ \[comp.lang.tcl\],1993-06-05\n\n\n\n**\ Compilation\ Notes\ **\n\n\[DKF\]:\ In\ Tcl\ \[Changes\ in\ Tcl/Tk\ 8.5%|%8.5\],\ `switch`\ is\ \[bytecode%|%byte-compiled\]\ if\ reasonably\ possible.\ The\ \"reasonably\ possible\"\ part\ means\ that\ you\ do\ have\ to\ be\ doing\ either\ '''`-exact`'''\ or\ '''`-glob`'''\ matching,\ and\ the\ bodies\ of\ the\ arms\ have\ to\ be\ compilable\ (as\ usual).\ With\ '''`-regexp`'''\ matching,\ that\ always\ goes\ to\ the\ \"interpreted\"\ version\ (though\ by\ compensation,\ there\ are\ some\ other\ new\ goodies\ (see\ `-matchvar`\ and\ `-indexvar`,\ for\ instance)\ available).\n\nIn\ most\ cases,\ the\ switch\ is\ compiled\ to\ (effectively)\ a\ sequence\ of\ `\[if\]`\ commands.\ However,\ in\ some\ special\ cases,\ i.e.\ '''`-exact`'''\ matching\ of\ constant\ terms,\ a\ jump\ table\ is\ built\ instead,\ which\ is\ considerably\ more\ efficient,\ especially\ for\ terms\ other\ than\ the\ first\ one.\n\n\n**\ Bug:\ `-indexvar`\ Indexes\ Off\ By\ One\ **\n**\ Bug:\ `-indexvar`\ indexess\ off\ by\ one\ **\n\[TJE\]:\ Why\ are\ the\ ranges\ placed\ in\ a\ `switch`\ statement's\ `-indexvar`\ target\ inclusive\ of\ the\ character\ AFTER\ the\ match?\ \ This\ differs\ from\ the\ behavior\ of\ regexp's\ `-indices`\ option,\ which\ seems\ quite\ odd\ to\ me.\ \ For\ example:\n\n======\n%\ set\ line\ \{foo\ bar\}\nfoo\ bar\n%\ regexp\ -inline\ -indices\ foo\ \$line\n\{0\ 2\}\n%\ switch\ -regexp\ -indexvar\ index\ --\ \$line\ foo\ \{set\ index\}\n\{0\ 3\}\n======\n\nDoesn't\ that\ seem\ odd?\ \ 'Tis\ not\ at\ all\ what\ I'd\ expected...\n\n\[PYK\]\ 2014-05-30:\ If\ this\ really\ happened,\ it\ must\ have\ been\ a\ bug\ in\ some\nversion\ of\ Tcl.\ The\ current\ version\ behaves\ as\ expected,\ returnint\ `\{0\ 2\}`.\n\n\n\n**\ Comments\ in\ Switch\ Statements\ **\n\nComments\ can\ be\ placed\ in\ the\ bodies\ of\ `switch`:\n\n======\nswitch\ \$x\ \{\n\ \ \ \ 1\ \{\n\ \ \ \ \ \ \ \ #comment\ goes\ here\n\ \ \ \ \ \ \ \ ...\n\ \ \ \ \}\n\ \ \ \ 2\ \{\n\ \ \ \ \ \ \ \ #comment\ goes\ here\n\ \ \ \ \ \ \ \ ...\n\ \ \ \ \}\n\}\n======\n\n----\n\n\[Wookie\]:\ I\ have\ a\ large\ switch\ and\ wanted\ comments\ for\ blocks\ of\ statements\ e.g.\n\n======\nswitch\ -exact\ --\ \$test\ \{\n\ \ \ \ #\ Comment\ for\ first\ block\n\ \ \ \ Test1\ \{do\ stuff...\}\n\ \ \ \ Test2\ \{do\ stuff...\}\n\ \ \n\ \ \ \ #\ Comment\ for\ second\ block\n\ \ \ \ Test3\ \{do\ stuff...\}\n\ \ \ \ Test4\ \{do\ stuff...\}\n\ \ \n\ \ \ \ #\ Comment\ for\ default\n\ \ \ \ NONE\ -\n\ \ \ \ default\ \{SomeCleanUpProc...\}\n\}\n======\n\nYou\ get\ the\ error:\n\ \ \ \"extra\ switch\ pattern\ with\ no\ body,\ this\ may\ be\ due\ to\ a\ comment\ incorrectly\ placed\ outside\ of\ a\ switch\ body\ -\ see\ the\ \"switch\"\ documentation\"\n\nAs\ Tcl\ `switch`\ statements\ don't\ seem\ to\ care\ that\ there\ are\ multiple\ definitions\ of\ a\ statement,\ I\ rewrote\ the\ code\ as:\ \n======\nswitch\ -exact\ --\ \$test\ \{\n\ \ \ \ COMMENT\ \{#\ Comment\ for\ first\ block\}\n\ \ \ \ Test1\ \{do\ stuff...\}\n\ \ \ \ Test2\ \{do\ stuff...\}\n\ \ \n\ \ \ \ COMMENT\ \{#\ Comment\ for\ second\ block\}\n\ \ \ \ Test3\ \{do\ stuff...\}\n\ \ \ \ Test4\ \{do\ stuff...\}\n\ \ \n\ \ \ \ COMMENT\ \{#\ Comment\ for\ default\}\n\ \ \ \ NONE\ -\n\ \ \ \ default\ \{clean\ up\ stuff...\}\n\}\ \n======\n\nIf\ COMMENT\ is\ passed\ in\ it\ simply\ calls\ the\ first\ COMMENT\ in\ the\ switch,\ which\ does\ nothing.\ If\ COMMENT\ is\ a\ valid\ statement\ it\ would\ have\ to\ be\ dealt\ with\ in\ the\ first\ block.\n\n\[PYK\]\ 2014-09-17:\ \ A\ \[scripted\ list\]\ is\ another\ option.\n\n\n\n\[AMG\]:\ Unlike\ \[C\]'s\ switch,\ which\ does\ numeric\ comparisons,\ \[Tcl\]\ switch\ performs\ `\[string\]`\ comparisons.\ \ This\ can\ make\ a\ big\ difference\ in\ your\ program\ if\ you\ are\ dealing\ with\ numbers\ that\ are\ formatted\ in\ different\ ways.\n\n======\nset\ number\ 0x5\nswitch\ --\ \$number\ \{\n\ \ \ \ 5\ \ \ \ \ \ \ \{puts\ five!\}\n\ \ \ \ default\ \{puts\ unknown\}\n\}\n======\n\nYou\ may\ instead\ consider\ a\ long\ `\[if\]`/`\[elseif\]`\ chain,\ but\ maybe\ this\ won't\ \[bytecode\]\ as\ well.\ \ Alternately,\ force\ the\ \[format%|%formatting\]\ to\ be\ consistent:\n\n======\nset\ number\ 0x5\nswitch\ --\ \[format\ %d\ \$number\]\ \{\n5\ \ \ \ \ \ \ \{puts\ five!\}\ndefault\ \{puts\ unknown\}\n\}\n======\n\n\n\n**\ Performance\ of\ `-regexp`\ **\n**\ Performance\ of\ `-regexp`\ **\[DrASK\]:\n\[DrASK\]:\n\n======\nswitch\ -exact\ --\ \$value\ \{\n\ \ \ \ a\ -\ b\ -\ c\ match\n\}\n\nswitch\ -regexp\ --\ \$value\ \{\n\ \ \ \ \[abc\]\ match\n\}\n======\n\n\[Lars\ H\]:\ Comments\ by\ \[DKF\]\ above\ suggest\ that\ the\ answer\ should\ be\ yes,\ but\ why\ not\ check\ for\ yourself?\ `\[time\]`\ it!\n\nAlso\ note\ that\ the\ two\ \[switch\]es\ aren't\ exactly\ equivalent:\ the\ latter\ checks\ whether\ the\ \$value\ ''contains''\ a,\ b,\ or\ c,\ not\ whether\ it\ ''is''.\ To\ do\ that,\ you\ need\ to\ change\ the\ regexp\ pattern\ as\ follows:\n\n======\nswitch\ -regexp\ --\ \$value\ \{\n\ \ \ ^\[abc\]\$\ \{match\}\n\}\n======\n\n\[DrASK\]:\ Yeah,\ I\ failed\ to\ mention\ that\ `\$value`\ is\ known\ to\ be\ a\ single\ character.\ Thanks.\ Here\ is\ the\ test\ and\ the\ results:\n\n======\nproc\ exact\ value\ \{\n\ \ \ \ switch\ -exact\ --\ \$value\ \{\n\ \ \ \ \ \ \ \ a\ -\ b\ -\ c\ \{return\ true\}\n\ \ \ \ \ \ \ \ default\ \{return\ false\}\n\ \ \ \ \}\n\}\n\nproc\ re\ value\ \{\n\ \ \ \ switch\ -regexp\ --\ \$value\ \{\n\ \ \ \ \ \ \ \ \[abc\]\ \{return\ true\}\n\ \ \ \ \ \ \ \ default\ \{return\ false\}\n\ \ \ \ \}\n\}\n\nproc\ first\ value\ \{\n\ \ \ \ return\ \[expr\ \{\[string\ first\ \$value\ abc\]\ !=\ -1\}\]\n\}\n\nproc\ multi\ \{type\ value\}\ \{\n\ \ \ \ for\ \{set\ i\ 0\}\ \{\$i\ <\ 100\}\ \{incr\ i\}\ \{\n\ \ \ \ \ \ \ \ \$type\ \$value\n\ \ \ \ \}\n\}\n\nforeach\ type\ \{exact\ re\ first\}\ \{\n\ \ \ \ foreach\ value\ \{a\ b\ c\ d\}\ \{\n\ \ \ \ \ \ \ \ puts\ \"\$type\ \$value\ \[errortime\ \{multi\ \$type\ \$value\}\ 10000\ 100\]\"\n\ \ \ \ \}\n\}\n======\n======none\nexact\ a\ 66\ +/-\ 0\ microseconds\ per\ iteration\nexact\ b\ 67\ +/-\ 0\ microseconds\ per\ iteration\nexact\ c\ 67\ +/-\ 0\ microseconds\ per\ iteration\nexact\ d\ 66\ +/-\ 0\ microseconds\ per\ iteration\nregexp\ a\ 151\ +/-\ 0\ microseconds\ per\ iteration\nregexp\ b\ 140\ +/-\ 0\ microseconds\ per\ iteration\nregexp\ c\ 142\ +/-\ 0\ microseconds\ per\ iteration\nregexp\ d\ 121\ +/-\ 0\ microseconds\ per\ iteration\nfirst\ a\ 71\ +/-\ 0\ microseconds\ per\ iteration\nfirst\ b\ 71\ +/-\ 0\ microseconds\ per\ iteration\nfirst\ c\ 71\ +/-\ 0\ microseconds\ per\ iteration\nfirst\ d\ 70\ +/-\ 0\ microseconds\ per\ iteration\n======\n\nIt's\ interesting\ to\ note\ the\ dropoff\ when\ `\[regexp\]`\ hit\ the\ default\ case.\ But\ `-regexp`\ is\ clearly\ is\ 2-2.5x\ slower.\ I\ used\ \[MAK\]'s\ \[How\ to\ Measure\ Performance%|%errortime\ proc\]\ for\ timing.\n\n\[ferrieux\]:\ Indeed,\ timing\ shows\ that\ the\ jump\ table\ is\ roughly\ 3x\ faster\ than\ `if..elseif..elseif`,\ which\ is\ itself\ 1.25x\ faster\ than\ `\[regexp\]`.\ Notice\ that\ the\ `\[regexp\]`\ compilation\ overhead\ is\ not\ in\ the\ picture,\ since\ it\ is\ cached.\ Not\ sure\ whether\ we\ should\ worry\ about\ the\ 1.25...\n\n\n**\ An\ Implementation\ in\ Tcl\ **\n\n\[rwm\]:\ I\ recently\ needed\ to\ run\ some\ \[Changes\ in\ Tcl/Tk\ 8.5%|%8.5\]\ code\ in\ \[Changes\ in\ Tcl/Tk\ 8.4%|%8.4\].\ \ I\ wrote\ the\ following\ code\ to\ mimic\ the\ 8.5\ switch\ in\ 8.4.\ (I\ looked\ for\ but\ could\ not\ find\ a\ compatibility\ library...)\ Note\ the\ many\ errors\ for\ cases\ that\ I\ did\ not\ need.\ \ Maybe\ someone\ else\ will\ cover\ fix/post\ those\ \;)\ \ Feel\ free\ to\ edit/move\ this\ as\ appropriate.\n\n======\nproc\ switch_8.5\ args\}\ \{\n\ \ \ \ ##\ this\ is\ an\ 8.4\ version\ of\ the\ 8.5\ switch\ (incomplete)\n\ \ \ \ if\ \{\[llength\ \$args\]\ <\ 2\}\ \{\n\ \ \ \ \ \ \ \ error\ \"usage:\ switch\ ?options?\ string\ \{pattern\ body\ ?pattern\ body\ ...?\}\"\n\ \ \ \ \}\n\ \ \ \ set\ type\ exact\n\ \ \ \ while\ \{\[string\ match\ -*\ \[lindex\ \$args\ 0\]\]\}\ \{\n\ \ \ \ \ \ \ \ set\ option\ \[lindex\ \$args\ 0\]\n\ \ \ \ \ \ \ \ set\ args\ \[lrange\ \$args\ 1\ end\]\n\ \ \ \ \ \ \ \ switch\ --\ \$option\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ -exact\ \ \ \ \{set\ type\ exact\}\n\ \ \ \ \ \ \ \ \ \ \ \ -nocase\ \ \ \{set\ type\ nocase\}\n\ \ \ \ \ \ \ \ \ \ \ \ -glob\ \ \ \ \ \{set\ type\ glob\}\n\ \ \ \ \ \ \ \ \ \ \ \ -regexp\ \ \ \{set\ type\ regexp\}\n\ \ \ \ \ \ \ \ \ \ \ \ -matchvar\ \{set\ matchvar\ \[lindex\ \$args\ 0\]\;\ set\ args\ \[lrange\ \$args\ 1\ end\]\}\n\ \ \ \ \ \ \ \ \ \ \ \ -indexvar\ \{error\ \"unimplemented\"\}\n\ \ \ \ \ \ \ \ \ \ \ \ --\ break\n\ \ \ \ \ \ \ \ \ \ \ \ default\ \{error\ \"bad\ switch\ option=\$option\"\}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ set\ string\ \[lindex\ \$args\ 0\]\n\ \ \ \ if\ \{\[llength\ \$args\]\ ==\ 2\}\ \{\n\ \ \ \ \ \ \ \ set\ body\ \[lindex\ \$args\ 1\]\n\ \ \ \ \}\ else\ \{\ \n\ \ \ \ \ \ \ \ set\ body\ \[lrange\ \$args\ 1\ end\]\n\ \ \ \ \}\n\ \ \ \ switch\ --\ \$type\ \{\n\ \ \ \ \ \ \ \ exact\ \ \{error\ unimplemented\}\n\ \ \ \ \ \ \ \ nocase\ \{error\ unimplemented\}\n\ \ \ \ \ \ \ \ glob\ \ \ \{error\ unimplemented\}\n\ \ \ \ \ \ \ \ regexp\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ foreach\ \{rexp\ script\}\ \$body\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$rexp\ eq\ \{default\}\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ uplevel\ 1\ \$script\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ break\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[regexp\ --\ \$rexp\ \$string\ match\ 1\ 2\ 3\ 4\ 5\ 6\ 7\ 8\ 9\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[info\ exists\ matchvar\]\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ upvar\ \$matchvar\ m\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ m\ \[list\ \$match\ \$1\ \$2\ \$3\ \$4\ \$5\ \$6\ \$7\ \$8\ \$9\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ uplevel\ 1\ \$script\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ unset\ m\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ uplevel\ 1\ \$script\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ break\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ default\ \{error\ \"internal\ type=\$type\ error\"\}\n\ \ \ \ \}\n\}\n======\n\n\n\n**\ A\ Dynamic\ `switch`\ **\n\n\[neb\]:\ ddd\ asked\ about\ https://groups.google.com/d/msg/comp.lang.tcl/tsNZHbu_K0A/8yTwNFjgOu8J%|%an\ expandable\ switch\ statements%|%.\ I'm\ putting\ some\ of\ the\ answers\ here,\ because\ I\ intend\ to\ possibly\ use\ them\ =\]\n\n\[Schelte\ Bron\]\ said:\ The\ `switch`\ command\ (at\ least\ in\ the\ format\ you\ used)\ takes\ a\ list\ as\ its\ last\ argument.\ So\ you\ can\ simply\ put\ that\ into\ a\ variable\ and\ use\ the\ normal\ list\ operations\ to\ manipulate\ it:\n\n======\nset\ switch\ \{\n\ \ \ a*b\ \ \ \ \ -\n\ \ \ b\ \ \ \ \ \ \ \{expr\ 1\}\n\ \ \ a*\ \ \ \ \ \ \{expr\ 2\}\n\ \ \ default\ \{expr\ 3\}\n\}\n\nswitch\ -glob\ aaab\ \$switch\n\nset\ switch\ \[linsert\ \$switch\ end-2\ c\ \{expr\ 4\}\]\n\nswitch\ -glob\ c\ \$switch\n======\n\n\[DKF\]\ said:\ I'd\ do\ it\ like\ this,\ using\ the\ alternate\ form\ of\ `\[switch\]`:\n\n======\nset\ defs\ \{\n\ \ \ \ a*b\ \ \ \ \ -\n\ \ \ \ b\ \ \ \ \ \ \ \{expr\ 1\}\n\ \ \ \ a*\ \ \ \ \ \ \{expr\ 2\}\n\}\n\nswitch\ -glob\ --\ \$value\ \{*\}\$defs\ default\ \{\n\ \ \ \ expr\ 3\n\}\n======\n\nLike\ that,\ adding\ another\ clause\ is\ just\ this:\n\n======\nlappend\ defs\ c\ \{expr\ 4\}\n======\n\nYet\ you\ won't\ disrupt\ the\ special\ handling\ of\ `default`,\ which\ has\ to\ be\ the\ last\ clause.\ (You\ could\ also\ put\ the\ default\ handling\ script\ in\ its\ own\ variable,\ or\ other\ arbitrarily\ complex\ solution.\ Your\ call.)\ \n\n\n**\ A\ Misunderstanding\ **\n\nSomeone\ wrote:\n\nThere\ is\ a\ typo\ in\ the\ current\ switch.html\ documenation.\ \ The\ original\ code\ looks\ like:\n\n======\nset\ foo\ abc\nswitch\ abc\ a\ -\ b\ \{expr\ 1\}\ \$foo\ \{expr\ 2\}\ default\ \{expr\ 3\}\n======\n\nIt\ should\ read:\n\n======\nswitch\ abc\ \{a\ -\ b\}\ \{expr\ 1\}\ \$foo\ \{expr\ 2\}\ default\ \{expr\ 3\}\n======\n\n2014-04-11:\ I\ don't\ think\ it's\ a\ typo,\ because\ it's\ valid,\ if\ a\ little\ contrived,\ code.\ \ The\ original\ code\ means\ that\ if\ `abc`\ were\ equal\ to\ `a`\ ''or''\ `\"b\"`,\ the\ result\ would\ be\ `1`.\ However,\ if\ you\ really\ want\ to\ match\ against\ the\ string\ `a\ -\ b`,\ then\ you\ need\ to\ enclose\ it\ in\ quotes\ or\ braces.\n\[PL\]\ 2014-04-11:\ I\ don't\ think\ it's\ a\ typo,\ because\ it's\ valid,\ if\ a\ little\ contrived,\ code.\ \ The\ original\ code\ means\ that\ if\ `abc`\ were\ equal\ to\ `a`\ ''or''\ `\"b\"`,\ the\ result\ would\ be\ `1`.\ However,\ if\ you\ really\ want\ to\ match\ against\ the\ string\ `a\ -\ b`,\ then\ you\ need\ to\ enclose\ it\ in\ quotes\ or\ braces.\n\n\n**\ Discussion\ **\n\n\[LV\]:\ Can\ someone\ help\ me\ with\ switch?\ I\ have\ what\ seems\ like\ a\ simple\nbit\ of\ code,\ but\ it\ doesn't\ work\ as\ I\ expected.\ So\ I\ need\ help\ adjusting\nmy\ expectation\ (and\ my\ code!).\n\n======\n#!\ /usr/tcl84/bin/tclsh\n\nset\ ::expert\ no\nset\ ::usage\ \"USAGE:\ \$argv0\ arg1\ arg2\"\nset\ ::val\ XYZ\n\nforeach\ i\ \$::argv\ \{\n\ \ \ \ switch\ -exact\ --\ \$i\ in\ \{\n\ \ \ \ \ \ \ \ !\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$::expert\ eq\ \{no\}\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ ::expert\ yes\n\ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ puts\ \$::usage\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ exit\ 1\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ 1\ \{set\ \$::val\ 1\}\n\ \ \ \ \ \ \ \ default\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ puts\ \{**\ Too\ many\ values\ specified\ **\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ puts\ \{You\ will\ be\ prompted\ for\ the\ information\ **\}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ ::expert\ no\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\}\n\nputs\ \$::expert\nputs\ \$::val\n\$\ ts.tcl\ 1\ 2\ !\nno\nXYZ\n======\n\nI\ was\ expecting\ to\ see\ \n\n======none\nno\ \n**\ Too\ many\ values\ specified\ **\nYou\ will\ be\ prompted\ for\ the\ information\ **\n1\n======\n\nas\ a\ result,\ since\ I\ supplied\ a\ 2\ and\ a\ !.\n\nWhat\ am\ I\ missing\ in\ this?\n\n\[RHS\]:\ There\ is\ an\ extraneous\ '''`in`'''\ there:\n\n======\nswitch\ -exact\ --\ \$i\ in\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ^^\n======\n\n\n\n<<categories>>\ Command\ |\ Control\ Structure\ |\ Tcl\ syntax\ |\ Arts\ and\ crafts\ of\ Tcl-Tk\ programming} CALL {my revision switch} CALL {::oo::Obj2632611 process revision/switch} CALL {::oo::Obj2632609 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