<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def mutate(table, exprs=None, **mutations):
 """ Convenience function for table projections involving adding columns Parameters exprs : list, default None List of named expressions to add as columns mutations : keywords for new columns Returns ------- mutated : TableExpr Examples -------- Using keywords arguments to name the new columns ref_0 UnboundTable[table] name: t schema: foo : float64 bar : float64 <BLANKLINE> Selection[table] table: Table: ref_0 selections: Table: ref_0 baz = Literal[int8] 5 qux = Add[float64*] left: foo = Column[float64*] 'foo' from table ref_0 right: bar = Column[float64*] 'bar' from table ref_0 Using the :meth:`ibis.expr.types.Expr.name` method to name the new columns True """

    if exprs is None:
        exprs = []
    else:
        exprs = util.promote_list(exprs)

    for k, v in sorted(mutations.items(), key=operator.itemgetter(0)):
        if util.is_function(v):
            v = v(table)
        else:
            v = as_value_expr(v)

        exprs.append(v.name(k))

    has_replacement = False
    for expr in exprs:
        if expr.get_name() in table:
            has_replacement = True

    if has_replacement:
        by_name = dict((x.get_name(), x) for x in exprs)
        used = set()
        proj_exprs = []
        for c in table.columns:
            if c in by_name:
                proj_exprs.append(by_name[c])
                used.add(c)
            else:
                proj_exprs.append(c)

        for x in exprs:
            if x.get_name() not in used:
                proj_exprs.append(x)

        return table.projection(proj_exprs)
    else:
        return table.projection([table] + exprs)