# Data structures

import lists
import util

def rmap(func, value, levels=None):
    '''Recursively applies func to all members of value
    @param func(value, is_leaf):value
    '''
    expand = util.coalesce(levels, 1) > 0 and (lists.is_seq(value)
        or isinstance(value, dict)) # whether value would be expanded
    value = func(value, not expand)
    
    if expand: # does nothing if func() returned a type that won't be expanded
        levels = util.do_ignore_none(lambda v: v-1, levels)
        rmap_ = lambda v: rmap(func, v, levels)
        if lists.is_seq(value): value = map(rmap_, value)
        elif isinstance(value, dict):
            value = dict(((k, rmap_(v)) for k, v in value.iteritems()))
    
    return value
