How can I use Decimal.is_decimal as a guard?

The canonical way to do what you’re after is to pattern match rather than use a guard. And as you’ve indentified, you can’t pattern match in guards. Using your example:

defmodule Mondo.Util do 

  def precise_exchange_rate(%Decimal{} = qty, %Decimal{} = subtotal) do
      if(Decimal.eq?(qty, 0), do: nil, else: Decimal.div(subtotal, qty))
  end

  def precise_exchange_rate(qty, subtotal) when is_binary(qty) and is_binary(subtotal) do
    decimal_qty = if qty == "", do: 0, else: Decimal.new(qty)
    decimal_subtotal = if subtotal == "", do: 0, else: Decimal.new(subtotal)

    if(Decimal.eq?(qty, 0), do: nil, else: Decimal.div(decimal_subtotal, decimal_qty))
  end  
end

I also suggest you use is_binary/1 rather than is_bitstring/1 since strings in Elixir are binaries (divisible by 8) whereas bit strings can be any number of bits.

2 Likes