def vectorized(left, right, c):
        if isinstance(left, String):
            left = str(left)
        if isinstance(right, String):
            right = str(right)
        if type(left) == Expression:
            left = left.run()
        if type(right) == Expression:
            right = right.run()
        left_type = type(left)
        right_type = type(right)
        left_is_iterable = (
            hasattr(left, "__iter__") and not isinstance(left, str)
        )
        right_is_iterable = (
            hasattr(right, "__iter__") and not isinstance(right, str)
        )
        if left_is_iterable or right_is_iterable:
            if left_is_iterable and right_is_iterable:
                result = afn(left, right, c) if afn else [
                    vectorized(l, r, c) for l, r in zip(left, right)
                ]
            else:
                result = (
                    [vectorized(item, right, c) for item in left]
                    if left_is_iterable else
                    [vectorized(left, item, c) for item in right]
                )
            result_type = type(left if left_is_iterable else right)
            try:
                return result_type(result)
            except:
                return result_type(result, left if left_is_iterable else right)
        if cast_string and left_type == str:
            left = (float if "." in left else int)(left)
        if cast_string and right_type == str:
            right = (float if "." in right else int)(right)
        return fn(left, right, c)