itable(...) yields a new immutable table object from the given set of arguments. The arguments
      may be any number of maps or itables followed by any number of keyword arguments. All the
      entries from the arguments and keywords are collapsed left-to-right (respecting laziness),
      and the resulting column set is returned as the itable. Arguments and maps may contain
      values that are functions of zero arguments; these are considered lazy values and are not
      evaluated by the itable function.

def itable(*args, **kwargs):
    '''
    itable(...) yields a new immutable table object from the given set of arguments. The arguments
      may be any number of maps or itables followed by any number of keyword arguments. All the
      entries from the arguments and keywords are collapsed left-to-right (respecting laziness),
      and the resulting column set is returned as the itable. Arguments and maps may contain
      values that are functions of zero arguments; these are considered lazy values and are not
      evaluated by the itable function.
    '''
    # a couple things we want to check first... does our argument list reduce to just an empty
    # itable or just a single itable?
    if len(args) == 0 and len(kwargs) == 0:
        return ITable({}, n=0)
    elif len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], ITable):
        return args[0]
    # we want to try to convert any arguments we can from datatables into maps
    try:
        import pandas
        args = [{k:a[k].values for k in a.keys()} if isinstance(a, pandas.DataFrame) else a
                for a in args]
    except: pass
    # now we want to merge these together and make them one lazy map
    m0 = lazy_map(merge(args, kwargs))
    # see if we can deduce the row size from a non-lazy argument:
    v = next((m0[k] for k in six.iterkeys(m0) if not m0.is_lazy(k)), None) if is_lazy_map(m0) else \
        None
    if v is None:
        k = next((u for u in six.iterkeys(m0)), m0)
        if k is m0: v = None
        else: v = m0[k]
    return ITable(m0, n=(None if v is None else len(v)))