key_map(f, m) is equivalent to {f(k):v for (k,v) in m.items()} except that it returns a
      persistent mapping object instead of a dict. Additionally, it respects the laziness of maps
      and does not evaluate the values of a lazy map that has been passed to it.
    key_map(f, m, *args, **kwargs) uses f(k, *args, **kwargs) instead of f(k).

def key_map(f, m, *args, **kwargs):
    '''
    key_map(f, m) is equivalent to {f(k):v for (k,v) in m.items()} except that it returns a
      persistent mapping object instead of a dict. Additionally, it respects the laziness of maps
      and does not evaluate the values of a lazy map that has been passed to it.
    key_map(f, m, *args, **kwargs) uses f(k, *args, **kwargs) instead of f(k).
    '''
    if is_lazy_map(m):
        from .table import (is_itable, itable)
        def _curry_getval(k): return lambda:m[k]
        m0 = {f(k, *args, **kwargs):_curry_getval(k) for k in six.iterkeys(m)}
        return itable(m0) if is_itable(m) else lazy_map(m0)
    else:
        return ps.pmap({f(k, *args, **kwargs):v for (k,v) in six.iteritems(m)})