Repository: ivy-llc/ivy

Issue:
OptionalGetElement



Discussion:

Resolving patch:
diff --git a/ivy/data_classes/array/experimental/utility.py b/ivy/data_classes/array/experimental/utility.py
--- a/ivy/data_classes/array/experimental/utility.py
+++ b/ivy/data_classes/array/experimental/utility.py
@@ -1,6 +1,34 @@
 # global
+from typing import Optional
 import abc
 
+# local
+import ivy
+
 
 class _ArrayWithUtilityExperimental(abc.ABC):
-    pass
+    def optional_get_element(
+        self: Optional[ivy.Array] = None,
+        /,
+        *,
+        out: Optional[ivy.Array] = None,
+    ) -> ivy.Array:
+        """
+        If the input is a tensor or sequence type, it returns the input. If the input is
+        an optional type, it outputs the element in the input. It is an error if the
+        input is an empty optional-type (i.e. does not have an element) and the behavior
+        is undefined in this case.
+
+        Parameters
+        ----------
+        self
+            Input array
+        out
+            Optional output array, for writing the result to.
+
+        Returns
+        -------
+        ret
+            Input array if it is not None
+        """
+        return ivy.optional_get_element(self._data, out=out)
diff --git a/ivy/data_classes/container/experimental/utility.py b/ivy/data_classes/container/experimental/utility.py
--- a/ivy/data_classes/container/experimental/utility.py
+++ b/ivy/data_classes/container/experimental/utility.py
@@ -1,5 +1,82 @@
+# global
+from typing import Optional, Union, Dict, List
+
+# local
+import ivy
 from ivy.data_classes.container.base import ContainerBase
 
 
 class _ContainerWithUtilityExperimental(ContainerBase):
-    pass
+    @staticmethod
+    def static_optional_get_element(
+        x: Optional[Union[ivy.Array, ivy.Container]] = None,
+        /,
+        *,
+        key_chains: Optional[Union[List[str], Dict[str, str]]] = None,
+        to_apply: bool = True,
+        prune_unapplied: bool = False,
+        map_sequences: bool = False,
+        out: Optional[ivy.Container] = None,
+    ) -> ivy.Container:
+        """
+        ivy.Container static method variant of ivy.optional_get_element. This method
+        simply wraps the function, and so the docstring for ivy.optional_get_element
+        also applies to this method with minimal changes.
+
+        Parameters
+        ----------
+        x
+            container with array inputs.
+        key_chains
+            The keychains to apply or not apply the method to. Default is ``None``.
+        to_apply
+            If True, the method will be applied to key_chains, otherwise key_chains
+            will be skipped. Default is ``True``.
+        prune_unapplied
+            Whether to prune key_chains for which the function was not applied.
+            Default is ``False``.
+        map_sequences
+            Whether to also map method to sequences (lists, tuples).
+            Default is ``False``.
+        out
+            optional output container, for writing the result to.
+
+        Returns
+        -------
+        ret
+            Container with arrays flattened at leaves.
+        """
+        return ContainerBase.cont_multi_map_in_function(
+            "optional_get_element",
+            x,
+            key_chains=key_chains,
+            to_apply=to_apply,
+            prune_unapplied=prune_unapplied,
+            map_sequences=map_sequences,
+            out=out,
+        )
+
+    def optional_get_element(
+        self: ivy.Container,
+        /,
+        *,
+        out: Optional[ivy.Container] = None,
+    ) -> ivy.Container:
+        """
+        ivy.Container instance method variant of ivy.optional_get_element. This method
+        simply wraps the function, and so the docstring for ivy.optional_get_element
+        also applies to this method with minimal changes.
+
+        Parameters
+        ----------
+        self
+            Input container
+        out
+            Optional output container, for writing the result to.
+
+        Returns
+        -------
+        ret
+            Output container.
+        """
+        return self.static_optional_get_element(self, out=out)
diff --git a/ivy/functional/ivy/experimental/utility.py b/ivy/functional/ivy/experimental/utility.py
--- a/ivy/functional/ivy/experimental/utility.py
+++ b/ivy/functional/ivy/experimental/utility.py
@@ -0,0 +1,41 @@
+# global
+from typing import Optional
+
+# local
+import ivy
+from ivy import handle_out_argument, handle_nestable
+from ivy.utils.exceptions import handle_exceptions
+
+
+@handle_out_argument
+@handle_nestable
+@handle_exceptions
+def optional_get_element(
+    x: Optional[ivy.Array] = None,
+    /,
+    *,
+    out: Optional[ivy.Array] = None,
+) -> ivy.Array:
+    """
+    If the input is a tensor or sequence type, it returns the input. If the input is an
+    optional type, it outputs the element in the input. It is an error if the input is
+    an empty optional-type (i.e. does not have an element) and the behavior is undefined
+    in this case.
+
+    Parameters
+    ----------
+    x
+        Input array
+    out
+        Optional output array, for writing the result to.
+
+    Returns
+    -------
+    ret
+        Input array if it is not None
+    """
+    if x is None:
+        raise ivy.utils.exceptions.IvyError(
+            "The requested optional input has no value."
+        )
+    return x


Test patch:
diff --git a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_utility.py b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_utility.py
--- a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_utility.py
+++ b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_utility.py
@@ -0,0 +1,33 @@
+# global
+from hypothesis import strategies as st
+
+# local
+import ivy_tests.test_ivy.helpers as helpers
+from ivy_tests.test_ivy.helpers import handle_test
+
+
+@handle_test(
+    fn_tree="functional.ivy.experimental.optional_get_element",
+    dtype_and_x=helpers.dtype_and_values(),
+    input_tensor=st.booleans(),
+)
+def test_optional_get_element(
+    *,
+    dtype_and_x,
+    input_tensor,
+    test_flags,
+    backend_fw,
+    fn_name,
+    on_device,
+):
+    input_dtype, x = dtype_and_x
+    fn_input = x[0] if input_tensor else x
+
+    helpers.test_function(
+        input_dtypes=input_dtype,
+        test_flags=test_flags,
+        on_device=on_device,
+        backend_to_test=backend_fw,
+        fn_name=fn_name,
+        x=fn_input,
+    )