TIP 577: Strict index values

Login
Bounty program for improvements to Tcl and certain Tcl packages.
Author:         Jan Nijtmans <jan.nijtmans@gmail.com>
State:          Draft
Type:           Project
Created:        8-June-2020
Post-History:   
Keywords:       Tcl index
Tcl-Version:    8.7
Tcl-Branch:     strict-index

Abstract

Various commands handle errors in "index" values differently. This TIP attempts to treat the different uses of index values (in both Tcl and Tk) to a more uniform way.

Rationale

Some examples (Tk):

$ wish8.6
% listbox .l
% menu .m
% .l index 0
0
% .l index none
bad listbox index "none": must be active, anchor, end, @x,y, or a number
% .m index none
none
% .m index 0
none
% .m index foo
bad menu entry index "foo"

More examples (Tcl):

$ tclsh8.6
% lreplace {a b c} -1 -1 d
d a b c
% lreplace {a b c} -2 -2 d
d a b c
% set x {a b c}
a b c
% lset x 0 d
d b c
% lset x -1 d
list index out of range

Changing any of the above examples to give a different answer is not possible in the Tcl 8.x timeline, as it could cause applications to break unexpectedly. But this examples make it clear that the responses -1 and none are used often to mean the same thing. For Tcl 9 more can be done, but more investigation is needed to determine whether none or maybe the empty string would be a better fit here. Also, whether a command gives an error-message on an invalid index or bails out cannot be changed in the Tcl 8.x timeline.

Since they are often causes of bugs, this TIP makes the step to deprecate the use of indices < -1 and > end+1. Such indices normally result from code loops which don't properly check for the end condition. Therefore, those indices will no longer be valid indices in Tcl 9.

It would be tempting to change Tcl 9 such that none or the empty string is used as return value in stead of -1. That change is not made yet in this TIP, more experimenting is needed to determine the impact that would have.

Specification

  • The C function Tcl_GetIntForIndex() will get an additional flags parameter, which holds any combination of 3 possible flags (could be extended further in the future):
    • TCL_INDEX_ERROR: Handle -2 (and lower) and end+2 (and higher) as invalid index.
    • TCL_INDEX_NOMIN: Handle -1 as invalid index (when TCL_INDEX_ERROR is set), or as the same as index "0".
    • TCL_INDEX_NOMAX: Handle end+1 as invalid index (when TCL_INDEX_ERROR is set), or as the same as index "end". The default flag value 0, will behave as-is now, accepting all forms as valid. Starting with Tcl 9.0, all internal Tcl_GetIntForIndex() calls will at least supply the TCL_INDEX_ERROR flag value to this function.
  • Values none and the empty string are now valid indices, representing "just before the first". Commands that accept either a single index or a list of indices will handle the empty string as empty list, not as a single index.
  • New functions "string is none" and "string is index".
  • Starting with Tcl 9.0, integers < -1 and forms end+x where x > 1 will no longer be valid indexes any more.
  • For Tk, start accepting all those same values as indices for entries, listboxes, menus ..... and also for button and menu-related -underline options. A new TK_OPTION_INDEX option is implemented, which is almost the same as TK_OPTION_INT, but in stead of only integers, accepts all index forms as well. See: widgets indices enhancement

Compatibility

For Tcl 8.7 this is almost 100% compatible, previous error-situations become valid now: Index value none can now be used in place of -1, just as the empty string "".

Since, starting with Tcl 9.0, some index forms are no longer valid, this is a potential incompatibility. Indices like -2 and end+2 can no longer be used in scripts: they will immediately result in an "index out of range" error, in stead of being silently ignore.

Implementation

See the strict-index branch.

For Tk, see the strict-index branch.

Copyright

This document has been placed in the public domain.

History