# Function Helpers

Module: `polygraphy.func`

extend(extend_func)[source]

A decorator that uses the function it decorates to extend the function provided as a parameter.

This is best illustrated with an example:

```def x(a0, a1, a2):
rv0 = [a0, a1, a2]
rv1 = None
return rv0, rv1

@extend(x)
def y(rv0, rv1):
rv0.append(-1)

# We can now call `y` as if it were `x`, and we will receive
# the return values from `x` after any modifications by `y`
rv0, rv1 = y(1, 2, 3)
assert rv0 == [1, 2, 3, -1]
assert rv1 is None
```

In this case, `extend` is essentially syntactic sugar for:

```def y(a0, a1, a2):
rv0, rv1 = x(a0, a1, a2)

# Body of `y` from previous section
rv0.append(-1)

return rv0, rv1
```

If `y` does not return anything, or returns `None`, then `extend` will ensure that the return value of `x` is forwarded to the caller. This means that `y` will provide exactly the same interface as `x`.

If y returns something other than `None`, then its return value will be provided to the caller, and the return value of `x` will be discarded.

In some cases, it may be necessary to access the parameters of `x`. If `y` takes all of `x`’s parameters prior to its usual parameters (which are the return values of `x`), then all arguments to `x` will be forwarded to `y`. Note that if `x` modifies its arguments in place, then `y` will see the modified arguments, not the original ones. For example:

```def x(x_arg):
return x_arg + 1

def y(x_arg, x_ret):
# `y` can now see both the input argument as well as the return value of `x`
assert x_ret == x_arg + 1

assert y(5) == 6
```

NOTE: This function will automatically unpack tuples returned by the function being extended. Thus, the following implementation of `x` would behave just like the one mentioned above:

```def x(a0, a1, a2):
ret = (rv0, rv1)
return ret # Tuple will be unpacked, and `y` still sees 2 parameters
```

NOTE: The decorated function must not use variadic parameters like `*args` or `**kwargs`.

Parameters

extend_func (Callable) – A callable to extend.