A
scripted list is a Tcl
script in which every
word of every
command becomes a value in the resulting list, with the first word of each command being considered just another value instead of being used as the command name.
See Also edit
- scripted templates
- a twist on scripted lists
- Convenient list arguments - larg
- a similar idea from jcw
Download edit
In addition to the full implementation below,
sl is also available as
ycl list sl.
Description edit
One way to look at a Tcl script is as a sequence of words that are grouped into commands. The
sl command presented below extracts those words into a single list while obeying the semantics of a Tcl script. Representing a list in this way, as a Tcl script, allows for elements on multiple lines without having to escape the newline, and also allows for comments between words in the list.
For example a
switch can contain comments between its blocks:
set grail 42
switch $answer [sl {
#set course for Traal
{a lurgid bee} {
lindex {Do not be alarmed}
}
#By Agrajag!
$grail {
lindex {Oh no, not again.}
}
#clueless Golgafrinchams
default {
puts [list whoa $answer]
error {get your cave redecorated!}
}
}]
the following procedure employs
commands to provide the described behaviour:
proc sl script {
concat {*}[lmap part [commands $script] {
if {[string match #* $part]} continue
uplevel 1 list $part
}]
}
Larry Smith It occurs to me a little
Sugar that substituted the [sl from 'begin' or 'do' and 'end' to ']' makes this concept quite readable:
set grail 42
switch $answer do {
#set course for Traal
{a lurgid bee} {
lindex {Do not be alarmed}
}
#By Agrajag!
$grail {
lindex {Oh no, not again.}
}
#clueless Golgafrinchams
default {
puts [list whoa $answer]
error {get your cave redecorated!}
}
} end
or even do-> "[sl {" and end->"} ]"
set grail 42
switch $answer do
#set course for Traal
{a lurgid bee} {
lindex {Do not be alarmed}
}
#By Agrajag!
$grail {
lindex {Oh no, not again.}
}
#clueless Golgafrinchams
default {
puts [list whoa $answer]
error {get your cave redecorated!}
}
end
Since the scripted list command "sl" itself can be coded to expand macros, this makes for a convenient escape from the strictures of escaped newlines or lots of braces. It does kind of change the feel of the language and I'm not sure how far one should take this, but if I were inclined to add macros built-in to the language this might be a nice way to go.
jsuntheimer72 applauds wildly for this idea ^
Another use for a scripted list is in parsing data formatted as a Tcl script:
proc configure script {
foreach command [cmdSplit $script] {
set command [namespace eval configns [
list [namespace which sl] $script]]
set cmdargs [lassign $command name]
switch $name {
someparameter {
do something with $cmdargs
}
someotherparameter {
do something with $cmdargs
}
}
}
}
A Twisted Scripted List edit
This list is a twist on the standard scripted list in which only the first command in a series of semicolon-separated commands becomes part of the result. The additional commands in such a series of commands might have side effects that influence the composition of the list. The current examples don't show a compelling use case, but perhaps someone will do something interesting with it.
Exampleset mylist [sl {
one
two three ;#this is a comment
$somevar
#ha ha! a two-line \
comment in the list!
[some command]
{;} ;#literal semicolons must be escaped
{some literal}
"some $substituted[value]"
}]
More Complex Example set six six
proc some {args} {
return {seven eight}
}
proc value {} {
return {nine ten}
}
proc side {args} {
upvar var2 var2
set var2 twelve
}
set substituted eleven
set mylist [sl {
one
two three ;#this is a comment
{four five}
$six
#this is a a two-line \
comment in the list!
[some command]
{;} ;#literal semicolons must be escaped
"[value] $substituted"
only the first command in a line gets the special scripted list treatment, \
but then only the value of the last command in a line counts, which \
means that this line is like a comment with [side effects], and its \
result that of the last command in the line; set var2
}]
puts $mylist
Output:
one two three {four five} six {seven eight} {;} {nine ten eleven} twelve
The Twisted Implementation edit
proc sl_twisted script {
set res {}
set parts {}
foreach part [split $script \n] {
lappend parts $part
set part [join $parts \n]
#add the newline that was stripped because it can make a difference
if {[info complete $part\n]} {
set parts {}
set part [string trim $part]
if {$part eq {}} {
continue
}
if {[string index $part 0] eq {#}} {
continue
}
#Here, the double-substitution via uplevel is intended!
lappend res {*}[uplevel list $part]
}
}
if {$parts ne {}} {
error [list {incomplete parts} [join $parts]]
}
return $res
}
The following was migrated here from
Additional string functions:
Substitution that Preserves Grouping RHS 2005-02-23: There have been a number of times where I have wanted a version of
subst that preserves grouping. For example, I want to be able to do the following:
% array set myarr [subst {
a $x
b [getConfigValue something]
c {
a b
c d
}
}]
% array get myArr
a 1 b blah c {
a b
c d
}
My main reason for this is, when the dataset get large, I tend to find \ line continuations fairly ugly... That, and my emacs config doesn't indent well for multiple levels of line continuations if there's sub levels.
In pursuit of the above, I came up with the following:
proc gsubst input {
set data {}
foreach line [split $input \n] {
if {[info complete $data]} {
append data " $line"
} else {
append data "\n$line"
}
}
uplevel 1 list $data
}
The above proc should, in theory, cause the following two to work exactly the same
list a 1 \
b $x \
c {
1
2
} \
d [somecommand]
gsubst {
a 1
b $x
c {
1
2
}
d [somecommand]
}
PYK 2015-10-23: Because it's using a less robust implementation of
commands,
gsubst chokes on semicolon-delimited commands and does not ignore comments. Also, to properly split a script into commands, it should be
[info complete $data]\n rather than
[info complete $data] but the false positive doesn't cause any problems because the newlines that delimit commands are just getting filtered out anyway.
Page Authors edit
- RHS
- PYK
- aspect