Tcl Source Code

View Ticket
Login
2014-06-15
16:15 Closed ticket [1b0266d8bb]: Single-argument dict merge/remove/replace plus 5 other changes artifact: bbe8a3c826 user: dkf
16:14
[1b0266d8bb] Make [dict replace] and [dict remove] have canonicalization semantics close to [lrange]... check-in: 847fa2261d user: dkf tags: trunk, potential incompatibility
15:36 Ticket [1b0266d8bb] Single-argument dict merge/remove/replace status still Open with 4 other changes artifact: 95daacef5f user: dkf
07:59 Ticket [1b0266d8bb]: 4 changes artifact: 8686330bc1 user: dkf
2014-06-03
07:31 Ticket [1b0266d8bb]: 4 changes artifact: 0fa6340089 user: dkf
07:26
[1b0266d8bb] Working towards ensuring that all dict operations are sufficiently strict. check-in: 064f886aae user: dkf tags: bug-1b0266d8bb
07:09 Ticket [1b0266d8bb] Single-argument dict merge/remove/replace status still Open with 4 other changes artifact: 4cf7a8fb1d user: dkf
06:59 Ticket [1b0266d8bb]: 4 changes artifact: 0532e16db5 user: dkf
2014-05-21
23:16 Ticket [1b0266d8bb]: 3 changes artifact: 1306529e02 user: aku
22:58 New ticket [1b0266d8bb]. artifact: 0c0ca53d92 user: andy

Ticket UUID: 1b0266d8bbc649bcb4df5dc4a1edca238536262b
Title: Single-argument [dict merge/remove/replace]
Type: Bug Version: cdc4e05235717e4959d745e4cc6670bd1333c783
Submitter: andy Created on: 2014-05-21 22:58:03
Subsystem: 15. Dict Object Assigned To: dkf
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2014-06-15 16:15:11
Resolution: Fixed Closed By: dkf
    Closed on: 2014-06-15 16:15:11
Description:
When given only one argument, [dict remove] and [dict replace] seem to return that argument without even looking at it.  Consequently, they can be made to return non-dicts (i.e. invalid list or odd list length) and noncanonical dicts (i.e. with duplicate keys).

When given only one argument, [dict merge] forces the argument to be a dict (thereby rejecting non-lists and odd-length lists), but the string representation is preserved.  Consequently, [dict merge] can be made to return noncanonical dicts.

% dict remove \{\}x
{}x
% dict remove {a 1 b}
a 1 b
% dict remove {a 1 b 2 a 3}
a 1 b 2 a 3
% dict replace \{\}x
{}x
% dict replace {a 1 b}
a 1 b
% dict replace {a 1 b 2 a 3}
a 1 b 2 a 3
% dict merge \{\}x
list element in braces followed by "x" instead of space
% dict merge {a 1 b}
missing value to go with key
% dict merge {a 1 b 2 a 3}
a 1 b 2 a 3
% ::tcl::unsupported::representation [dict merge {a 1 b 2}]
value is a dict with a refcount of 3, object pointer at 0xbeb3b0, internal representation 0xbe11a0:0xbeb860, string representation "a 1 b 2"
% ::tcl::unsupported::representation [dict merge {a 1 b 2 a 3}]
value is a dict with a refcount of 5, object pointer at 0x1c3a560, internal representation 0x1c843a0:0x1c35790, string representation "a 1 b 2 a 3"

Contrast with every other [dict] command that returns a dict and/or sets a dict variable.  They all produce only canonical dicts.

% dict get {a 1 b 2 a 3}
a 3 b 2
% ::tcl::unsupported::representation [dict get {a 1 b 2 a 3}]
value is a list with a refcount of 1, object pointer at 0x99cc90, internal representation 0x9adb00:(nil), no string representation
% ::tcl::unsupported::representation [dict get {a 1 b 2}]
value is a list with a refcount of 1, object pointer at 0x9a09e0, internal representation 0x9db0e0:(nil), no string representation
User Comments: dkf added on 2014-06-15 15:36:27:

In fact, I completely refuse to promise canonicalization with dict merge, as that causes problems in compilation.


dkf added on 2014-06-15 07:59:29:

On the other hand, having dict replace and dict remove guarantee canonicality in their result (as long as it doesn't leak back into the argument) is reasonable; they parallel with lrange's features in this area.

I think dict merge doesn't need the change, as that feels more like it's working with whatever people provide; it merges your dictionaries.


dkf added on 2014-06-03 07:31:08:

Uncovered an issue when working on this; the error message is wrong.

test dict-4.14 {dict replace command: type check is mandatory} -body {
    dict replace { a b {}c d }
} -returnCodes error -result {list element in braces followed by "c" instead of space}
It's a bit tricky to fix; the message comes out of TclFindElement and that both has a semi-exposed API and no way to actually affect it at the moment.


dkf added on 2014-06-03 07:09:53:

To be exact, canonicality comes from the modification causing a purge of the old string representation. Consider this:

% dict merge {
  a b
  c d
} {} {} {}

  a b
  c d

% dict merge {
  a b
  c d
} {a b}
a b c d
(No, we aren't going to detect where a modification “does nothing”.)


dkf added on 2014-06-03 06:59:39:

I think the non-canonicality is OK; the code isn't guaranteed to canonicalize when it doesn't have anything to do. However, the failure to confirm the format is indeed an (arguable) bug.

It'd be a Potential Incompatibility though.