Implementing Inspect

I’m working on a small library to scratch a current itch involving IP addresses & network subnetting that gives me a more structured datatype (a struct) after parsing a string or tuple.

While trying to improve it and make it nicer to work with, I started experimenting with deimpl Enumerable and managed to get things functional. However to do that, I ended up introducing a hidden key much like __struct__. Which then led me into deimpl Inspect in order to hide the new key and now I’m at a bit of a cross roads trying to balance two separate needs.

The struct I’m working with looks like:

%CIDR{
  first: {172, 16, 0, 0},
  last: {172, 31, 255, 255},
  prefix: 12,
  hosts: 1048576,
  version: :v4
}

And I get that using:

defimpl Inspect, for: CIDR do
  def inspect(%module{} = network, opts \\ []) do
    filtered = Map.drop(network, [:__enum__, :__struct__])
    Inspect.Map.inspect(filtered, Code.Identifier.inspect_as_atom(module), opts)
  end
end

Reading that in the console standalone is perfect because I can quickly scan and grab whatever information I need from it. But if I’m looking at a list of maps, and the struct is the value of a key in each, it becomes a lot of noise.

To suppress things a bit I had a look at sigils and ended up implementing one which meant I was able to do:

defimpl Inspect, for: CIDR do
  import Inspect.Algebra
  def inspect(network, _opts), do: concat(["~n\"", CIDR.to_string(network) , "\""])
end

That’s perfect when it’s used as a datatype in a map or struct but I lose the convenience of seeing the struct in cases like:

iex> CIDR.parse("10.0.0.0/8")
~n"10.0.0.0/8"

It may be asking for a lot but is there anything contextual in Inspect that would allow me to use the short form when it’s a nested value but the long form when it’s the parent structure displayed?

Thanks.