Check-in [0b004d697b]

Login

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

Overview
Comment:New TIP: 526
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 0b004d697b9b97127aa6c3918e5c1e474f22b19ec499e81343d086f79af2de0d
User & Date: dkf 2018-11-08 10:16:11.988
Context
2018-11-10
09:26
Add precisions in TIP #466 about spaces trimming, -spacemode options, and the fact that no -spacemode value shows text completely identical to the legacy code (slight backwards incompatibility). check-in: 489ef3ca2b user: fvogel tags: trunk
2018-11-08
10:16
New TIP: 526 check-in: 0b004d697b user: dkf tags: trunk
2018-11-06
15:18
Corrected vote record check-in: af2513fa1b user: dkf tags: trunk
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to index.json.
1

2
3
4

5
6
7
8
9
10
11
1
2
3
4

5
6
7
8
9
10
11
12

+


-
+







{"tip": {
	"526":{"url":"./tip/526.md","created":"08-Nov-2018","post-history":"","state":"Draft","tcl-version":"9.0","vote":"Pending","type":"Project","title":"# TIP 526: Make [expr] Only Accept One Argument","author":["Donal K. Fellows <[email protected]>"],"is-jest":false},
	"525":{"url":"./tip/525.md","keywords":"Tcl, testing, continuous integration","state":"Final","type":"Project","author":["Donal K. Fellows <[email protected]>"],"vote-results":"8/0/0 accepted","votes-for":"KBK, SL, AF, DGP, FV, DKF, AK, JN","votes-against":"none","created":"24-Oct-2018","title":"# TIP 525: Make Tcltest Report Overall Success in a Machine-Readable Way","post-history":"","vote":"Done","tcl-version":"8.5","votes-present":"none","is-jest":false},
	"524":{"url":"./tip/524.md","keywords":"Tcl, object orientation, customization","state":"Final","vote-summary":"Accepted 2/0/4","type":"Project","author":["Donal K. Fellows <[email protected]>"],"votes-against":"none","votes-for":"DKF, JN","created":"23-Oct-2018","title":"# TIP 524: Custom Definition Dialects for TclOO","post-history":"","vote":"Done","tcl-version":"8.7","tcl-branch":"tip-524","votes-present":"BG, KBK, FV, SL","is-jest":false},
	"523":{"url":"./tip/523.md","keywords":"queue, stack, pop","state":"Final","vote-summary":"Accepted 7/0/0","type":"Project","author":["Peter Spjuth <[email protected]>"],"votes-against":"none","votes-for":"DKF, KBK, JN, DGP, FV, SL","created":"22-Oct-2018","title":"# TIP 523: New lpop command","post-history":"","vote":"Done","tcl-version":"8.7","tcl-branch":"tip-523","votes-present":"BG","is-jest":false},
	"523":{"url":"./tip/523.md","keywords":"queue, stack, pop","state":"Final","vote-summary":"Accepted 7/0/0","type":"Project","author":["Peter Spjuth <[email protected]>"],"votes-against":"none","votes-for":"DKF, BG, KBK, JN, DGP, FV, SL","created":"22-Oct-2018","title":"# TIP 523: New lpop command","post-history":"","vote":"Done","tcl-version":"8.7","tcl-branch":"tip-523","votes-present":"none","is-jest":false},
	"522":{"url":"./tip/522.md","keywords":"tcltest, error codes","state":"Final","type":"Project","author":["Peter Spjuth <[email protected]>"],"vote-results":"8/0/0 accepted","votes-for":"KBK, SL, AF, DGP, FV, DKF, AK, JN","votes-against":"none","created":"22-Oct-2018","title":"# TIP 522: Test error codes with Tcltest","post-history":"","tcl-branch":"tip-522","vote":"Done","tcl-version":"8.7","votes-present":"none","is-jest":false},
	"521":{"url":"./tip/521.md","keywords":"Tcl, floating point, NaN, not a number","created":"21 October 2018","post-history":"","state":"Draft","tcl-version":"8.7","vote":"Pending","type":"Project","title":"# TIP 521: Floating Point Classification Functions","author":["Kevin B. Kenny <[email protected]>"],"is-jest":false},
	"520":{"url":"./tip/520.md","keywords":"Tcl, floating point, NaN, not a number","created":"18 October 2018","post-history":"","state":"Draft","tcl-branch":"tip-520","tcl-version":"8.7","vote":"Pending","type":"Project","title":"# TIP 520: Make NaN Quiet","author":["Kevin B. Kenny <[email protected]>"],"is-jest":false},
	"519":{"url":"./tip/519.md","":"","keywords":"TclOO","state":"Final","vote-summary":"Accepted 4/0/2","this tip proposes to extend the `method` subcommand of the `oo":":define` command","type":"Project","author":["Pietro Cerutti <[email protected]>"],"votes-against":"none","votes-for":"DKF, KBK, JN, SL","follows":"","oo":":define RPCClient {","created":"18-Oct-2018","title":"# TIP 519: Inline export/unexport option to TclOO method definition","the class definition in the previous example would then be as follows":"","post-history":"","vote":"Done","tcl-version":"8.7","tcl-branch":"tip-519","votes-present":"BG, FV","is-jest":false},
	"518":{"url":"./tip/518.md","keywords":"Tk","state":"Final","vote-summary":"Accepted 6/0/0","type":"Project","tk-branch":"tip518-event-last-child-unmanaged","author":["Harald Oehlmann <[email protected]>"],"votes-against":"none","votes-for":"DKF, BG, KBK, JN, FV, SL","created":"22-Sep-2018","title":"# TIP 518: Virtual Event when Last Child is not Managed any more","post-history":"","vote":"Done","tcl-version":"8.7","votes-present":"none","is-jest":false},
	"517":{"url":"./tip/517.md","keywords":"tk menu","created":"13-Sept-2018","post-history":"","state":"Final","tk-branch":"tip-517","tcl-version":"8.7","vote":"Done","type":"Project","title":"# TIP 517: Add -activerelief Configuration Option to the menu widget","author":["Francois Vogel <[email protected]>"],"is-jest":false},
	"516":{"url":"./tip/516.md","keywords":"Tcl, TclOO","state":"Final","type":"Project","author":["Donal K. Fellows <[email protected]>"],"vote-results":"4/0/5 accepted","votes-for":"DKF, JN, JD, AK","votes-against":"none","created":"7-Sept-2018","title":"# TIP 516: More OO Slot Operations","post-history":"","tcl-branch":"tip-516","vote":"Done","tcl-version":"8.7","votes-present":"BG, KBK, DGP, FV, SL","is-jest":false},
522
523
524
525
526
527
528
529
530


523
524
525
526
527
528
529


530
531







-
-
+
+
	"5":{"url":"./tip/5.md","created":"17-Oct-2000","post-history":"","state":"Final","vote":"Done","tcl-version":"8.4","type":"Project","title":"# TIP 5: Make TkClassProcs and TkSetClassProcs Public and Extensible","author":["Eric Melski <[email protected]>"],"is-jest":false},
	"4":{"url":"./tip/4.md","created":"26-Oct-2000","post-history":"","state":"Draft","vote":"Pending","type":"Informative","title":"# TIP 4: Tcl Release and Distribution Philosophy","discussions-to":"news:comp.lang.tcl","author":["Brent Welch <[email protected]>","Donal K. Fellows <[email protected]>","Larry W. Virden <[email protected]>","Larry W. Virden <[email protected]>"],"is-jest":false},
	"3":{"url":"./tip/3.md","created":"14-Sep-2000","post-history":"","state":"Accepted","vote":"Done","type":"Process","title":"# TIP 3: TIP Format","author":["Andreas Kupries <[email protected]>","Donal K. Fellows <[email protected]>"],"is-jest":false},
	"2":{"url":"./tip/2.md","created":"12-Sep-2000","post-history":"","state":"Draft","vote":"Pending","type":"Process","title":"# TIP 2: TIP Guidelines","author":["Andreas Kupries <[email protected]>","Donal K. Fellows <[email protected]>","Don Porter <[email protected]>","Mo DeJong <[email protected]>","Larry W. Virden <[email protected]>","Kevin Kenny <[email protected]>"],"is-jest":false},
	"1":{"url":"./tip/1.md","created":"14-Sep-2000","post-history":"","state":"Active","vote":"No voting","type":"Informational","title":"# TIP 1: TIP Index","author":["TIP Editor <[email protected]>"],"is-jest":false},
	"0":{"url":"./tip/0.md","created":"11-Dec-2000","post-history":"","state":"Final","vote":"Done","type":"Process","title":"# TIP 0: Tcl Core Team Basic Rules","author":["John Ousterhout <[email protected]>"],"is-jest":false},
	"@min": 0,
	"@max": 525
}, "@timestamp": 1541517293}
	"@max": 526
}, "@timestamp": 1541672033}
Changes to index.md.
116
117
118
119
120
121
122








123
124
125
126
127
128
129
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137







+
+
+
+
+
+
+
+







<th>Type</th>
<th>Tcl Version</th>
<th>Status</th>
<th>Title</th>
<th>Impl.</th>
</tr></thead><tbody>

<tr class='project projectdraft projectdraft90 project90'>
<td valign='top'><a href='./tip/526.md'>526</a></td>
<td valign='top'>Project</td>
<td valign='top'>9.0</td>
<td valign='top'>Draft</td>
<td valign='top'># TIP 526: Make [expr] Only Accept One Argument</td>
<td></td>
</tr>
<tr class='project projectfinal projectfinal85 project85'>
<td valign='top'><a href='./tip/525.md'>525</a></td>
<td valign='top'>Project</td>
<td valign='top'>8.5</td>
<td valign='top'>Final</td>
<td valign='top'># TIP 525: Make Tcltest Report Overall Success in a Machine-Readable Way</td>
<td></td>
Added tip/526.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# TIP 526: Make [expr] Only Accept One Argument
	Author:         Donal K. Fellows <[email protected]>
	State:          Draft
	Type:           Project
	Vote:           Pending
	Created:        08-Nov-2018
	Tcl-Version:    9.0
	Post-History:
------

# Abstract

This TIP proposes that `expr` should only accept a single argument and stop
accepting and concatenating arguments.

# Rationale and Discussion

A very common fault of `expr` usage is to fail to brace expressions. This was
semi-good practice in Tcl 7.6 and before as Tcl's substitution phase was
faster than the expression evaluation engine's, but it was always a little
tricky even then as it depended on you being sure that the substituted values
were numeric for safety. When that critical side condition didn't hold, it
resulted in unsafe code:

    proc addFive {x} {
        expr $x + 5
    }
    puts [addFive 17];                 # ==> 22
    puts [addFive {[exec format C:]}]; # OOPS!

From Tcl 8.0 onwards, this was no longer a good idea. The bytecode compiler is
able to generate compiled code ahead of time for braced expressions, but is
not able to do so (usefullly) if any of the arguments to `expr` are unbraced.
Of course, we want to be able to use an unbraced argument occasionally, such
as when we take an expression as an argument from elsewhere, but those are
very much the unusual case: almost always, a call to `expr` with any argument
unbraced is _both_ a performance bug and a security bug.

Because this is so strongly the case, there are uses of Tcl that are almost
always a problem; for example:

    expr $x >= "inf";   # where $x is expected to be a string

# Proposal

To reduce the incidence of this, I propose that in Tcl 9.0 the `expr` command
should only take a single argument. It most definitely isn't a total fix for
this — a total fix isn't really possible without making the `expr` command
special in the Tcl base language, and that goes against the general principle
that _nothing_ is special there — but it will at least reduce the incidence a
bit by encouraging people to either brace their expressions or be very clear
that they are not doing so.

This will leave virtually all correct code working, and yet force code that
has a problem to acknowledge the fact.

Supported cases:

 1. Braced expressions:

        expr {$x * 5}

 2. Expressions in variables:

        set theExpression {$x * 5}
        expr $theExpression

 3. Expressions from commands:

        expr [dict get $myExpressions thisCase]

Cases that work because we can't stop them without breaking the language:

 1. Expressions in double quotes:

        expr "$x * 5"

 2. Expressions with unquoted compound substitutions:

        expr $x*5+[llength $y]

Cases that are outright rejected:

 1. Expressions with multiple arguments:

        expr $x * 5

 2. Expressions with multiple literal arguments (uncommon):

        expr {$x} *5

## Workarounds for Broken Old Code

The cases where someone genuinely needs the old behaviour can be handled by
them using `concat` (or `string cat`, depending on exact requirements)
explicitly to make the expression:

    set x {2 + 3}
    expr [concat $x * 5]

That still has the faults, but now at least looks like it is doing something
tricky. Which it is, given that the actual behaviour of the equivalent code in
Tcl 8 is so messy. Another alternative (and a better one in this particular
case) is:

    set x {2 + 3}
    expr {[expr $x] * 5}

That also looks weird, but is better in that it only has the potential for
trouble in one place and allows for better compilation of the outer parts of
the expression. (Yes, it produces a different result from the other code. This
is likely to be a good thing in almost all cases.)