Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Avoiding errors on lset?

43 views
Skip to first unread message

Alexandru

unread,
Jun 26, 2018, 12:15:11 AM6/26/18
to
When using lset with an index larger than available in the list, the function returns an error. I find this annoying for my usage and I wrote a procedure that avoids this. What do you think of this code? Does it make sense or even it could be an improvement to the actual "lset" function?

## This procedure works like Tcl's "lset" but avoids errors when the requested list index is not available in list.
# Variable with provided "varname" is written.
# \param varname name of list variable
# \param idx list index to set
# \param value value for list index to set
# \param defval optional default value for non-existent list indexes
# return new list value.
proc LSet {varname idx value {defval ""}} {
upvar $varname l
set nelem [llength $l]
if {$nelem<[expr {$idx+1}]} {
lappend l {*}[lrepeat [expr {$idx+1-$nelem}] $defval]
}
lset l $idx $value
}

Arjen Markus

unread,
Jun 26, 2018, 5:20:48 AM6/26/18
to
Just a remark: [lset] can take several indices to handle nested lists. If you intend to use this as a general wrapper, then you will need to take care of that usage too - which will complicate the use of a default, I guess.

Regards,

Arjen

stefan

unread,
Jun 26, 2018, 6:48:14 AM6/26/18
to
> Does it make sense or even it could be an improvement to the actual "lset" function?

I haven't measured the difference, but I'd consider Tcl's on-board mechanisms first (error codes). This is my take (without proper arg handling, obviously).

proc LSet {args} {

if {[lindex $args 0] eq "-nocomplain"} {
set args [lassign $args withNoComplain]
}

try {
uplevel 1 lset {*}$args
} trap {TCL OPERATION LSET BADINDEX} {msg opts} {
if {![info exists withNoComplain]} {
return -options $opts $msg
}
}
}

- the "-nocomplain" is more what you are after (as used in other places like unset)

- lset provides a proper errorcode (TCL OPERATION LSET BADINDEX) to trap (either using try or catch)

- I agree with Arjen that defaults won't work here (besides, there is no default for [set] either)

- "Does it make sense": [lset] alone is not compelling for me, personally, but there appear to be some inconsistency with handling valid and invalid list ranges between commands (bad index has different failure semantics in lrange than in lset, for example). Arriving at consistency here is more of a priority, IMHO.

Stefan

stefan

unread,
Jun 26, 2018, 6:56:27 AM6/26/18
to
besides, your range or index check does not cover all possible types of index specification allowed for list commands (relative ones) so your [LSet] is not a full or drop-in replacement of [lset].

> if {$nelem<[expr {$idx+1}]} {

Note: no [expr] needed in an expression.

Alexandru

unread,
Jun 26, 2018, 7:23:26 AM6/26/18
to
Oh, this is new to me: The first term of "if" is already interpreted as "expr"?

stefan

unread,
Jun 26, 2018, 7:40:16 AM6/26/18
to
> > > if {$nelem<[expr {$idx+1}]} {
> >
> > Note: no [expr] needed in an expression.
>
> Oh, this is new to me: The first term of "if" is already interpreted as "expr"?

Exactly. From the [if] manpage: "The if command evaluates expr1 as an expression (in the same way that [expr] evaluates its argument) [...]"

0 new messages