diff --git a/CHANGELOG.md b/CHANGELOG.md index 235f36f6fdc..3ca40239939 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ This release no longer supports WERL (a graphical user interface for the Erlang * [Exception] Add `MissingApplicationsError` exception to denote missing applications * [Kernel] Update source code parsing to match [UTS #55](https://www.unicode.org/reports/tr55/) latest recommendations. In particular, mixed script is allowed in identifiers as long as they are separate by underscores (`_`), such as `http_сервер`. Previously allowed highly restrictive identifiers, which mixed Latin and other scripts, such as the japanese word for t-shirt, `Tシャツ`, now require the underscore as well * [Kernel] Warn on bidirectional confusability in identifiers + * [List] Add `List.ends_with?/2` * [Macro] Improve `dbg` handling of `if/2`, `unless/2`, and code blocks * [Process] Handle arbitrarily high integer values in `Process.sleep/1` * [String] Inspect special whitespace and zero-width characters using their Unicode representation diff --git a/lib/elixir/lib/list.ex b/lib/elixir/lib/list.ex index cc396213ef5..f8fe874bbeb 100644 --- a/lib/elixir/lib/list.ex +++ b/lib/elixir/lib/list.ex @@ -908,6 +908,34 @@ defmodule List do def starts_with?(list, []) when is_list(list), do: true def starts_with?(list, [_ | _]) when is_list(list), do: false + @doc """ + Returns `true` if `list` ends with the given `suffix` list, otherwise returns `false`. + + If `suffix` is an empty list, it returns `true`. + + ### Examples + + iex> List.ends_with?([1, 2, 3], [2, 3]) + true + + iex> List.ends_with?([1, 2], [1, 2, 3]) + false + + iex> List.ends_with?([:alpha], []) + true + + iex> List.ends_with?([], [:alpha]) + false + + """ + @doc since: "1.18.0" + @spec ends_with?(nonempty_list, nonempty_list) :: boolean + @spec ends_with?(list, []) :: true + @spec ends_with?([], nonempty_list) :: false + def ends_with?(list, suffix) do + :lists.suffix(suffix, list) + end + @doc """ Converts a charlist to an atom. diff --git a/lib/elixir/test/elixir/list_test.exs b/lib/elixir/test/elixir/list_test.exs index 368e0d6b9ea..12676c126f1 100644 --- a/lib/elixir/test/elixir/list_test.exs +++ b/lib/elixir/test/elixir/list_test.exs @@ -285,6 +285,41 @@ defmodule ListTest do end end + describe "ends_with?/2" do + test "list and prefix are equal" do + assert List.ends_with?([], []) + assert List.ends_with?([1], [1]) + assert List.ends_with?([1, 2, 3], [1, 2, 3]) + end + + test "proper lists" do + refute List.ends_with?([2], [1, 2]) + assert List.ends_with?([1, 2, 3], [2, 3]) + refute List.ends_with?([2, 3, 4], [1, 2, 3, 4]) + end + + test "list is empty" do + refute List.ends_with?([], [1]) + refute List.ends_with?([], [1, 2]) + end + + test "prefix is empty" do + assert List.ends_with?([1], []) + assert List.ends_with?([1, 2], []) + assert List.ends_with?([1, 2, 3], []) + end + + test "only accepts proper lists" do + assert_raise ArgumentError, ~r/not a list/, fn -> + List.ends_with?([1 | 2], [1 | 2]) + end + + assert_raise ArgumentError, ~r/not a list/, fn -> + List.ends_with?([1, 2], 1) + end + end + end + test "to_string/1" do assert List.to_string([?æ, ?ß]) == "æß" assert List.to_string([?a, ?b, ?c]) == "abc"