Current section
Files
Jump to
Current section
Files
lib/alchemist.ex
defmodule Alchemist do
@moduledoc """
Run an experiment all the time:
```
transmute "experiment" do
# Experimental code block is run
else
# Control code block is ignored
end
```
Run an experiment only when a condition is met:
```
transmute "experiment", enable: false do
# Experimental code block is ignored
else
# Control code block is run
end
```
Run an experiment some percentage of the time:
```
transmute "experiment", probability: 0.01 do
# Control code block runs 99% of the time
try
# Experimental code block runs 1% of the time
end
```
"""
defmacro __using__(_) do
quote do
import Alchemist
end
end
defmacro transmute(_name, options \\ [], clauses) do
enable = Keyword.get(options, :enable, true)
probability = Keyword.get(options, :probability)
clauses = Keyword.merge(clauses, [probability: probability])
build_transmute(enable, clauses)
end
defp build_transmute(condition, do: do_clause, else: else_clause, probability: probability) do
quote do
condition = unquote(condition)
probability = unquote(probability)
condition = case probability do
nil -> condition
_ -> case condition do
false -> false
_ -> :rand.uniform <= probability
end
end
case condition do
x when x in [false, nil] -> unquote(else_clause)
_ -> unquote(do_clause)
end
end
end
defp build_transmute(_condition, _arguments) do
raise(ArgumentError, "invalid or duplicate keys for transmute, only " <>
"\"do\" and \"else\" are permitted")
end
end