Test For Bytestring in Elixir


Here's how to test for a bytestring in Elixir.

Non-solutions

A couple things that won't work:

You can't use is_binary on its own, because it returns true for string type as well:

iex> is_binary("wow")
true

You can't use String.valid? inside a guard. You get an error like this:

iex> defmodule MyModule do
...>   def my_function(x) when String.valid?(x), do: "schtuff"
...> end
** (CompileError) iex:2: cannot invoke remote function String.valid?/1 inside guard

Solution

So we need a combo: is_binary and not String.valid?, and we need to use a plain ol if expression instead of a guard.

Imagine we wanted to convert binary UUIDs to strings. We could write a convert_uuids function like this:

defp convert_uuids(row) do
  Enum.map(row, fn value ->
    if is_bytestring(value) do
      Ecto.UUID.load!(value)
    else
      value
    end
  end)
end

defp is_bytestring(value) do
  is_binary(value) and not String.valid?(value)
end