Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/dicthash%3A+Yet+another+lightweight+object+system?V=10
QUERY_STRINGV=10
CONTENT_TYPE
DOCUMENT_URI/revision/dicthash:+Yet+another+lightweight+object+system
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.69.59.177
REMOTE_PORT25478
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.204
HTTP_CF_RAY87946d60db681140-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.204
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 {dicthash: Yet another lightweight object system} I\ was\ using\ \[unknown\]\ today\ to\ add\ some\ syntax\ sugar\ to\ dicts\ and\ somehow\ came\ up\ with\ a\ simple,\ lightweight\ object\ system\ that\ has\ the\ feel\ of\ \[javascript\]\ objects.\n\nThe\ basic\ idea\ is\ that\ everything's\ a\ value\ (how\ very\ tclish\ \;-).\ Methods\ are\ simply\ lambda\ expressions\ stored\ as\ elements\ in\ a\ dict.\ Also,\ I\ started\ by\ stealing\ the\ object\ syntax\ from\ Tk\ widget\ hierarchies\ but\ ended\ up\ with\ a\ very\ javascript-like\ syntax.\n\n**Usage\ Summary**\n\n======\n\ \ #\ start\ with\ a\ dict:\n\ \ set\ foo\ \{\n\ \ \ \ location\ \{x\ 0\ y\ 0\}\n\ \ \ \ heading\ 0\n\ \ \ \ move\ \{\{distance\}\ \{\n\ \ \ \ \ \ %this.location.x\ =\ \[expr\ \{\n\ \ \ \ \ \ \ \ \[%this.location.x\]+(\$distance*cos(\[%this.heading\]))\n\ \ \ \ \ \ \}\]\n\ \ \ \ \ \ %this.location.y\ =\ \[expr\ \{\n\ \ \ \ \ \ \ \ \[%this.location.y\]+(\$distance*sin(\[%this.heading\]))\n\ \ \ \ \ \ \}\]\n\ \ \ \ \}\}\n\ \ \}\n\n\ \ puts\ \[%foo.location.x\]\ \;#\ get\ value\n\ \ %foo.heading\ =\ 1\ \ \ \ \ \ \ \;#\ assign\ value\n\ \ %foo.move.apply\ 100\ \ \ \ \;#\ call\ method\n\n\ \ set\ newfoo\ \[%foo\ +\ \{name\ \"tortise\"\}\]\ \;#\ dict\ merge\n\ \ %foo\ +=\ \{name\ \"hare\"\}\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \;#\ dict\ merge\n\n======\n\n**Syntax**\n\nAll\ commands\ that\ begins\ with\ '''%'''\ are\ assumed\ to\ be\ the\ variable\ names\ of\ proper\ dicts.\ The\ basic\ syntax\ of\ a\ dicthash\ command\ is:\n\n======\n\ \ %varname.key.key\n======\n\nWhere\ varname\ is\ the\ variable\ name\ pointing\ to\ a\ dict\ and\ the\ keys\ are\ nested\ keys\ referring\ to\ elements\ in\ the\ dict.\ Since\ this\ is\ tcl,\ the\ fact\ that\ \$\ substitution\ stops\ at\ \".\"\ can\ be\ exploited\ to\ substitute\ key\ names:\n\n======\n\ \ %varname.\$key\n======\n\nWhen\ a\ dicthash\ command\ is\ passed\ two\ arguments\ and\ the\ first\ argument\ is\ '''='''\ then\ a\ \[dict\ set\]\ is\ applied\ to\ the\ dict:\n\n======\n\ \ %varname.key.key\ =\ \$value\n======\n\nWhen\ a\ dicthash\ command\ is\ passed\ two\ arguments\ and\ the\ first\ argument\ is\ '''+'''\ then\ a\ \[dict\ merge\]\ is\ applied\ to\ the\ dict:\n\n======\n\ \ set\ newvar\ \[%varname\ +\ \$somedict\]\n======\n\nWhen\ a\ dicthash\ command\ is\ passed\ two\ arguments\ and\ the\ first\ argument\ is\ '''+='''\ then\ a\ \[dict\ merge\]\ is\ applied\ to\ the\ dict\ and\ the\ result\ is\ stored\ back\ into\ the\ dict:\n\n======\n\ \ %varname\ +=\ \$somedict\n======\n\nIf\ the\ last\ key\ is\ '''apply'''\ then\ the\ value\ of\ the\ next-to-last\ key\ is\ assumed\ to\ be\ a\ lambda\ expression\ and\ is\ invoked\ automatically\ by\ calling\ the\ \[apply\]\ command:\n\n======\n\ \ %varname.method.apply\ \$argument\ \$argument\n======\n\nI\ toyed\ with\ the\ idea\ of\ implementing\ method\ calls\ as\ %foo.move(\$value)\ but\ that\ felt\ very\ un-tclish\ to\ me.\ So\ I\ opted\ to\ use\ '''apply'''\ as\ the\ keyword\ for\ method\ invocation.\n\nWithin\ dicthash\ methods\ (lambda\ expressions\ which\ are\ elements\ of\ the\ dict),\ '''this'''\ is\ a\ keyword\ referring\ to\ the\ dicthash\ object\ (in\ other\ words,\ the\ current\ dict.\ Just\ what\ you'd\ expect):\n\n======\n\ \ set\ mydict\ \{\n\ \ \ \ set\ \{\{key\ value\}\ \{\n\ \ \ \ \ \ %this.\$key\ =\ \$value\n\ \ \ \ \}\}\n\ \ \ \ lappend\ \{\{key\ args\}\ \{\n\ \ \ \ \ \ dict\ lappend\ this\ \$key\ \{*\}\$args\n\ \ \ \ \}\}\n\ \ \ \ dump\ \{\{\}\ \{\n\ \ \ \ \ \ puts\ \$this\n\ \ \ \ \}\}\n\ \ \}\n\ \ %mydict.set.apply\ somekey\ \"some\ value\"\n\ \ %mydict.lappend.apply\ anotherkey\ 1\ 2\ 3\ 4\n\ \ %mydict.dump.apply\n======\n\n**Here's\ the\ implementation**\n======\n\ \ #\ syntax\ sugar\ for\ dict:\n\ \ proc\ dicthash\ \{cmd\ args\}\ \{\n\ \ \ \ uplevel\ 1\ \[string\ map\ \"CMD\ \$cmd\ ARGS\ \{\{\$args\}\}\"\ \{\n\ \ \ \ \ \ set\ path\ \[split\ \[string\ range\ CMD\ 1\ end\]\ .\]\n\ \ \ \ \ \ set\ varname\ \[lindex\ \$path\ 0\]\n\ \ \ \ \ \ set\ path\ \[lrange\ \$path\ 1\ end\]\n\ \ \ \ \ \ \n\ \ \ \ \ \ upvar\ 1\ \$varname\ var\n\ \ \ \ \ \ \n\ \ \ \ \ \ if\ \{\[lindex\ \$path\ end\]\ ==\ \"apply\"\}\ \{\n\ \ \ \ \ \ \ \ set\ path\ \[lrange\ \$path\ 0\ end-1\]\n\ \ \ \ \ \ \ \ set\ script\ \[dict\ get\ \$var\ \{*\}\$path\]\n\ \ \ \ \ \ \ \ set\ body\ \[lindex\ \$script\ 1\]\n\n\ \ \ \ \ \ \ \ #\ Improved\ implementation\ of\ \"this\":\n\ \ \ \ \ \ \ \ set\ body\ \"upvar\ 1\ var\ this\;\$body\"\n\n\ \ \ \ \ \ \ \ lset\ script\ 1\ \$body\n\ \ \ \ \ \ \ \ if\ \{ARGS\ ==\ \"\"\}\ \{\n\ \ \ \ \ \ \ \ \ \ return\ \[apply\ \$script\]\n\ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ return\ \[apply\ \$script\ \{*\}ARGS\]\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ switch\ --\ \[llength\ ARGS\]\ \{\n\ \ \ \ \ \ \ \ \ \ 0\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ return\ \[dict\ get\ \$var\ \{*\}\$path\]\n\ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ 2\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ op\ \[lindex\ ARGS\ 0\]\n\ \ \ \ \ \ \ \ \ \ \ \ set\ val\ \[lindex\ ARGS\ 1\]\n\ \ \ \ \ \ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$op\ ==\ \"=\"\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \[dict\ set\ var\ \{*\}\$path\ \$val\]\n\ \ \ \ \ \ \ \ \ \ \ \ \}\ elseif\ \{\$op\ ==\ \"+\"\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$path\ ==\ \"\"\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \[dict\ merge\ \$var\ \$val\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ error\ \"invalid\ dict\ merge\"\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \}\ elseif\ \{\$op\ ==\ \"+=\"\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$path\ ==\ \"\"\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \[set\ var\ \[dict\ merge\ \$var\ \$val\]\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ error\ \"invalid\ dict\ merge\"\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \}\n\ \ \ \ \ \ error\ \"unsupported\ operation\ on\ CMD\"\n\ \ \ \ \}\]\n\ \ \}\n\ \ proc\ unknown\ \{cmd\ args\}\ \{\n\ \ \ \ if\ \{\[string\ index\ \$cmd\ 0\]\ ==\ \"%\"\}\ \{\n\ \ \ \ \ \ return\ \[dicthash\ \$cmd\ \{*\}\$args\]\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ error\ \"unknown:\ \$cmd\ \$args\"\n\ \ \ \ \}\n\ \ \}\n\n======\n\n**EIAS**\n\nA\ dicthash\ \"object\"\ is\ nothing\ more\ than\ a\ dict.\ Therefore\ an\ object\ also\ has\ a\ natural\ string\ representation.\ This\ somehow\ feels\ extremely\ tclish\ to\ me\ :-)\n\nIt\ also\ means\ that\ an\ object\ can\ be\ modified\ after\ instantiation,\ just\ like\ javascript.\ So\ for\ example,\ taking\ the\ example\ of\ the\ \"foo\"\ object\ above,\ to\ add\ a\ new\ method\ to\ draw\ it\ on\ a\ canvas\ you\ simply\ assign\ a\ lambda\ expression\ to\ it:\n\n======\n\ \ #\ add\ a\ new\ method:\n\ \ dict\ set\ foo\ draw\ \{\{canvas\}\ \{\n\ \ \ \ set\ x\ \[%this.location.x\]\n\ \ \ \ set\ y\ \[%this.location.y\]\n\ \ \ \ \$canvas\ create\ oval\ \\\n\ \ \ \ \ \ \[expr\ \{\$x-5\}\]\ \[expr\ \{\$y-5\}\]\ \\\n\ \ \ \ \ \ \[expr\ \{\$x+5\}\]\ \[expr\ \{\$y+5\}\]\ \\\n\ \ \ \ \ \ -fill\ red\n\ \ \}\}\n\n\ \ #\ or\ using\ dicthash\ sugar:\n\ \ %foo.draw\ =\ \{\{canvas\}\ \{\n\ \ \ \ set\ x\ \[%this.location.x\]\n\ \ \ \ set\ y\ \[%this.location.y\]\n\ \ \ \ \$canvas\ create\ oval\ \\\n\ \ \ \ \ \ \[expr\ \{\$x-5\}\]\ \[expr\ \{\$y-5\}\]\ \\\n\ \ \ \ \ \ \[expr\ \{\$x+5\}\]\ \[expr\ \{\$y+5\}\]\ \\\n\ \ \ \ \ \ -fill\ red\n\ \ \}\}\n\n\ \ #\ now\ you\ can\ draw\ foo:\n\ \ pack\ \[canvas\ .c\]\ -fill\ both\ -expand\ 1\n\ \ %foo.draw.apply\ .c\n======\n\n**Inheritance**\n\nOriginally\ I\ didn't\ think\ this\ supports\ inheritance.\ After\ all,\ I\ wrote\ this\ and\ I\ haven't\ implemented\ inheritance\ yet!\ It\ turns\ out\ that\ dicthash\ is\ a\ pure\ prototype\ base\ object\ system.\ Much\ more\ so\ than\ \[javascript\]\ thanks\ to\ tcl's\ strict\ value\ semantics\ (also\ known\ as\ \[everything\ is\ a\ string\]).\n\nIn\ a\ prototype\ based\ object\ system\ you\ don't\ inherit.\ Instead\ you\ clone\ from\ your\ parent\ object\ and\ then\ extend\ yourself.\ In\ tcl\ this\ is\ trivial.\ In\ the\ '''foo'''\ example\ above\ I've\ already\ shown\ how\ '''newfoo'''\ ''\"inherits\"''\ from\ '''foo'''.\ So\ in\ dicthash\ (since\ objects\ are\ simply\ dicts)\ inheritance\ is\ simply:\n\n======\n\ \ #\ dict2\ \"inherits\"\ from\ dict1:\n\ \ set\ dict2\ \$dict1\n======\n\nAlso,\ as\ bonus\ and\ because\ of\ the\ excellent\ design\ of\ the\ dict\ API,\ multiple\ \"inheritence\"\ is\ simply:\n\n======\n\ \ #\ dict2\ \"inherits\"\ from\ dict1\ and\ dict0:\n\ \ set\ dict2\ \[dict\ merge\ \$dict1\ \$dict0\]\n\n\ \ #\ or\ in\ dicthash\ notation:\n\ \ set\ dict2\ \[%dict1\ +\ \$dict0\]\n======\n\nA\ more\ elaborate\ example\ of\ \"inheritance\":\n\n======\n\ \ set\ mammal\ \{\n\ \ \ \ class\ mammal\n\ \ \ \ species\ unknown\n\ \ \ \ speak\ \{\{\}\ \{\}\}\n\ \ \}\n\n\ \ #\ dogs\ are\ a\ type\ of\ mammal:\n\ \ set\ dog\ \[%mammal\ +\ \{\n\ \ \ \ species\ dog\n\ \ \ \ speak\ \{\{\}\ \{puts\ Bark!\}\}\n\ \ \}\]\n\n\ \ #\ so\ are\ humans:\n\ \ set\ human\ \[%mammal\ +\ \{\n\ \ \ \ species\ human\n\ \ \ \ name\ \"\"\n\ \ \ \ speak\ \{\{\}\ \{puts\ \"Hello.\ My\ name\ is\ \[%this.name\].\"\}\}\n\ \ \}\]\n\n\ \ #\ create\ instances:\n\ \ set\ fido\ \[%dog\ +\ \{name\ Fido\}\]\n\ \ set\ charlie\ \[%human\ +\ \{name\ Charlie\}\]\n\n\ \ #\ hear\ them\ speak:\n\ \ %fido.speak.apply\ \ \ \ \;#\ Bark!\n\ \ %charlie.speak.apply\ \;#\ Hello.\ My\ name\ is\ Charlie.\n======\n\[Martyn\ Smith\]\ This\ looks\ very\ interesting,\ Have\ you\ looked\ at\ \[RS\]s\ \[Let\ unknown\ know\]\ page,\ especially\ the\ \[namespace\ unknown\]\ command\ in\ 8.5\ which\ would\ be\ perfect\ for\ your\ \[unknown\]\ patch,\ I\ think\ just\ replacing\ \[unknown\]\ could\ cause\ problems\ later.\ Excellent\ idea.\n======\n----\n!!!!!!\n%|\ \[Category\ Object\ Orientation\]\ |%\n!!!!!! regexp2} CALL {my render {dicthash: Yet another lightweight object system} I\ was\ using\ \[unknown\]\ today\ to\ add\ some\ syntax\ sugar\ to\ dicts\ and\ somehow\ came\ up\ with\ a\ simple,\ lightweight\ object\ system\ that\ has\ the\ feel\ of\ \[javascript\]\ objects.\n\nThe\ basic\ idea\ is\ that\ everything's\ a\ value\ (how\ very\ tclish\ \;-).\ Methods\ are\ simply\ lambda\ expressions\ stored\ as\ elements\ in\ a\ dict.\ Also,\ I\ started\ by\ stealing\ the\ object\ syntax\ from\ Tk\ widget\ hierarchies\ but\ ended\ up\ with\ a\ very\ javascript-like\ syntax.\n\n**Usage\ Summary**\n\n======\n\ \ #\ start\ with\ a\ dict:\n\ \ set\ foo\ \{\n\ \ \ \ location\ \{x\ 0\ y\ 0\}\n\ \ \ \ heading\ 0\n\ \ \ \ move\ \{\{distance\}\ \{\n\ \ \ \ \ \ %this.location.x\ =\ \[expr\ \{\n\ \ \ \ \ \ \ \ \[%this.location.x\]+(\$distance*cos(\[%this.heading\]))\n\ \ \ \ \ \ \}\]\n\ \ \ \ \ \ %this.location.y\ =\ \[expr\ \{\n\ \ \ \ \ \ \ \ \[%this.location.y\]+(\$distance*sin(\[%this.heading\]))\n\ \ \ \ \ \ \}\]\n\ \ \ \ \}\}\n\ \ \}\n\n\ \ puts\ \[%foo.location.x\]\ \;#\ get\ value\n\ \ %foo.heading\ =\ 1\ \ \ \ \ \ \ \;#\ assign\ value\n\ \ %foo.move.apply\ 100\ \ \ \ \;#\ call\ method\n\n\ \ set\ newfoo\ \[%foo\ +\ \{name\ \"tortise\"\}\]\ \;#\ dict\ merge\n\ \ %foo\ +=\ \{name\ \"hare\"\}\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \;#\ dict\ merge\n\n======\n\n**Syntax**\n\nAll\ commands\ that\ begins\ with\ '''%'''\ are\ assumed\ to\ be\ the\ variable\ names\ of\ proper\ dicts.\ The\ basic\ syntax\ of\ a\ dicthash\ command\ is:\n\n======\n\ \ %varname.key.key\n======\n\nWhere\ varname\ is\ the\ variable\ name\ pointing\ to\ a\ dict\ and\ the\ keys\ are\ nested\ keys\ referring\ to\ elements\ in\ the\ dict.\ Since\ this\ is\ tcl,\ the\ fact\ that\ \$\ substitution\ stops\ at\ \".\"\ can\ be\ exploited\ to\ substitute\ key\ names:\n\n======\n\ \ %varname.\$key\n======\n\nWhen\ a\ dicthash\ command\ is\ passed\ two\ arguments\ and\ the\ first\ argument\ is\ '''='''\ then\ a\ \[dict\ set\]\ is\ applied\ to\ the\ dict:\n\n======\n\ \ %varname.key.key\ =\ \$value\n======\n\nWhen\ a\ dicthash\ command\ is\ passed\ two\ arguments\ and\ the\ first\ argument\ is\ '''+'''\ then\ a\ \[dict\ merge\]\ is\ applied\ to\ the\ dict:\n\n======\n\ \ set\ newvar\ \[%varname\ +\ \$somedict\]\n======\n\nWhen\ a\ dicthash\ command\ is\ passed\ two\ arguments\ and\ the\ first\ argument\ is\ '''+='''\ then\ a\ \[dict\ merge\]\ is\ applied\ to\ the\ dict\ and\ the\ result\ is\ stored\ back\ into\ the\ dict:\n\n======\n\ \ %varname\ +=\ \$somedict\n======\n\nIf\ the\ last\ key\ is\ '''apply'''\ then\ the\ value\ of\ the\ next-to-last\ key\ is\ assumed\ to\ be\ a\ lambda\ expression\ and\ is\ invoked\ automatically\ by\ calling\ the\ \[apply\]\ command:\n\n======\n\ \ %varname.method.apply\ \$argument\ \$argument\n======\n\nI\ toyed\ with\ the\ idea\ of\ implementing\ method\ calls\ as\ %foo.move(\$value)\ but\ that\ felt\ very\ un-tclish\ to\ me.\ So\ I\ opted\ to\ use\ '''apply'''\ as\ the\ keyword\ for\ method\ invocation.\n\nWithin\ dicthash\ methods\ (lambda\ expressions\ which\ are\ elements\ of\ the\ dict),\ '''this'''\ is\ a\ keyword\ referring\ to\ the\ dicthash\ object\ (in\ other\ words,\ the\ current\ dict.\ Just\ what\ you'd\ expect):\n\n======\n\ \ set\ mydict\ \{\n\ \ \ \ set\ \{\{key\ value\}\ \{\n\ \ \ \ \ \ %this.\$key\ =\ \$value\n\ \ \ \ \}\}\n\ \ \ \ lappend\ \{\{key\ args\}\ \{\n\ \ \ \ \ \ dict\ lappend\ this\ \$key\ \{*\}\$args\n\ \ \ \ \}\}\n\ \ \ \ dump\ \{\{\}\ \{\n\ \ \ \ \ \ puts\ \$this\n\ \ \ \ \}\}\n\ \ \}\n\ \ %mydict.set.apply\ somekey\ \"some\ value\"\n\ \ %mydict.lappend.apply\ anotherkey\ 1\ 2\ 3\ 4\n\ \ %mydict.dump.apply\n======\n\n**Here's\ the\ implementation**\n======\n\ \ #\ syntax\ sugar\ for\ dict:\n\ \ proc\ dicthash\ \{cmd\ args\}\ \{\n\ \ \ \ uplevel\ 1\ \[string\ map\ \"CMD\ \$cmd\ ARGS\ \{\{\$args\}\}\"\ \{\n\ \ \ \ \ \ set\ path\ \[split\ \[string\ range\ CMD\ 1\ end\]\ .\]\n\ \ \ \ \ \ set\ varname\ \[lindex\ \$path\ 0\]\n\ \ \ \ \ \ set\ path\ \[lrange\ \$path\ 1\ end\]\n\ \ \ \ \ \ \n\ \ \ \ \ \ upvar\ 1\ \$varname\ var\n\ \ \ \ \ \ \n\ \ \ \ \ \ if\ \{\[lindex\ \$path\ end\]\ ==\ \"apply\"\}\ \{\n\ \ \ \ \ \ \ \ set\ path\ \[lrange\ \$path\ 0\ end-1\]\n\ \ \ \ \ \ \ \ set\ script\ \[dict\ get\ \$var\ \{*\}\$path\]\n\ \ \ \ \ \ \ \ set\ body\ \[lindex\ \$script\ 1\]\n\n\ \ \ \ \ \ \ \ #\ Improved\ implementation\ of\ \"this\":\n\ \ \ \ \ \ \ \ set\ body\ \"upvar\ 1\ var\ this\;\$body\"\n\n\ \ \ \ \ \ \ \ lset\ script\ 1\ \$body\n\ \ \ \ \ \ \ \ if\ \{ARGS\ ==\ \"\"\}\ \{\n\ \ \ \ \ \ \ \ \ \ return\ \[apply\ \$script\]\n\ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ return\ \[apply\ \$script\ \{*\}ARGS\]\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ switch\ --\ \[llength\ ARGS\]\ \{\n\ \ \ \ \ \ \ \ \ \ 0\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ return\ \[dict\ get\ \$var\ \{*\}\$path\]\n\ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ 2\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ set\ op\ \[lindex\ ARGS\ 0\]\n\ \ \ \ \ \ \ \ \ \ \ \ set\ val\ \[lindex\ ARGS\ 1\]\n\ \ \ \ \ \ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$op\ ==\ \"=\"\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \[dict\ set\ var\ \{*\}\$path\ \$val\]\n\ \ \ \ \ \ \ \ \ \ \ \ \}\ elseif\ \{\$op\ ==\ \"+\"\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$path\ ==\ \"\"\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \[dict\ merge\ \$var\ \$val\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ error\ \"invalid\ dict\ merge\"\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \}\ elseif\ \{\$op\ ==\ \"+=\"\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ \{\$path\ ==\ \"\"\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ return\ \[set\ var\ \[dict\ merge\ \$var\ \$val\]\]\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ error\ \"invalid\ dict\ merge\"\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \}\n\ \ \ \ \ \ error\ \"unsupported\ operation\ on\ CMD\"\n\ \ \ \ \}\]\n\ \ \}\n\ \ proc\ unknown\ \{cmd\ args\}\ \{\n\ \ \ \ if\ \{\[string\ index\ \$cmd\ 0\]\ ==\ \"%\"\}\ \{\n\ \ \ \ \ \ return\ \[dicthash\ \$cmd\ \{*\}\$args\]\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ error\ \"unknown:\ \$cmd\ \$args\"\n\ \ \ \ \}\n\ \ \}\n\n======\n\n**EIAS**\n\nA\ dicthash\ \"object\"\ is\ nothing\ more\ than\ a\ dict.\ Therefore\ an\ object\ also\ has\ a\ natural\ string\ representation.\ This\ somehow\ feels\ extremely\ tclish\ to\ me\ :-)\n\nIt\ also\ means\ that\ an\ object\ can\ be\ modified\ after\ instantiation,\ just\ like\ javascript.\ So\ for\ example,\ taking\ the\ example\ of\ the\ \"foo\"\ object\ above,\ to\ add\ a\ new\ method\ to\ draw\ it\ on\ a\ canvas\ you\ simply\ assign\ a\ lambda\ expression\ to\ it:\n\n======\n\ \ #\ add\ a\ new\ method:\n\ \ dict\ set\ foo\ draw\ \{\{canvas\}\ \{\n\ \ \ \ set\ x\ \[%this.location.x\]\n\ \ \ \ set\ y\ \[%this.location.y\]\n\ \ \ \ \$canvas\ create\ oval\ \\\n\ \ \ \ \ \ \[expr\ \{\$x-5\}\]\ \[expr\ \{\$y-5\}\]\ \\\n\ \ \ \ \ \ \[expr\ \{\$x+5\}\]\ \[expr\ \{\$y+5\}\]\ \\\n\ \ \ \ \ \ -fill\ red\n\ \ \}\}\n\n\ \ #\ or\ using\ dicthash\ sugar:\n\ \ %foo.draw\ =\ \{\{canvas\}\ \{\n\ \ \ \ set\ x\ \[%this.location.x\]\n\ \ \ \ set\ y\ \[%this.location.y\]\n\ \ \ \ \$canvas\ create\ oval\ \\\n\ \ \ \ \ \ \[expr\ \{\$x-5\}\]\ \[expr\ \{\$y-5\}\]\ \\\n\ \ \ \ \ \ \[expr\ \{\$x+5\}\]\ \[expr\ \{\$y+5\}\]\ \\\n\ \ \ \ \ \ -fill\ red\n\ \ \}\}\n\n\ \ #\ now\ you\ can\ draw\ foo:\n\ \ pack\ \[canvas\ .c\]\ -fill\ both\ -expand\ 1\n\ \ %foo.draw.apply\ .c\n======\n\n**Inheritance**\n\nOriginally\ I\ didn't\ think\ this\ supports\ inheritance.\ After\ all,\ I\ wrote\ this\ and\ I\ haven't\ implemented\ inheritance\ yet!\ It\ turns\ out\ that\ dicthash\ is\ a\ pure\ prototype\ base\ object\ system.\ Much\ more\ so\ than\ \[javascript\]\ thanks\ to\ tcl's\ strict\ value\ semantics\ (also\ known\ as\ \[everything\ is\ a\ string\]).\n\nIn\ a\ prototype\ based\ object\ system\ you\ don't\ inherit.\ Instead\ you\ clone\ from\ your\ parent\ object\ and\ then\ extend\ yourself.\ In\ tcl\ this\ is\ trivial.\ In\ the\ '''foo'''\ example\ above\ I've\ already\ shown\ how\ '''newfoo'''\ ''\"inherits\"''\ from\ '''foo'''.\ So\ in\ dicthash\ (since\ objects\ are\ simply\ dicts)\ inheritance\ is\ simply:\n\n======\n\ \ #\ dict2\ \"inherits\"\ from\ dict1:\n\ \ set\ dict2\ \$dict1\n======\n\nAlso,\ as\ bonus\ and\ because\ of\ the\ excellent\ design\ of\ the\ dict\ API,\ multiple\ \"inheritence\"\ is\ simply:\n\n======\n\ \ #\ dict2\ \"inherits\"\ from\ dict1\ and\ dict0:\n\ \ set\ dict2\ \[dict\ merge\ \$dict1\ \$dict0\]\n\n\ \ #\ or\ in\ dicthash\ notation:\n\ \ set\ dict2\ \[%dict1\ +\ \$dict0\]\n======\n\nA\ more\ elaborate\ example\ of\ \"inheritance\":\n\n======\n\ \ set\ mammal\ \{\n\ \ \ \ class\ mammal\n\ \ \ \ species\ unknown\n\ \ \ \ speak\ \{\{\}\ \{\}\}\n\ \ \}\n\n\ \ #\ dogs\ are\ a\ type\ of\ mammal:\n\ \ set\ dog\ \[%mammal\ +\ \{\n\ \ \ \ species\ dog\n\ \ \ \ speak\ \{\{\}\ \{puts\ Bark!\}\}\n\ \ \}\]\n\n\ \ #\ so\ are\ humans:\n\ \ set\ human\ \[%mammal\ +\ \{\n\ \ \ \ species\ human\n\ \ \ \ name\ \"\"\n\ \ \ \ speak\ \{\{\}\ \{puts\ \"Hello.\ My\ name\ is\ \[%this.name\].\"\}\}\n\ \ \}\]\n\n\ \ #\ create\ instances:\n\ \ set\ fido\ \[%dog\ +\ \{name\ Fido\}\]\n\ \ set\ charlie\ \[%human\ +\ \{name\ Charlie\}\]\n\n\ \ #\ hear\ them\ speak:\n\ \ %fido.speak.apply\ \ \ \ \;#\ Bark!\n\ \ %charlie.speak.apply\ \;#\ Hello.\ My\ name\ is\ Charlie.\n======\n\[Martyn\ Smith\]\ This\ looks\ very\ interesting,\ Have\ you\ looked\ at\ \[RS\]s\ \[Let\ unknown\ know\]\ page,\ especially\ the\ \[namespace\ unknown\]\ command\ in\ 8.5\ which\ would\ be\ perfect\ for\ your\ \[unknown\]\ patch,\ I\ think\ just\ replacing\ \[unknown\]\ could\ cause\ problems\ later.\ Excellent\ idea.\n======\n----\n!!!!!!\n%|\ \[Category\ Object\ Orientation\]\ |%\n!!!!!!} CALL {my revision {dicthash: Yet another lightweight object system}} CALL {::oo::Obj139079 process revision/dicthash%3A+Yet+another+lightweight+object+system} CALL {::oo::Obj139077 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