# Docstring Examples#

After writing the general docstrings, the final step is to add helpful examples to the docstrings.

There are eight types of examples, which each need to be added:

**Functional** examples show the function being called like so `ivy.func_name(...)`

, and these should be added to docstring of the function in the Ivy API `ivy.func_name()`

.

**Container static method** examples show the method being called like so `ivy.Container.static_func_name(...)`

, and these should be added to the docstring of the static container method `ivy.Container.static_func_name()`

.

**Array instance method** examples show the method being called like so `x.func_name(...)`

on an `ivy.Array`

instance, and these should be added to the docstring of the `ivy.Array`

instance method `ivy.Array.func_name()`

.

**Container instance method** examples show the method being called like so `x.func_name(...)`

on an `ivy.Container`

instance, and these should be added to the docstring of the `ivy.Container`

instance method `ivy.Container.func_name()`

.

**Array operator** examples show an operation being performed like so `x + y`

with `x`

being an `ivy.Array`

instance, and these should be added to the docstring of the `ivy.Array`

special method `ivy.Array.__<op_name>__()`

.

**Array reverse operator** examples show an operation being performed like so `x + y`

with `x`

being a `Number`

and `y`

being an `ivy.Array`

instance. These should be added to the docstring of the `ivy.Array`

reverse special method `ivy.Array.__r<op_name>__()`

.

**Container operator** examples show an operation being performed like so `x + y`

with `x`

being an `ivy.Container`

instance, and these should be added to the docstring of the `ivy.Container`

special method `ivy.Container.__<op_name>__()`

.

**Container reverse operator** examples show an operation being performed like so `x + y`

with `x`

being a `Number`

and `y`

being an `ivy.Container`

instance. These should be added to the docstring of the `ivy.Container`

reverse special method `ivy.Container.__r<op_name>__()`

.

The first four example types are very common, while the last four, unsurprisingly, are only relevant for *operator* functions such as `ivy.add()`

, `ivy.subtract()`

, `ivy.multiply()`

and `ivy.divide()`

.

For example, calling any of (`+`

, `-`

, `*`

, `/`

etc.) on the array will result in (`__add__()`

, `__sub__()`

, `__mul__()`

, `__truediv__()`

etc.) being called on the array class.

**Operator** examples are only relevant for *operator* functions. These are functions which are called when a corresponding operator is applied to an array.
For example, the functions `ivy.add()`

, `ivy.subtract()`

, `ivy.multiply()`

and `ivy.divide()`

are called when the operators `+`

, `-`

, `*`

and `/`

are used respectively.
Under the hood, these operators first call the special methods `__add__()`

, `__sub__()`

, `__mul__()`

and `__truediv__()`

respectively, on either the `ivy.Array`

or `ivy.Container`

instance upon which the operator is being applied.
These special methods in turn call the functions in the Ivy API mentioned above.

**Functional Examples**

To recap, *functional* examples show the function being called like so `ivy.func_name(...)`

, and these should be added to docstring of the function in the Ivy API `ivy.func_name()`

.

Firstly, we should include *functional* examples with `ivy.Array`

instances in the input.

These should:

cover all possible variants (explained below) for each of the arguments independently, not combinatorially. This means the number of examples should be equal to the maximum number of variations for a single argument, and not the entire grid of variations across all arguments (further explained in the examples below)

vary the values and input shapes considerably between examples

start with the simplest examples first. For example, this means using the default values for all optional arguments in the first example, and using small arrays, with a small number of dimensions, and with

*simple*values for the function in questionshow an example with: (a)

`out`

unused, (b)`out`

used to update a new array`y`

, and (c)`out`

used to inplace update the input array`x`

(provided that it shares the same`dtype`

and`shape`

as the return)If broadcasting is relevant for the function, then show examples which highlight this. For example, passing in different shapes for two array arguments

For all remaining examples, we can repeat input values from these `ivy.Array`

*functional* examples covered by points 1-5.

The purpose of the extra examples with different input types in points 6-18 is to highlight the different contexts in which the function can be called (as an instance method etc.). The purpose is not to provide an excessive number of variations of possible function inputs.

Next, for *nestable* functions there should be an example that:

passes in an

`ivy.Container`

instance in place of one of the arguments

For *nestable* functions which accept more than one argument, there should also be an example that:

passes in

`ivy.Container`

instances for multiple arguments

In all cases, the containers should have at least two leaves. For example, the following container is okay to use for example purposes:

```
x = ivy.Container(a=ivy.array([0.]), b=ivy.array([1.]))
```

Whereas the following container is not okay to use for example purposes:

```
x = ivy.Container(a=ivy.array([0.]))
```

**Container Static Method Examples**

To recap, *container static method* examples show the method being called like so `ivy.Container.static_func_name(...)`

, and these should be added to the docstring of the static container method `ivy.Container.static_func_name()`

.

The static methods of the `ivy.Container`

class are used under the hood when supporting the *nestable* property for all Ivy functions in the API, as showcased by the examples for points 6 and 7.
We should demonstrate these same examples in the static method docstrings also.

the example from point 6 should be replicated, but added to the

`ivy.Container`

static method`ivy.Container.static_func_name()`

docstring. With`ivy.func_name()`

replaced with`ivy.Container.static_func_name()`

in the example.the example from point 7 should be replicated, but added to the

`ivy.Container`

static method`ivy.Container.static_func_name()`

docstring. With`ivy.func_name()`

replaced with`ivy.Container.static_func_name()`

in the example.

**Array Instance Method Example**

To recap, *array instance method* examples show the method being called like so `x.func_name(...)`

on an `ivy.Array`

instance, and these should be added to the docstring of the `ivy.Array`

instance method `ivy.Array.func_name()`

.

These examples are of course only relevant if an instance method for the function exists. If so, this example should simply:

call this instance method of the

`ivy.Array`

class

**Container Instance Method Example**

To recap, *container instance method* examples show the method being called like so `x.func_name(...)`

on an `ivy.Container`

instance, and these should be added to the docstring of the `ivy.Container`

instance method `ivy.Container.func_name()`

.

These examples are of course only relevant if an instance method for the function exists. If so, this example should simply:

call this instance method of the

`ivy.Container`

class

**Array Operator Examples**

To recap, *array operator* examples show an operation being performed like so `x + y`

with `x`

being an `ivy.Array`

instance, and these should be added to the docstring of the `ivy.Array`

special method `ivy.Array.__<op_name>__()`

.

If the function is an *operator* function, then the *array operator* examples should:

call the operator on two

`ivy.Array`

instancescall the operator with an

`ivy.Array`

instance on the left and`ivy.Container`

on the right

**Array Reverse Operator Example**

To recap, *array reverse operator* examples show an operation being performed like so `x + y`

with `x`

being a `Number`

and `y`

being an `ivy.Array`

instance. These should be added to the docstring of the `ivy.Array`

reverse special method `ivy.Array.__r<op_name>__()`

.

If the function is an *operator* function, then the *array reverse operator* example should:

call the operator with a

`Number`

on the left and an`ivy.Array`

instance on the right

**Container Operator Examples**

To recap, *container operator* examples show an operation being performed like so `x + y`

with `x`

being an `ivy.Container`

instance, and these should be added to the docstring of the `ivy.Container`

special method `ivy.Container.__<op_name>__()`

.

If the function is an *operator* function, then the *container operator* examples should:

call the operator on two

`ivy.Container`

instances containing`Number`

instances at the leavescall the operator on two

`ivy.Container`

instances containing`ivy.Array`

instances at the leavescall the operator with an

`ivy.Container`

instance on the left and`ivy.Array`

on the right

**Container Reverse Operator Example**

To recap, *container reverse operator* examples show an operation being performed like so `x + y`

with `x`

being a `Number`

and `y`

being an `ivy.Container`

instance.
These should be added to the docstring of the `ivy.Container`

reverse special method `ivy.Container.__r<op_name>__()`

.

If the function is an *operator* function, then the *array reverse operator* example should:

call the operator with a

`Number`

on the left and an`ivy.Container`

instance on the right

**Note**

All docstrings must run without error for all backend frameworks.
If some backends do not support some `dtype`

for a function, then we should not include this `dtype`

for any of the examples for that particular function in the docstring.

**All Possible Variants**

Point 1 mentions that the examples should cover *all possible variations*.
Let’s look at an example to make it more clear what is meant by *all possible variants* of each argument independently.

Let’s take an imaginary function with the following argument spec:

```
def my_func(x: array,
mode: Union[std, prod, var],
some_flag: bool,
another_flag: bool = False,
axes: Optional[Union[int, List[int]]]=-1):
```

In this case, our examples would need to include

`x`

being an`array`

`mode`

being all of:`std`

,`prod`

,`var`

`some_flag`

being both of:`True`

,`False`

`another_flag`

being all of:`default`

,`True`

,`False`

`axis`

being all of:`default`

,`list`

,`int`

.

Please note, this does not need to be done with a grid search.
There are 1 x 3 x 2 x 3 x 3 = 54 possible variations here, and we do not need an example for each one!
Instead, we only need as many examples as there are variations for the argument with the maximum number of variations, in this case jointly being the `mode`

, `another_flag`

and `axis`

arguments, each with 3 variations.

For example, we could have three examples using the following arguments:

```
my_func(x0, std, True)
my_func(x1, prod, False, True, [0, 1, 2])
my_func(x2, var, True, False, 1)
```

It doesn’t matter how the variations are combined for the examples, as long as every variation for every argument is included in the examples. These three examples procedurally go through the variations from left to right for each argument, but this doesn’t need to be the case if you think other combinations make more sense for the examples.

You can also add more examples if you think some important use cases are missed, this is just a lower limit on the examples that should be included in the docstring!

We’ll next go through some examples to make these 18 points more clear.

## ivy.tan#

**Functional Examples**

The signature for `ivy.tan()`

is as follows:

```
def tan(
x: Union[ivy.Array, ivy.NativeArray],
/,
*,
out: Optional[ivy.Array] = None
) -> ivy.Array:
```

Let’s start with the functional examples, with `ivy.Array`

instances in the input:

```
Examples
--------
With
````ivy.Array`

input:
>>> x = ivy.array([0, 1, 2])
>>> y = ivy.tan(x)
>>> print(y)
ivy.array([0., 1.5574077, -2.1850398])
>>> x = ivy.array([0.5, -0.7, 2.4])
>>> y = ivy.zeros(3)
>>> ivy.tan(x, out=y)
>>> print(y)
ivy.array([0.5463025, -0.8422884, -0.91601413])
>>> x = ivy.array([[1.1, 2.2, 3.3],
... [-4.4, -5.5, -6.6]])
>>> ivy.tan(x, out=x)
>>> print(x)
ivy.array([[ 1.9647598, -1.3738229, 0.1597457],
[-3.0963247, 0.9955841, -0.3278579]])

These examples cover points 1, 2, 3, 4 and 5.

Please note that in the above case of x having multi-line input, it is necessary for each line of the input to be seperated by a ‘…' so that they can be parsed by the script that tests the examples in the docstrings.

Point 1 is simple to satisfy.
Ignoring the union over `ivy.Array`

and `ivy.NativeArray`

which is covered by points 6 and 7, and ignoring the *nestable* nature of the function which is covered by points 8 and 9, then as far as point 1 is concerned, the input `x`

only has one possible variation.
It must be an array.

Point 2 is satisfied, as the shape and values of the inputs are varied between each of the three examples.

Point 3 is satisfied, there are no optional inputs (aside from `out`

) and so this point is irrelevant, and the values and shapes do become increasingly *complex*.

Point 4 is clearly satisfied, as each of the three examples shown above use the `out`

argument exactly as explained in point 4.
The return has the same `shape`

and `dtype`

as the input, making all three examples possible.

Point 5 is not relevant, as there is only one array input, and so broadcasting rules do not apply.

We then also add an example with an `ivy.Container`

input, in order to satisfy point 6.
Point 7 is not relevant as there is only one input argument (excluding `out`

which does not count, as it essentially acts as an output)

`With ``ivy.Container`

input:
>>> x = ivy.Container(a=ivy.array([0., 1., 2.]), b=ivy.array([3., 4., 5.]))
>>> y = ivy.tan(x)
>>> print(y)
{
a: ivy.array([0., 1.5574077, -2.1850398]),
b: ivy.array([-0.14254655, 1.1578213, -3.380515])
}

**Container Static Method Examples**

We then add an `ivy.Container`

static method example to the docstring of `ivy.Container.static_tan()`

in order to satisfy point 8.
Point 9 is not relevant as there is only one input argument (excluding `out`

which does not count, as it essentially acts as an output).

```
Examples
--------
With
````ivy.Container`

input:
>>> x = ivy.Container(a=ivy.array([0., 1., 2.]), b=ivy.array([3., 4., 5.]))
>>> y = ivy.Container.static_tan(x)
>>> print(y)
{
a: ivy.array([0., 1.56, -2.19]),
b: ivy.array([-0.143, 1.16, -3.38])
}

**Array Instance Method Example**

We then add an instance method example to `ivy.Array.tan()`

in order to satisfy
point 10.

```
Examples
--------
>>> x = ivy.array([0., 1., 2.])
>>> y = x.tan()
>>> print(y)
ivy.array([0., 1.56, -2.19])
```

**Container Instance Method Example**

We then add an instance method example to `ivy.Container.tan()`

in order to satisfy point 11.

```
Examples
--------
>>> x = ivy.Container(a=ivy.array([0., 1., 2.]), b=ivy.array([3., 4., 5.]))
>>> y = x.tan()
>>> print(y)
{
a:ivy.array([0., 1.56, -2.19]),
b:ivy.array([-0.143, 1.16, -3.38])
}
```

**Array Operator Examples**

Points 12 and 13 are not relevant as `ivy.tan()`

is not an *operator* function.

**Array Reverse Operator Example**

Point 14 is not relevant as `ivy.tan()`

is not an *operator* function.

**Container Operator Examples**

Points 15, 16 and 17 are not relevant as `ivy.tan()`

is not an *operator* function.

**Container Reverse Operator Example**

Point 18 is not relevant as `ivy.tan()`

is not an *operator* function.

## ivy.roll#

**Functional Examples**

The signature for `ivy.roll()`

is as follows:

```
def roll(
x: Union[ivy.Array, ivy.NativeArray],
/,
shift: Union[int, Sequence[int]],
*,
axis: Optional[Union[int, Sequence[int]]] = None,
out: Optional[ivy.Array] = None,
) -> ivy.Array:
```

Let’s start with the functional examples, with `ivy.Array`

instances in the input:

```
Examples
--------
With
````ivy.Array`

input:
>>> x = ivy.array([0., 1., 2.])
>>> y = ivy.roll(x, 1)
>>> print(y)
ivy.array([2., 0., 1.])
>>> x = ivy.array([[0., 1., 2.],
... [3., 4., 5.]])
>>> y = ivy.zeros((2, 3))
>>> ivy.roll(x, 2, -1, out=y)
>>> print(y)
ivy.array([[1., 2., 0.],
[4., 5., 3.]])
>>> x = ivy.array([[[0., 0.], [1., 3.], [2., 6.]],
... [[3., 9.], [4., 12.], [5., 15.]]])
>>> ivy.roll(x, (1, -1), (0, 2), out=x)
>>> print(x)
ivy.array([[[ 9., 3.],
[12., 4.],
[15., 5.]],
[[ 0., 0.],
[ 3., 1.],
[ 6., 2.]]])

These examples cover points 1, 2, 3, 4 and 5.

Again, please note that in the above case of x having multi-line input, it is necessary for each line of the input to be seperated by a ‘…' so that they can be parsed by the script that tests the examples in the docstrings.

Point 1 is a bit less trivial to satisfy than it was for `ivy.tan()`

above.
While `x`

again only has one variation (for the same reason as explained in the `ivy.tan()`

example above), `shift`

has two variations (`int`

or sequence of `int`

), and `axis`

has three variations (`int`

, :sequence of `int`

, or `None`

).

Therefore, we need at least three examples (equal to the maximum number of variations, in this case `axis`

), in order to show all variations for each argument.
By going through each of the three examples above, it can be seen that each variation for each argument is demonstrated in at least one of the examples.
Therefore, point 1 is satisfied.

Point 2 is satisfied, as the shape and values of the inputs are varied between each of the three examples.

Point 3 is satisfied, as the first example uses the default values for optional arguments, and the subsequent examples the non-default values in increasingly *complex* examples.

Point 4 is clearly satisfied, as each of the three examples shown above use the `out`

argument exactly as explained in point 4.
The return has the same `shape`

and `dtype`

as the input, making all three examples possible.

Point 5 is not relevant, as there is only one array input, and so broadcasting rules do not apply.

We then also add an example with an `ivy.Container`

for one of the inputs, in order to satisfy point 6.

`With one ``ivy.Container`

input:
>>> x = ivy.Container(a=ivy.array([0., 1., 2.]),
... b=ivy.array([3., 4., 5.]))
>>> y = ivy.roll(x, 1)
>>> print(y)
{
a: ivy.array([2., 0., 1.]),
b: ivy.array([5., 3., 4.])
}

Unlike `ivy.tan()`

, point 7 is relevant in this case, as there are three function inputs in total (excluding `out`

).
We can therefore add an example with multiple `ivy.Container`

inputs, in order to satisfy point 7.

`With multiple ``ivy.Container`

inputs:
>>> x = ivy.Container(a=ivy.array([0., 1., 2.]),
... b=ivy.array([3., 4., 5.]))
>>> shift = ivy.Container(a=1, b=-1)
>>> y = ivy.roll(x, shift)
>>> print(y)
{
a: ivy.array([2., 0., 1.]),
b: ivy.array([4., 5., 3.])
}

**Container Static Method Examples**

We then add an `ivy.Container`

static method example with an `ivy.Container`

for one of the inputs, to the docstring of `ivy.Container.static_roll()`

, in order to satisfy point 8.

We then add an `ivy.Container`

static method example with multiple `ivy.Container`

inputs, to the docstring of `ivy.Container.static_roll()`

, in order to satisfy point 9.

`With multiple ``ivy.Container`

inputs:
>>> x = ivy.Container(a=ivy.array([0., 1., 2.]),
... b=ivy.array([3., 4., 5.]))
>>> shift = ivy.Container(a=1, b=-1)
>>> y = ivy.Container.static_roll(x, shift)
>>> print(y)
{
a: ivy.array([2., 0., 1.]),
b: ivy.array([4., 5., 3.])
}

**Array Instance Method Example**

We then add an instance method example to `ivy.Array.roll()`

in order to satisfy point 10.

```
Examples
--------
>>> x = ivy.array([0., 1., 2.])
>>> y = x.roll(1)
>>> print(y)
ivy.array([2., 0., 1.])
```

**Container Instance Method Example**

We then add an instance method example to `ivy.Container.roll()`

in order to satisfy point 11.

```
Examples
--------
>>> x = ivy.Container(a=ivy.array([0., 1., 2.]), b=ivy.array([3., 4., 5.]))
>>> y = x.roll(1)
>>> print(y)
{
a: ivy.array([2., 0., 1.], dtype=float32),
b: ivy.array([5., 3., 4.], dtype=float32)
}
```

**Array Operator Examples**

Points 12 and 13 are not relevant as `ivy.roll()`

is not an *operator* function.

**Array Reverse Operator Example**

Point 14 is not relevant as `ivy.roll()`

is not an *operator* function.

**Container Operator Examples**

Points 15, 16 and 17 are not relevant as `ivy.roll()`

is not an *operator* function.

**Container Reverse Operator Example**

Point 18 is not relevant as `func.roll`

is not an *operator* function.

## ivy.add#

**Functional Examples**

The signature for `ivy.add()`

is as follows:

```
def add(
x1: Union[ivy.Array, ivy.NativeArray],
x2: Union[ivy.Array, ivy.NativeArray],
/,
*,
out: Optional[ivy.Array] = None,
) -> ivy.Array:
```

Let’s start with the functional examples, with `ivy.Array`

instances in the input:

```
Examples
--------
With
````ivy.Array`

inputs:
>>> x = ivy.array([1, 2, 3])
>>> y = ivy.array([4, 5, 6])
>>> z = ivy.add(x, y)
>>> print(z)
ivy.array([5, 7, 9])
>>> x = ivy.array([[1.1, 2.3, -3.6]])
>>> y = ivy.array([[4.8], [5.2], [6.1]])
>>> z = ivy.zeros((3, 3))
>>> ivy.add(x, y, out=z)
>>> print(z)
ivy.array([[5.9, 7.1, 1.2],
[6.3, 7.5, 1.6],
[7.2, 8.4, 2.5]])
>>> x = ivy.array([[[1.1], [3.2], [-6.3]]])
>>> y = ivy.array([[8.4], [2.5], [1.6]])
>>> ivy.add(x, y, out=x)
>>> print(x)
ivy.array([[[9.5],
[5.7],
[-4.7]]])

These examples cover points 1, 2, 3, 4 and 5.

Again, please note that in the above case of x having multi-line input, it is necessary for each line of the input to be seperated by a ‘…' so that they can be parsed by the script that tests the examples in the docstrings.

Point 1 is again trivial to satisfy, as was the case for `ivy.tan()`

.
Ignoring the union over `ivy.Array`

and `ivy.NativeArray`

which is covered by points 6 and 7, and also ignoring the *nestable* nature of the function which is covered by points 8 and 9, then as far as point 1 is concerned, inputs `x1`

and `x2`

both only have one possible variation.
They must both be arrays.

Point 2 is satisfied, as the shape and values of the inputs are varied between each of the three examples.

Point 3 is satisfied, there are no optional inputs (aside from `out`

) and so this point is irrelevant, and the values and shapes do become increasingly *complex*.

Point 4 is clearly satisfied, as each of the three examples shown above use the `out`

argument exactly as explained in point 4.
The return has the same `shape`

and `dtype`

as the input, making all three examples possible.

Point 5 is satisfied, as the second example uses different shapes for the inputs `x1`

and `x2`

.
This causes the broadcasting rules to apply, which dictates how the operation is performed and the resultant shape of the output.

We then also add an example with an `ivy.Container`

for one of the inputs, in order to satisfy point 6.

`With one ``ivy.Container`

input:
>>> x = ivy.array([[1.1, 2.3, -3.6]])
>>> y = ivy.Container(a=ivy.array([[4.], [5.], [6.]]),
... b=ivy.array([[5.], [6.], [7.]]))
>>> z = ivy.add(x, y)
>>> print(z)
{
a: ivy.array([[5.1, 6.3, 0.4],
[6.1, 7.3, 1.4],
[7.1, 8.3, 2.4]]),
b: ivy.array([[6.1, 7.3, 1.4],
[7.1, 8.3, 2.4],
[8.1, 9.3, 3.4]])
}

Again, unlike `ivy.tan()`

, point 7 is relevant in this case, as there are two function inputs in total (exluding `out`

).
We can therefore add an example with multiple `ivy.Container`

inputs, in order to satisfy point 7.

`With multiple ``ivy.Container`

inputs:
>>> x = ivy.Container(a=ivy.array([1, 2, 3]),
... b=ivy.array([2, 3, 4]))
>>> y = ivy.Container(a=ivy.array([4, 5, 6]),
... b=ivy.array([5, 6, 7]))
>>> z = ivy.add(x, y)
>>> print(z)
{
a: ivy.array([5, 7, 9]),
b: ivy.array([7, 9, 11])
}

**Container Static Method Examples**

We then add an `ivy.Container`

static method example with an `ivy.Container`

for one of the inputs, to the docstring of `ivy.Container.static_add()`

, in order to satisfy point 8.

```
Examples
--------
With one
````ivy.Container`

input:
>>> x = ivy.array([[1.1, 2.3, -3.6]])
>>> y = ivy.Container(a=ivy.array([[4.], [5.], [6.]]),
... b=ivy.array([[5.], [6.], [7.]]))
>>> z = ivy.Container.static_add(x, y)
>>> print(z)
{
a: ivy.array([[5.1, 6.3, 0.4],
[6.1, 7.3, 1.4],
[7.1, 8.3, 2.4]]),
b: ivy.array([[6.1, 7.3, 1.4],
[7.1, 8.3, 2.4],
[8.1, 9.3, 3.4]])
}

We then add an `ivy.Container`

static method example with multiple `ivy.Container`

inputs, also to the docstring of `ivy.Container.static_add()`

, in order to satisfy point 9.

`With multiple ``ivy.Container`

inputs:
>>> x = ivy.Container(a=ivy.array([1, 2, 3]),
... b=ivy.array([2, 3, 4]))
>>> y = ivy.Container(a=ivy.array([4, 5, 6]),
... b=ivy.array([5, 6, 7]))
>>> z = ivy.Container.static_add(x, y)
>>> print(z)
{
a: ivy.array([5, 7, 9]),
b: ivy.array([7, 9, 11])
}

**Array Instance Method Example**

We then add an instance method example to `ivy.Array.add()`

in order to satisfy point 10.

```
Examples
--------
>>> x = ivy.array([1, 2, 3])
>>> y = ivy.array([4, 5, 6])
>>> z = x.add(y)
>>> print(z)
ivy.array([5, 7, 9])
```

**Container Instance Method Example**

We then add an instance method example to `ivy.Container.add()`

in order to satisfy point 11.

```
Examples
--------
>>> x = ivy.Container(a=ivy.array([1, 2, 3]),
... b=ivy.array([2, 3, 4]))
>>> y = ivy.Container(a=ivy.array([4, 5, 6]),
... b=ivy.array([5, 6, 7]))
>>> z = x.add(y)
>>> print(z)
{
a: ivy.array([5, 7, 9]),
b: ivy.array([7, 9, 11])
}
```

**Array Operator Examples**

Point 12 is satisfied by the following example in the `ivy.Array.__add__()`

docstring, with the operator called on two `ivy.Array`

instances.

```
Examples
--------
With
````ivy.Array`

instances only:
>>> x = ivy.array([1, 2, 3])
>>> y = ivy.array([4, 5, 6])
>>> z = x + y
>>> print(z)
ivy.array([5, 7, 9])

Point 13 is satisfied by the following example in the `ivy.Array.__add__()`

docstring, with the operator called with an `ivy.Array`

instance on the left and `ivy.Container`

on the right.

With mix of`ivy.Array`

and`ivy.Container`

instances: >>> x = ivy.array([[1.1, 2.3, -3.6]]) >>> y = ivy.Container(a=ivy.array([[4.], [5.], [6.]]), ... b=ivy.array([[5.], [6.], [7.]])) >>> z = x + y >>> print(z) { a: ivy.array([[5.1, 6.3, 0.4], [6.1, 7.3, 1.4], [7.1, 8.3, 2.4]]), b: ivy.array([[6.1, 7.3, 1.4], [7.1, 8.3, 2.4], [8.1, 9.3, 3.4]]) }

**Array Reverse Operator Examples**

Point 14 is satisfied by the following example in the `ivy.Array.__radd__()`

docstring, with the operator called with a `Number`

on the left and an `ivy.Array`

instance on the right.

```
Examples
--------
>>> x = 1
>>> y = ivy.array([4, 5, 6])
>>> z = x + y
>>> print(z)
ivy.array([5, 6, 7])
```

**Container Operator Examples**

Point 15 is satisfied by the following example in the `ivy.Container.__add__()`

docstring, with the operator called on two `ivy.Container`

instances containing `Number`

instances at the leaves.

```
Examples
--------
With
````Number`

instances at the leaves:
>>> x = ivy.Container(a=1, b=2)
>>> y = ivy.Container(a=3, b=4)
>>> z = x + y
>>> print(z)
{
a: 4,
b: 6
}

Point 16 is satisfied by the following example in the `ivy.Container.__add__()`

docstring, with the operator called on two `ivy.Container`

instances containing `ivy.Array`

instances at the leaves.

`With ``ivy.Array`

instances at the leaves:
>>> x = ivy.Container(a=ivy.array([1, 2, 3]),
... b=ivy.array([2, 3, 4]))
>>> y = ivy.Container(a=ivy.array([4, 5, 6]),
... b=ivy.array([5, 6, 7]))
>>> z = x + y
>>> print(z)
{
a: ivy.array([5, 7, 9]),
b: ivy.array([7, 9, 11])
}

Point 17 is satisfied by the following example in the `ivy.Container.__add__()`

docstring, with the operator called with an `ivy.Container`

instance on the left and `ivy.Array`

on the right.

With a mix of`ivy.Container`

and`ivy.Array`

instances: >>> x = ivy.Container(a=ivy.array([[4.], [5.], [6.]]), ... b=ivy.array([[5.], [6.], [7.]])) >>> y = ivy.array([[1.1, 2.3, -3.6]]) >>> z = x + y >>> print(z) { a: ivy.array([[5.1, 6.3, 0.4], [6.1, 7.3, 1.4], [7.1, 8.3, 2.4]]), b: ivy.array([[6.1, 7.3, 1.4], [7.1, 8.3, 2.4], [8.1, 9.3, 3.4]]) }

**Container Reverse Operator Example**

Point 18 is satisfied by the following example in the `ivy.Container.__radd__()`

docstring, with the operator called with a `Number`

on the left and an `ivy.Container`

instance on the right.

```
Examples
--------
>>> x = 1
>>> y = ivy.Container(a=3, b=4)
>>> z = x + y
>>> print(z)
{
a: 4,
b: 5
}
```

**Docstring Tests**

After making a Pull Request, each time you make a commit, then a number of checks are run on it to ensure everything’s working fine.
One of these checks is the docstring tests named as `test-docstrings / run-docstring-tests`

in the GitHub actions.
The docstring tests check whether the docstring examples for a given function are valid or not.
It basically checks if the output upon execution of the examples that are documented match exactly with the ones shown in the docstrings.
Therefore each time you make a commit, you must ensure that the `test-docstrings / run-docstring-tests`

are working correctly at least for the function you are making changes to.
To check whether the docstring tests are passing you need to check the logs for `test-docstrings / run-docstring-tests`

:

You will need to go through the logs and see if the list of functions for which the docstring tests are failing also has the function you are working with.

If the docstring tests are failing the logs show a list of functions having issues along with a diff message:
`output for failing_fn_name on run: ......`

`output in docs: ........`

as shown below:

It can be quite tedious to go through the output diffs and spot the exact error, so you can take help of online tools like text compare to spot the minutest of differences.

Once you make the necessary changes and the function you are working on doesn’t cause the docstring tests to fail, you should be good to go. However, one of the reviewers might ask you to make additional changes involving examples. Passing docstring tests is a necessary but not sufficient condition for the completion of docstring formatting.

Note

Docstring examples should not have code that imports ivy or sets a backend, otherwise it leads to segmentation faults.

**Round Up**

These three examples should give you a good understanding of what is required when adding docstring examples.

If you have any questions, please feel free to reach out on discord in the docstring examples channel or in the docstring examples forum!

**Video**