Utility macro for non-deterministic decisions

I’ve written the following very simple utility macro to generate proabbilitic fake data for a project and thought other people might find it interesting. It doesn’t make sense to package such a simple macro but it might make sense to include it in a larger package such as Faker. The implementation speaks for itself:

defmodule ProbabilityDemo do
  defmacro with_probability(p, [do: do_body, else: else_body]) do
    quote do
      if :rand.uniform() < unquote(p) do
        unquote(do_body)
      else
        unquote(else_body)
      end
    end
  end
end

You use it like this

iex(2)> import ProbabilityDemo
ProbabilityDemo
iex(3)> with_probability 0.3 do "Success!" else "Failure!" end
"Failure!"
iex(4)> with_probability 0.3 do "Success!" else "Failure!" end
"Failure!"
iex(5)> with_probability 0.3 do "Success!" else "Failure!" end
"Failure!"
iex(6)> with_probability 0.3 do "Success!" else "Failure!" end
"Failure!"
iex(7)> with_probability 0.3 do "Success!" else "Failure!" end
"Failure!"
iex(8)> with_probability 0.3 do "Success!" else "Failure!" end
"Failure!"
iex(9)> with_probability 0.3 do "Success!" else "Failure!" end
"Failure!"
iex(10)> with_probability 0.3 do "Success!" else "Failure!" end
"Success!"
iex(11)> with_probability 0.3 do "Success!" else "Failure!" end
"Success!"

It saves you from writing something like the following and makes the intent clearer

# Is the first outcome success or failure? should it be < or >?
if :rand.uniform() < prob do
 # something in case of success
else
  # something in case of failure
ned

In practice I’m using it for things like:

gender = with_probability 0.35 do :female else :male end
2 Likes