Abusing Elixir: JS equality
March 5, 2023
Do you find the `==` operator _too strict_? Do you often dream of two values being equal even though they are completely different types, or of maps being equal to absolutely nothing?
Thankfully, Elixir lets us un-import `Kernel.==/2` and define our own.
defmodule JSEquality do
def a == b, do: equal?(a, b) or equal?(b, a)
def a != b, do: not __MODULE__.==(a, b)
def a === b, do: strictly_equal?(a, b) or strictly_equal?(b, a)
def a !== b, do: not __MODULE__.===(a, b)
defp equal?(1, x) when x in [true, 1], do: true
defp equal?(0, x) when x in [false, 0], do: true
defp equal?("1", x) when x in [true, 1, "1"], do: true
defp equal?("0", x) when x in [false, 0, "0"], do: true
defp equal?("", x) when x in [false, 0, ""], do: true
defp equal?(:undefined, x) when x in [nil, :undefined], do: true
defp equal?(:Infinity, :Infinity), do: true
defp equal?(:negative_Infinity, :negative_Infinity), do: true
defp equal?([], x) when x in [false, 0, ""], do: true
defp equal?([[]], x) when x in [false, 0, ""], do: true
defp equal?([0], x) when x in [false, 0, "0"], do: true
defp equal?([1], x) when x in [true, 1, "1"], do: true
defp equal?(:NaN, _), do: false
defp equal?(int, x) when is_integer(int),
do: Kernel.==(int, x) or Kernel.==(Integer.to_string(int), x)
defp equal?(list, _) when is_list(list), do: false
defp equal?(map, _) when is_map(map), do: false
defp equal?(x, x), do: true
defp equal?(_, _), do: false
defp strictly_equal?(list, _) when is_list(list), do: false
defp strictly_equal?(map, _) when is_map(map), do: false
defp strictly_equal?(:NaN, _), do: false
defp strictly_equal?(x, x), do: true
defp strictly_equal?(_, _), do: false
end
And, in use:
iex> import Kernel, except: [==: 2, !=: 2, ===: 2, !==: 2]
Kernel
iex> import JSEquality
JSEquality
iex> "hello" == "hello"
true
iex> "hello" == :world
false
iex> :undefined == nil
true
iex> "1" == [1]
true
iex> %{} == %{}
false
iex> false == "0"
true
iex> [] == []
false
iex> [[]] == false
true
iex> "" == 0
true
iex> -123 == "-123"
true
iex> :NaN == :NaN
false
iex> "foo" === "foo"
true
iex> -1 === "-1"
false
iex> [] === []
false
Navigation
Posts
Pursuits
About
Response: 20 (Success), text/gemini
| Original URL | gemini://gmi.schrockwell.com/posts/2023-03-05-abusing-eli... |
|---|---|
| Status Code | 20 (Success) |
| Content-Type | text/gemini; charset=utf-8 |