code: def _substitute(self, expr, mapping):
          
          node = expr.op()
          try:
              return mapping[node]
          except KeyError:
              if node.blocks():
                  return expr
  
              new_args = list(node.args)
              unchanged = True
              for i, arg in enumerate(new_args):
                  if isinstance(arg, ir.Expr):
                      new_arg = self.substitute(arg, mapping)
                      unchanged = unchanged and new_arg is arg
                      new_args[i] = new_arg
              if unchanged:
                  return expr
              try:
                  new_node = type(node)(*new_args)
              except IbisTypeError:
                  return expr
  
              try:
                  name = expr.get_name()
              except ExpressionError:
                  name = None
              return expr._factory(new_node, name=name)
docs: Substitute expressions with other expressions.
  
          Parameters
          ----------
          expr : ibis.expr.types.Expr
          mapping : Mapping[ibis.expr.operations.Node, ibis.expr.types.Expr]
  
          Returns
          -------
          ibis.expr.types.Expr