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

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
LegitStack
I’m hoping you guys can give me some general advice and perhaps code examples if you’re feeling up to it. I’m very interested in Elixir,...
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
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
dokuzbir
Hello, I am trying to convert my lists to string without losing brackets.For start i have 3 map. They look like these buyer = %{ id: ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; someth...
New
Codball
Mix format works fine if run from the cmd. I’ve followed this to facilitate the implementation into VSC which involves downloading an ext...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

Other popular topics Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
sergio
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

We're in Beta

About us Mission Statement