TIP #341 Version 1.4: Multiple 'dict filter' Patterns

This is not necessarily the current version of this TIP.


TIP:341
Title:Multiple 'dict filter' Patterns
Version:$Revision: 1.4 $
Author:Lars Hellström <Lars dot Hellstrom at residenset dot net>
State:Accepted
Type:Project
Tcl-Version:8.6
Vote:Done
Created:Thursday, 27 November 2008
Keywords:Tcl, set intersection

Abstract

The key and value forms of dict filter are generalised to allow an arbitrary number of patterns.

Specification

The two dict filter command forms

dict filter dictionary key pattern

dict filter dictionary value pattern

are generalised to

dict filter dictionary key ?pattern ...?

dict filter dictionary value ?pattern ...?

and the results are the sub-dictionaries of those keys and values respectively which match at least one of the patterns.

Rationale

Although there are dict subcommands which allow deleting some keys from a dictionary (dict remove) and inserting some keys into a dictionary (dict replace), there is no direct way of requesting the sub-dictionary which only has keys from a given list; if we think of only the set of keys in the dictionary, then we have subcommands for set minus and set union, but none for set intersection. A situation where this would be useful is that the option dictionary for a high-level procedure can contain options meant to be passed on to lower level commands, and it is necessary to extract the subdictionary of options that the lower level command would accept (since passing one which is not supported would cause it to throw an error).

There is of course already the dict filter command, which indeed returns a subdictionary of an existing dictionary, but its key form only accepts one string match pattern and therefore cannot be used to e.g. select all three of -foo, -bar, and -baz (it could select both -bar and -baz through the pattern -ba[rz], but that's neither common nor particularly readable). However, in many instances where this kind of pattern is used (notably glob, namespace export, and switch), it is possible to give several such patterns and have it interpreted as the union of the patterns. Were that the case with dict filter, the "-foo, -bar, and -baz" problem could be solved as easily as

  dict filter $opts key -foo -bar -baz

which is comparable to

  dict remove $opts -foo -bar -baz
  dict replace $opts -foo 1 -bar off -baz 42

and much nicer than the script counterpart

  dict filter $opts script {key val} {
     ::tcl::mathop::in $key {-foo -bar -baz}
  }

If the key form is generalised like this, then it seems appropriate to also generalise the value form in the same way to keep the symmetry, even though I have no immediate use-case for that feature.

Since it is generally good to Do Nothing Gracefully, the command syntax is also generalised to allow the case of no patterns at all.

Rejected Alternatives

A more direct way of meeting the motivating need would be a command dict select with the same syntax as dict remove (no pattern matching) but logic reversed. This would however be so close to dict filter ... key that extending the syntax of the latter seemed more appropriate.

An alternative to al