feat(list): add `unique` function (#716)

* feat(list): add `unique` function

* Update lists.bzl

* Update lists.bzl

* Update lists.bzl

* Update lists.bzl

---------

Co-authored-by: Alex Eagle <alex@aspect.dev>
diff --git a/docs/lists.md b/docs/lists.md
index c7029ee..03143fc 100644
--- a/docs/lists.md
+++ b/docs/lists.md
@@ -188,3 +188,29 @@
 True or False
 
 
+<a id="unique"></a>
+
+## unique
+
+<pre>
+unique(<a href="#unique-arr">arr</a>)
+</pre>
+
+Return a new list with unique items in it.
+
+Example:
+  `unique(["foo", "bar", "foo", "baz"]) // ["foo", "bar", "baz"]`
+
+
+**PARAMETERS**
+
+
+| Name  | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="unique-arr"></a>arr |  List to iterate over   |  none |
+
+**RETURNS**
+
+A new list with unique items
+
+
diff --git a/lib/lists.bzl b/lib/lists.bzl
index 976dce6..72aa79e 100644
--- a/lib/lists.bzl
+++ b/lib/lists.bzl
@@ -1,6 +1,6 @@
 "Functions for lists"
 
-load("//lib/private:lists.bzl", _every = "every", _filter = "filter", _find = "find", _map = "map", _once = "once", _pick = "pick", _some = "some")
+load("//lib/private:lists.bzl", _every = "every", _filter = "filter", _find = "find", _map = "map", _once = "once", _pick = "pick", _some = "some", _unique = "unique")
 
 every = _every
 filter = _filter
@@ -9,3 +9,4 @@
 once = _once
 pick = _pick
 some = _some
+unique = _unique
diff --git a/lib/private/lists.bzl b/lib/private/lists.bzl
index 11125e0..df52268 100644
--- a/lib/private/lists.bzl
+++ b/lib/private/lists.bzl
@@ -117,3 +117,21 @@
         if f(a):
             return True
     return False
+
+def unique(arr):
+    """Return a new list with unique items in it.
+
+    Example:
+      `unique(["foo", "bar", "foo", "baz"]) // ["foo", "bar", "baz"]`
+
+    Args:
+      arr: List to iterate over
+
+    Returns:
+      A new list with unique items
+    """
+    res = []
+    for a in arr:
+        if a not in res:
+            res.append(a)
+    return res
diff --git a/lib/tests/lists_test.bzl b/lib/tests/lists_test.bzl
index 81c1117..82c86b2 100644
--- a/lib/tests/lists_test.bzl
+++ b/lib/tests/lists_test.bzl
@@ -1,7 +1,7 @@
 """unit tests for lists"""
 
 load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")
-load("//lib/private:lists.bzl", "every", "filter", "find", "map", "once", "pick", "some")
+load("//lib/private:lists.bzl", "every", "filter", "find", "map", "once", "pick", "some", "unique")
 
 def _every_test_impl(ctx):
     env = unittest.begin(ctx)
@@ -70,6 +70,15 @@
 
 some_test = unittest.make(_some_test_impl)
 
+def _unique_test_impl(ctx):
+    env = unittest.begin(ctx)
+
+    asserts.equals(env, unique(["foo", {"bar": "baz"}, 42, {"bar": "baz"}, "foo"]), ["foo", {"bar": "baz"}, 42])
+
+    return unittest.end(env)
+
+unique_test = unittest.make(_unique_test_impl)
+
 def lists_test_suite():
     unittest.suite(
         "lists_tests",
@@ -80,4 +89,5 @@
         once_test,
         pick_test,
         some_test,
+        unique_test,
     )