samgaw

samgaw

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.

Most Liked

fuelen

fuelen

:custom_options key in https://hexdocs.pm/elixir/master/Inspect.Opts.html probably is what you are looking for

lud

lud

Hi,

I don’t think that could be automatic but you could use the inspect options for that:

defmodule Test do
  defmodule CIDR do
    defstruct a: nil, b: nil, c: nil
  end

  def test do
    t = %CIDR{a: 1, b: 2, c: 3}

    IO.inspect(t)
    IO.inspect(t, pretty: true)
  end
end

defimpl Inspect, for: Test.CIDR do
  def inspect(%Test.CIDR{a: a, b: b, c: c} = t, %Inspect.Opts{pretty: true}) do
    "#CIDR<#{a}/#{b}/#{c}>"
  end

  def inspect(%Test.CIDR{a: a, b: b, c: c} = t, _) do
    "#CIDR<#{a}>"
  end
end

Test.test()
#CIDR<1>
#CIDR<1/2/3>

You can also use custom options, or other options from Inspect.Opts.

Of course that would still be up to you to pass or not the option that would change the result. Options will be passed down to your implementation from the implementation for lists.

Where Next?

Popular in Questions Top

minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

We're in Beta

About us Mission Statement