traverse_dict_partial_key

Definition: traverse_dict_partial_key(integer rid, object pkey, object user_data=0, integer tid=1, bool rev=false)
Description: Perform an in-order traversal of the dictionary, starting from the first key greater than or equal to pkey (last key less than or equal if rev is true), invoking the specified routine for each {key,data} pairing.

rid: routine_id of a function that accepts four parameters, called for each entry.
pkey: a partial key that determines where it starts (but not where it ends).
user_data: any additional data that might be required by rid.
tid: a result from new_dict(), or if omitted it uses the one common dictionary.
rev: if true, the traversal is made from the highest key to the lowest key.
Comments: The specified routine should be a function that accepts four parameters: key, data, pkey, and user_data, and should return 1 to continue the traversal, or 0 to terminate it.

The same rid would not normally be passed to both traverse_dict_partial_key and traverse_dict, since they need to accept a different number of parameters, however that is possible if the fourth parameter is optional (has a default) and some other means is used to determine whether it received ..,user_data) or ..,pkey,user_data), such as that in the first example below.

Note: it is the responsibility of the specified routine to check key against pkey; the first key yielded may be way past the pkey asked for, and traversal will continue to the end (or start if rev is true) unless said routine returns 0, which terminates the traversal immediately.

Internally, at the start, this routine avoids processing entire sub-trees that are less than pkey and therefore cannot possibly be relevant, but does not limit any processing of larger keys/nodes/sub-trees unless explicitly told to stop. If rev is true, you could say more than pkey, but it must be stressed that pkey is only partial in the sense of what it skips at the start, not what it lets through.

The ordering is case-sensitive. If a case-insensitive ordering is required, the key values as passed to setd() [etc] should be passed through either upper() or lower() and if needs be a copy of the original case included somewhere in data.

The use of a named parameter when setting the rev flag is recommended, to make the intent clear and the code easier to read.
Example 1:
function visitor(object key, object data, object pkey, object user_data=-2)
    if user_data!=-2 and not my_idea_of_a_partial_match(key,pkey) then
        return 0
    end if
    ?{key,data}
    return 1
end function

setd("key","data")
setd("key2","data2")

traverse_dict_partial_key(routine_id("visitor"),"key1")

visitor will be called with "key2" (and everything after that). The -2 default was chosen on the assumption that no call to traverse_dict_partial_key passes that as the third parameter, and that way rule out any plain traverse_dict calls (that use the same visitor, but do not expect any "partial key mismatch early out", and in which case user_data ends up in pkey and no fourth parameter is supplied).
Example 2:
integer next_unused_key
function pvisitor(integer key, object /*data*/, object /*pkey*/, object /*user_data*/)
    next_unused_key = key+1
    return 0    -- (always cease traversal immediately)
end function

next_unused_key = 1 -- default if pvisitor not called (dict empty)
traverse_dict_partial_key(routine_id("pvisitor"),999999999,true)
See Also: setd, upper, lower, routine_id, traverse_dict