Use is_bitstring or is_binary in Elixir Guard for String?

Viewed 6556

Let's take this simple function:

  @spec laBionda(String.t()) :: String.t()
  def laBionda(name \\ "you") when is_bitstring(name) do
    "One for #{name}, one for me"
  end

I only want to define the function for String inputs.

Should I use is_bitstring or is_binary on the Guard? Are there any differences? Both seem to be fine in that case.

2 Answers

You should use is_binary/1.

Strings in Elixir are represented as binaries. Elixir binaries are sequences of bytes, whereas bitstrings are sequences of bits. While all binaries are bitstrings, not all bitstrings are binaries.

is_bitstring/1 can return true for some bitstrings that cannot be represented as a binary, for example, the single bit:

iex(1)> is_binary(<<1::1>>)
false
iex(2)> is_bitstring(<<1::1>>)
true

You expect strings only. Bitstrings that are not binaries are never desired, so the more specific is_binary/1 is the better choice.

According to this answer: https://stackoverflow.com/a/10821192/10895259

The difference between in a binary and a bitstring is that the length of a binary is evenly divisible by 8, i.e. it contains no 'partial' bytes; a bitstring has no such restriction.

The example from guides demonstrates this difference.

iex> is_binary(<<100 :: size(9)>>)
false
iex> is_binary(<<100 :: size(8)>>)
true
iex> is_binary(<<100 :: size(7)>>)
false

In your function, it does not matter what guard to use. But is_binary/1 is a convention, as the strings are stored in bytes.

Related