Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/%7B%2A%7D?V=42
QUERY_STRINGV=42
CONTENT_TYPE
DOCUMENT_URI/revision/{*}
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.70.178.178
REMOTE_PORT53302
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR13.58.252.8
HTTP_CF_RAY8793cfd389b70280-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_IP13.58.252.8
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 {{*}} {** Summary **

'''`{*}`''', the syntax formerly known as [{expand}], was added in Tcl 8.5 to allow safe argument expansion.
This resulted in the [Endekalogue] becoming the [Dodekalogue].

See [TIP] [http://tip.tcl.tk/293%|%293] for details.


** See Also **


   [Expansion with {*} in Tcl 8.4]:   

   [BraceStarBrace]:   How should we call this thing?


** Description **

'''`{*}`''' provides an alternative to using `[[[eval]]` to expand a list into
its individual elements 

In older versions of Tcl, one would write: 

======
#warning: no longer recommended
eval destroy [winfo children .]
eval button .b $stdargs -text \$mytext -bd $border
eval exec \$prog $opts1 [getMoreopts] \$file1 \$file2
======

The `[[[eval]]` version would be even more complex if the lists that are to be
expanded are not known to be pure. To be really safe the last would be:

======
#warning: no longer recommended
eval exec \$prog [lrange $opts1 0 end] [lrange [getMoreopts] 0 end] \$file1 \$file2     
======
Or:
======
#warning: no longer recommended
eval [list exec $prog] [lrange $opts1 0 end] [lrange [getMoreopts] 0 end] [list $file1 $file2]
======

With the new syntax the examples become:
======
destroy {*}[winfo children .]
button .b {*}$stdargs -text $mytext -bd $border
exec $prog {*}$opts1 {*}[getMoreopts] $file1 $file2
======

[RS]: One might say {*} is the inverse function of `[[[list]]`:

======
{*}[list a b c] <==> a b c
======

----

[RS]:  In [re_syntax], ''*'' stands for "zero or more", which is
exactly the unique cardinality of an {expand}ed item...

[DKF]: Similarly in `[[[string match]]` syntax.


** Shell Equivalents **

The [bash] equivalent of '''`{*}`''' is

======sh
${varname[@]:+"${varname[@]}"}
======


** More Examples **

======none
(Mike) 1 % set args [list range foobar 2 4]
range foobar 2 4
(Mike) 2 % string $args
unknown or ambiguous subcommand "range foobar 2 4"
(Mike) 3 % string {*}$args
oba
======

The first time, `[[[string]]` gets the entire value of `$args` as one argument,
and fails. The second time, `$args` is expanded, and `[[[string]]`, receiving 4
separate arguments, works correctly.

----

======
(wits) 49 % proc p args {puts "Number of arguments: [llength $args]"}
(wits) 50 % p {a b c}
Number of arguments: 1
(wits) 51 % p {*}{a b c}
Number of arguments: 3
======


** `{*}` in Multiple Dimensions **

[HaO]:  To flatten a matrix, one could use `{*}[[concat {*}...]`.  Example to
find the max of a matrix:

======
% set m {{1 2} {3 4}}
% tcl::mathfunc::max {*}[concat {*}$m]
4
======

The expression, `{*}[[concat {*}$m]` results in `1 2 3 4`.


** Response **

[RLH]: This is much better IMHO.

[jcw]: '''HURRAY!'''''

[SYStems]: I vote yes. I don't think though that its necessary to deprecate
`[{expand}]`, but I agree on deprecating `{}` it does look like syntax error
rather than a feature.

[RLH]: I think `[{expand}]` should be removed completely. It is not in the
language "official" yet and so it should be yanked to make sure no abuse
occurs.

[JMN]:  Well.. `{*}` looks to me like a nipple.. which is clearly better than a
wart.

** Misc **


CN slightly regrets that [{expand}] is now gone - I was looking forward to
possible future enhancements along the same line, like for example 

======
lappend mylist {sort|toupper|regmatch [0-9]+}$somelist
======

to specify a chain of filters for the expansion. But I suppose that people for
whom `[{expand}]` is a wart will classify this a as a tumor... ;-)

[DKF]: It's also trivially replacable using '''{*}[['''...''']]''' and some
commands to preprocess the list.

----

[SYStems] or you can just 

======
lappend mylist {*}[lsort [string toupper [regmatch {[0-9]+} $somelist]]]
======

The moral is that `[{*}]` is not a shorthand for other commands, but a new
feature, although for this particular example you could have just used 

======
set mylist [concat $mylist [lsort [string toupper [regmatch {[0-9]+} $somelist]]] ]
======

[AMG]: Often I need to construct a new list by combining a mixture of lists and
elements.  This is done very well by combining the [[[list]]] command and the
`[{*}]` operator.  (Is it right to call it an operator?)

======
set l1 {a b c}
set e1 d
set l2 {e f g}
set e2 {h i}
set result [list {*}$l1 $e1 {*}$l2 $e2]
======

This sets `$result` to `{a b c d e f g {h i}}`.  Equivalent non-`[{*}]` code:

======
set result $l1
lappend result $e1
set result [concat $result $l2]
lappend result $e2
======

[kpv]: Here's a better way of doing with concat (it's a question of do you
special handle the list pieces or element pieces).

======
set result [concat $l1 [list $e1] $l2 [list $e2]]
======

[AMG]: Thanks.  This clearly shows the two methods are duals of each other.
Side-by-side:

======
set result [list  {*}$l1       $e1  {*}$l2       $e2 ]
set result [concat   $l1 [list $e1]    $l2 [list $e2]]
======

In the first method, `[{*}]` is used to mark which elements are to be expanded,
and the default is to not expand.  In the second method, `[[[list]]` is used to
mark which elements are ''not'' to be expanded, and the default is to expand.
The latter approach is similar to the behavior of [Unix shells] and has led to
a lot of unsafe code when the programmer isn't careful about quoting---
apparently this default is surprising to many people.  However, it does work;
just be cautious!

[kpv]: I think both ways have an equal need for the programmer to be
''cautious'' -- forgetting the `[{*}]` is just as bad as forgetting the
`[[[list]]`. To me, with years of pre-8.5 programming experience, especially in
using `[[[eval]]`, the `[[[concat]]` method feels more natural. I'm sure that
will change as I do more 8.5+ programming.

----

[AMG]: When I have a long command but don't feel like using `\` at the end of
every line, I sometimes do the following:

======
set data [dict create {*}{
    key1 val1    key2 val2
    key3 val3    key4 val4
    key5 val5    key6 val6
}]
======

Of course, in this case I could have just left out the `[[[dict create]]` and
instead relied on the internal representation being generated the first time I
tried accessing `$data` as a `[[[dict]]`.  But the above is slightly faster and
clearer... well, except for the `[{*}]` nonsense, of course. :^)  Given a bit
of time, I'm sure I could come up with a more realistic example, but I actually
find myself doing the above in real code (if anything I write can be said to be
"real").

This usage of `[{*}]` provides quoting without grouping.  Dollar signs and
square brackets become ordinary characters, sequences of unquoted whitespace
and newlines are delimiters, and the resulting list elements (all of which are
pure strings) are placed one-after-the-other into the command's objv list
without any extra interpretation.  Backslashes, paired braces, and paired
double quotes still function as quoting/grouping characters.  ("Grouping" means
to disable the special meaning of characters that would otherwise be treated as
delimiters.)



<<categories>> Syntax | Dodekalogue} regexp2} CALL {my render {{*}} {** Summary **

'''`{*}`''', the syntax formerly known as [{expand}], was added in Tcl 8.5 to allow safe argument expansion.
This resulted in the [Endekalogue] becoming the [Dodekalogue].

See [TIP] [http://tip.tcl.tk/293%|%293] for details.


** See Also **


   [Expansion with {*} in Tcl 8.4]:   

   [BraceStarBrace]:   How should we call this thing?


** Description **

'''`{*}`''' provides an alternative to using `[[[eval]]` to expand a list into
its individual elements 

In older versions of Tcl, one would write: 

======
#warning: no longer recommended
eval destroy [winfo children .]
eval button .b $stdargs -text \$mytext -bd $border
eval exec \$prog $opts1 [getMoreopts] \$file1 \$file2
======

The `[[[eval]]` version would be even more complex if the lists that are to be
expanded are not known to be pure. To be really safe the last would be:

======
#warning: no longer recommended
eval exec \$prog [lrange $opts1 0 end] [lrange [getMoreopts] 0 end] \$file1 \$file2     
======
Or:
======
#warning: no longer recommended
eval [list exec $prog] [lrange $opts1 0 end] [lrange [getMoreopts] 0 end] [list $file1 $file2]
======

With the new syntax the examples become:
======
destroy {*}[winfo children .]
button .b {*}$stdargs -text $mytext -bd $border
exec $prog {*}$opts1 {*}[getMoreopts] $file1 $file2
======

[RS]: One might say {*} is the inverse function of `[[[list]]`:

======
{*}[list a b c] <==> a b c
======

----

[RS]:  In [re_syntax], ''*'' stands for "zero or more", which is
exactly the unique cardinality of an {expand}ed item...

[DKF]: Similarly in `[[[string match]]` syntax.


** Shell Equivalents **

The [bash] equivalent of '''`{*}`''' is

======sh
${varname[@]:+"${varname[@]}"}
======


** More Examples **

======none
(Mike) 1 % set args [list range foobar 2 4]
range foobar 2 4
(Mike) 2 % string $args
unknown or ambiguous subcommand "range foobar 2 4"
(Mike) 3 % string {*}$args
oba
======

The first time, `[[[string]]` gets the entire value of `$args` as one argument,
and fails. The second time, `$args` is expanded, and `[[[string]]`, receiving 4
separate arguments, works correctly.

----

======
(wits) 49 % proc p args {puts "Number of arguments: [llength $args]"}
(wits) 50 % p {a b c}
Number of arguments: 1
(wits) 51 % p {*}{a b c}
Number of arguments: 3
======


** `{*}` in Multiple Dimensions **

[HaO]:  To flatten a matrix, one could use `{*}[[concat {*}...]`.  Example to
find the max of a matrix:

======
% set m {{1 2} {3 4}}
% tcl::mathfunc::max {*}[concat {*}$m]
4
======

The expression, `{*}[[concat {*}$m]` results in `1 2 3 4`.


** Response **

[RLH]: This is much better IMHO.

[jcw]: '''HURRAY!'''''

[SYStems]: I vote yes. I don't think though that its necessary to deprecate
`[{expand}]`, but I agree on deprecating `{}` it does look like syntax error
rather than a feature.

[RLH]: I think `[{expand}]` should be removed completely. It is not in the
language "official" yet and so it should be yanked to make sure no abuse
occurs.

[JMN]:  Well.. `{*}` looks to me like a nipple.. which is clearly better than a
wart.

** Misc **


CN slightly regrets that [{expand}] is now gone - I was looking forward to
possible future enhancements along the same line, like for example 

======
lappend mylist {sort|toupper|regmatch [0-9]+}$somelist
======

to specify a chain of filters for the expansion. But I suppose that people for
whom `[{expand}]` is a wart will classify this a as a tumor... ;-)

[DKF]: It's also trivially replacable using '''{*}[['''...''']]''' and some
commands to preprocess the list.

----

[SYStems] or you can just 

======
lappend mylist {*}[lsort [string toupper [regmatch {[0-9]+} $somelist]]]
======

The moral is that `[{*}]` is not a shorthand for other commands, but a new
feature, although for this particular example you could have just used 

======
set mylist [concat $mylist [lsort [string toupper [regmatch {[0-9]+} $somelist]]] ]
======

[AMG]: Often I need to construct a new list by combining a mixture of lists and
elements.  This is done very well by combining the [[[list]]] command and the
`[{*}]` operator.  (Is it right to call it an operator?)

======
set l1 {a b c}
set e1 d
set l2 {e f g}
set e2 {h i}
set result [list {*}$l1 $e1 {*}$l2 $e2]
======

This sets `$result` to `{a b c d e f g {h i}}`.  Equivalent non-`[{*}]` code:

======
set result $l1
lappend result $e1
set result [concat $result $l2]
lappend result $e2
======

[kpv]: Here's a better way of doing with concat (it's a question of do you
special handle the list pieces or element pieces).

======
set result [concat $l1 [list $e1] $l2 [list $e2]]
======

[AMG]: Thanks.  This clearly shows the two methods are duals of each other.
Side-by-side:

======
set result [list  {*}$l1       $e1  {*}$l2       $e2 ]
set result [concat   $l1 [list $e1]    $l2 [list $e2]]
======

In the first method, `[{*}]` is used to mark which elements are to be expanded,
and the default is to not expand.  In the second method, `[[[list]]` is used to
mark which elements are ''not'' to be expanded, and the default is to expand.
The latter approach is similar to the behavior of [Unix shells] and has led to
a lot of unsafe code when the programmer isn't careful about quoting---
apparently this default is surprising to many people.  However, it does work;
just be cautious!

[kpv]: I think both ways have an equal need for the programmer to be
''cautious'' -- forgetting the `[{*}]` is just as bad as forgetting the
`[[[list]]`. To me, with years of pre-8.5 programming experience, especially in
using `[[[eval]]`, the `[[[concat]]` method feels more natural. I'm sure that
will change as I do more 8.5+ programming.

----

[AMG]: When I have a long command but don't feel like using `\` at the end of
every line, I sometimes do the following:

======
set data [dict create {*}{
    key1 val1    key2 val2
    key3 val3    key4 val4
    key5 val5    key6 val6
}]
======

Of course, in this case I could have just left out the `[[[dict create]]` and
instead relied on the internal representation being generated the first time I
tried accessing `$data` as a `[[[dict]]`.  But the above is slightly faster and
clearer... well, except for the `[{*}]` nonsense, of course. :^)  Given a bit
of time, I'm sure I could come up with a more realistic example, but I actually
find myself doing the above in real code (if anything I write can be said to be
"real").

This usage of `[{*}]` provides quoting without grouping.  Dollar signs and
square brackets become ordinary characters, sequences of unquoted whitespace
and newlines are delimiters, and the resulting list elements (all of which are
pure strings) are placed one-after-the-other into the command's objv list
without any extra interpretation.  Backslashes, paired braces, and paired
double quotes still function as quoting/grouping characters.  ("Grouping" means
to disable the special meaning of characters that would otherwise be treated as
delimiters.)



<<categories>> Syntax | Dodekalogue}} CALL {my revision {{*}}} CALL {::oo::Obj78049 process revision/%7B%2A%7D} CALL {::oo::Obj78047 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