Check-in [001cc04be5]

Login
Bounty program for improvements to Tcl and certain Tcl packages.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:New TIP 505.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 001cc04be521194d3498598351db990daa1ca8db237b1e035f15be0d31784035
User & Date: dgp 2018-03-26 16:01:29
Context
2018-03-26
19:03
IMplementation now on the branch. check-in: a159e3a950 user: dgp tags: trunk
16:01
New TIP 505. check-in: 001cc04be5 user: dgp tags: trunk
2018-03-21
19:07
New TIP 504 check-in: 7f50ba4aca user: dgp tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to index.json.

cannot compute difference between binary files

Changes to index.md.

87
88
89
90
91
92
93







94
95
96
97
98
99
100
<th>#</th>
<th>Type</th>
<th>Tcl Version</th>
<th>Status</th>
<th>Title</th>
</tr></thead><tbody>








<tr class='project projectdraft projectdraft87 project87'>
<td valign='top'><a href='./tip/504.md'>504</a></td>
<td valign='top'>Project</td>
<td valign='top'>8.7</td>
<td valign='top'>Draft</td>
<td valign='top'># TIP 504: New subcommand [string insert]</td>
</tr>






>
>
>
>
>
>
>







87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<th>#</th>
<th>Type</th>
<th>Tcl Version</th>
<th>Status</th>
<th>Title</th>
</tr></thead><tbody>

<tr class='project projectdraft projectdraft86 project86'>
<td valign='top'><a href='./tip/505.md'>505</a></td>
<td valign='top'>Project</td>
<td valign='top'>8.6.9</td>
<td valign='top'>Draft</td>
<td valign='top'># TIP 505: Make [lreplace] Accept All Out-of-Range Index Values</td>
</tr>
<tr class='project projectdraft projectdraft87 project87'>
<td valign='top'><a href='./tip/504.md'>504</a></td>
<td valign='top'>Project</td>
<td valign='top'>8.7</td>
<td valign='top'>Draft</td>
<td valign='top'># TIP 504: New subcommand [string insert]</td>
</tr>

Added tip/505.md.










































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# TIP 505: Make [lreplace] Accept All Out-of-Range Index Values
	Author:         Don Porter <[email protected]>
	State:          Draft
	Type:           Project
	Vote:           Pending
	Created:        26-Mar-2018
	Post-History:   
	Tcl-Version:	8.6.9
-----

# Abstract

Create a consistent rule to control how [lreplace] treats indices
out of the range of a list's collection of elements.

# Background

Using Tcl 8.5 we can examine how [lreplace] has been working as far back
as we can test.

	% lreplace a -5 -4 b
	b a
	% lreplace a -5 -1 b
	b a
	% lreplace a -5 0 b
	b
	% lreplace a -5 5 b
	b
	% lreplace a -1 -1 b
	b a
	% lreplace a -1 0 b
	b
	% lreplace a -1 5 b
	b

So it is clear that negative index values are tolerated, and all of
them are treated the same and they all anchor the replacement at
the beginning of the list so that [lreplace] may be used to prepend
to the list. Contrast with the treatment of index values beyond the
end of the list:

	% lreplace a 1 1 b
	list doesn't contain element 1

So index values pointing past the end of the list are rejected, and
[lreplace] cannot be used to append to a list.

Of course, no Tcl inconsistency would be complete without its own
inconsistency:

	% lreplace {} 0 0 b
	b
	% lreplace {} 1 1 b
	b
	% lreplace {} 20 40 b
	b

So operating on an empty list apparently suspends the index value checking,
and you can append once to an empty list, but no more after that.

This situation is ridiculous.

Active readers at this point might well be trying it out for
themselves and are about to correct me...

	% info patchlevel
	8.6.8
	% lreplace a 1 1 b
	a b
	% lreplace a 2 2 b
	list doesn't contain element 2

The 8.6.\* patchlevels have exhibited a variety of behaviors,
courtesy of a number of buggy attempts to bytecode [lreplace].
Some releases have tolerated all index values beyond the end
of the list.  Recent ones have tolerated only the index value
*end+1* or equivalent. None of these functional changes were 
TIPped. They are simply the result of sensible programmers having
a natural instinct to produce sensible results when they are
writing code or fixing bugs. The test suite offered no constraint
to keep us consistent with the weird incumbent functionality.

A fresh round of bug-fixing on the core-8-6-branch has restored
consistency with 8.5 behavior, which gets us back to where out
TIP history justifies us, but which is a return to the ridiculous.
I don't want to return to the ridiculous, so here is the TIP to
bless sensible treatment of index values beyond the end of list,
consistent with how other built-in Tcl commands behave.

# Proposal

Starting with Tcl 8.6.9, [lreplace] will accept all syntactically 
valid index values, without any regard to whether they indicate an
element not in the list. All index values that point before the
beginning of a list are to continue to be treated as the index
value *-1*, pointing at the beginning of the list. This allows
[lreplace] to prepend. All index values that point past the end of
the list will from now on be treated as the index value *end+1*,
pointing at the end of the list. This allows [lreplace] to append.

# Compatibility

Given the mess of the 8.6.\* releases, it's almost a joke to
worry about compatibility, but compared with Tcl 8.5, this
change is a conversion of an error case to a well-defined and
useful working case. This is the kind of incompatibility we
normally accept as an expansion of useful functionality.

# Implementation

Is easy to do, but not yet on any branch. Watch for a tip-505 branch
to provide it.

# Copyright

This document has been placed in the public domain.