Suppose one wants to have a bunch of structs that represent API requests. Requests have parameters and it should be possible to validate parameters when constructing the structs. This use case would be completely covered if one could specify a structure by simply providing an appropriate (validating) constructor.
Here is is somewhat contrived example:
defmodule Orders do
import SuperStruct # hypothetical
defsstruct market(id, quantity, type, exchange \\ nil, fill_or_kill \\ false)
when is_binary(id) and is_int(quantity) and type in [:buy, :sell]
and (is_binary(exchange) or is_nil(exchange)) and is_boolean(fill_or_kill)
defsstruct limit(id, quantity, type, price, exchange \\ nill, valid_until \\ nil) #...
end
# Create an order
# Would be nice to be able to use keyword syntax for all params
order = Orders.Market.new(id: "GOOG", quantity: 100, type: :buy)
# Processing code
case order do
%Orders.Market{} -> # market order
%Orders.Limit{} -> # limit order
end
def process(%Orders.Market{}=o), do: #...
def process(%Orders.Limit{}=o), do: #...
It looks like it should be possible to come up with macros that would parse the signatures and generate the appropriate struct modules (e.g. modules having custom __struct__
methods). I am wondering if there is a library for doing something similar or maybe someone looked into something similar in the past.
I briefly looked at construct
, exconstructor
and struct_constructor
packages and I think their focus is slightly different. It looks like they all provide nice field definition macros but do not aim at parsing/repackaging constructors. Clearly, there are pros and cons to both approaches.