<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def apply(self, func, mapping=None, new_dtype=None, **kwargs):
 """Apply an element-wise UDF to the Series. There are currently 6 options for using a UDF. First 4 are lazy, other 2 are eager and require the use of the raw decorator: - One of the predefined functions in baloo.functions. - Implementing a function which encodes the result. kwargs are automatically passed to it. - Pure Weld code and mapping. - Weld code and mapping along with a dynamically linked C++ lib containing the UDF. - Using a NumPy function, which however is EAGER and hence requires self.values to be raw. Additionally, NumPy does not support kwargs in (all) functions so must use raw decorator to strip away weld_type. - Implementing an eager function with the same precondition as above. Use the raw decorator to check this. Parameters func : function or str Weld code as a str to encode or function from baloo.functions. mapping : dict, optional Additional mappings in the weld_template to replace on execution. self is added by default to reference to this Series. new_dtype : numpy.dtype, optional Specify the new dtype of the result Series. If None, it assumes it's the same dtype as before the apply. Returns ------- Series With UDF result. Examples -------- <BLANKLINE> --- -- 0 3 1 4 2 5 <BLANKLINE> --- -- 0 4 1 5 2 6 <BLANKLINE> --- -- 0 1 1 2 2 10 <BLANKLINE> --- -- 0 1 1 2 2 3 3 4 <BLANKLINE> --- -- 0 1 1 2 2 3 3 4 <BLANKLINE> --- -- 0 1 1 2 2 3 3 4 # check tests/core/cudf/* and tests/core/test_series.test_cudf for C UDF example """

        if callable(func):
            return Series(func(self.values,
                               weld_type=self.weld_type,
                               **kwargs),
                          self.index,
                          self.dtype,
                          self.name)
        elif isinstance(func, str):
            check_type(mapping, dict)
            check_dtype(new_dtype)

            default_mapping = {'self': self.values}
            if mapping is None:
                mapping = default_mapping
            else:
                mapping.update(default_mapping)

            if new_dtype is None:
                new_dtype = self.dtype

            return Series(weld_udf(func,
                                   mapping),
                          self.index,
                          new_dtype,
                          self.name)
        else:
            raise TypeError('Expected function or str defining a weld_template')