From b75fc0451c9ae53593cf9a966a5760d53f2e8485 Mon Sep 17 00:00:00 2001 From: Arthur Evans Date: Thu, 12 Sep 2024 12:13:15 -0700 Subject: [PATCH] [Docs] Add conditional conformance section. MODULAR_ORIG_COMMIT_REV_ID: b57b717ce29c6cde7dababfc3234d88e5295996e --- docs/manual/parameters/index.ipynb | 83 +++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/docs/manual/parameters/index.ipynb b/docs/manual/parameters/index.ipynb index d098309bf9..3d4aa2778e 100644 --- a/docs/manual/parameters/index.ipynb +++ b/docs/manual/parameters/index.ipynb @@ -217,7 +217,7 @@ "## Parameterized structs\n", "\n", "You can also add parameters to structs. You can use parameterized structs to\n", - "build generic containers. For example, a generic array type might include code\n", + "build generic collections. For example, a generic array type might include code\n", "like this:" ] }, @@ -322,6 +322,87 @@ "The method returns an instance of `GenericArray[Float64]`." ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Conditional conformance\n", + "\n", + "When creating a generic struct, you might want to define some methods that\n", + "require extra features. For example, consider a collection like `GenericArray`\n", + "that holds instances of `CollectionElement`. The `CollectionElement` trait\n", + "only requires that the stored data type be copyable and movable. This\n", + "imposes a lot of limitations: you can't implement a `sort()` method because\n", + "you can't guarantee that the stored type supports the comparison operators; you can't\n", + "write a useful `__str__()` or `__repr__()` dunder method because you can't\n", + "guarantee that the stored type supports conversion to a string.\n", + "\n", + "The answer to these issues is _conditional conformance_, which lets you define a \n", + "method that requires additional features. You do this by defining the `self`\n", + "value that has a more specific bound on one or more of its parameters. \n", + "\n", + "For example, the following code defines a `Container` type that holds an\n", + "instance of `CollectionElement`. It also defines a `__str__()` method that can \n", + "only be called if the stored `ElementType` conforms to \n", + "`StringableCollectionElement`:" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5\n", + "Hello\n" + ] + } + ], + "source": [ + "@value\n", + "struct Container[ElementType: CollectionElement]:\n", + " var element: ElementType\n", + "\n", + " def __str__[StrElementType: StringableCollectionElement, //](\n", + " self: Container[StrElementType]) -> String:\n", + " return str(self.element)\n", + "\n", + "def use_container():\n", + " float_container = Container(5)\n", + " string_container = Container(\"Hello\")\n", + " print(float_container.__str__())\n", + " print(string_container.__str__())\n", + "\n", + "use_container()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note the signature of the `__str__()` method, which declares the `self` argument\n", + "with a more specific type. Specifically, it declares that it takes a `Container`\n", + "with an `ElementType` that conforms to the `StringableCollectionElement` trait.\n", + "\n", + "```mojo\n", + "def __str__[StrElementType: StringableCollectionElement, //](\n", + " self: Container[StrElementType]) -> String:\n", + "```\n", + "\n", + "This trait must be a superset of `ElementType`'s original trait: for example,\n", + "`StringableCollectionElement` inherits from `CollectionElement`, so it includes\n", + "all of requirements of the original trait.\n", + "\n", + "Note that the `use_container()` function calls the `__str__()` method directly,\n", + "rather than calling `str(float_container)`. One current limitation of\n", + "conditional conformance is that Mojo can't recognize the struct\n", + "`Container[Int]` as conforming to `Stringable`, even though the `__str__()`\n", + "method is implemented for any `ElementType` that's also `Stringable`." + ] + }, { "attachments": {}, "cell_type": "markdown",