bahner

bahner

To struct or not to struct, Decode or not decode

So, I am working with my IPFS client library and I’ve run into dialyzer hell. The code is kinda working fine, but Dialyzer is not happy with me. Before I ignore it completely, I want to make sure I’m not guilty of an anti-pattern.

The IPFS API returns stuff like this:

{
  "BlocksReceived": "<uint64>",
  "BlocksSent": "<uint64>",
  "DataReceived": "<uint64>",
  "DataSent": "<uint64>",
  "DupBlksReceived": "<uint64>",
  "DupDataReceived": "<uint64>",
  "MessagesReceived": "<uint64>",
  "Peers": [
    "<string>"
  ],
  "ProvideBufLen": "<int>",
  "Wantlist": [
    {
      "/": "<cid-string>"
    }
  ]
}

I thought it would be nice to make structs for these types of return values, instead of just passing the JSON back to user. I have made structs to build these, where I have structs for wantlist and CIDs.
myspace-ipfs/wantlist.ex at develop · bahner/myspace-ipfs · GitHub
myspace-ipfs/common.ex at develop · bahner/myspace-ipfs · GitHub

Then I use the structs as components for complex structs and so forth. I like the wantlist.keys notation that they give me when I structure the keys as (existing) atoms.

But when I take a result and pass it to Jason.decode, then dialyser becomes really unhappy. The error messages blow up in length, as I try to fix them. And, hence, I suspect I’m doing it wrong.

Please note. I can’t always use only use the Tesla.Middleware.Jason for this, as the API sometimes returns \n<\n when data is streamed, and there is no known end to the data, so it canæt generate lists, and hence not proper JSON.

Am I doing it wrong by trying to massage the data and should I just pass the JSON strings to the user? Or just let the middleware do its best and decode the lines as they come in.

Most Liked

al2o3cr

al2o3cr

What warnings? Where do they appear? I ask because I’ve seen plenty of very strange messages in-editor when elixir-ls gets confused, but those usually disappear after cleaning _build etc and don’t show up in mix dialyzer.

zachallaun

zachallaun

I personally have dialyzer disabled in my vscode-elixirls settings because I find the warnings very distracting for WIP code. When I am closer to a final version, I run it on the command line to check my assumptions and catch things I missed.

bahner

bahner

I took in the replies I got and learned that I was trying a bit too hard. So i loosened up trying to cram everything into a specific type in the api-module. Refactored the whole thing, in a way that means I have to do a little more work over each function, but have more control. Using the mix dialyzer allowed be to see the errors more clearly in the shell, than as small windows in VS Code.
The hint, that dialyser is usually right made me follow the advice to get a better picture of what iot wanted. And it worked. Thanks.

paulanthonywilson

paulanthonywilson

Fun thing about elixir_ls is that it doesn’t compile to ./_build, but to ./.elixir_ls (specifically ./elixir_ls/build/test). I don’t think I’m alone in occasionally zapping the .elixir_ls directory.

Another fun thing is that dialyzer is almost always correct although often cryptic. (When I say fun, I really mean infuriating.)

As @hlx says, I’d be inclined to also include dialyxir as a dependency (only: [:dev, :test], runtime: false) so you can run mix dialyzer from the terminal and fix the errors, eg with the capitalisation typo MySpaceIPFS instead of MyspaceIPFS, eg here

Also as @hlx alludes {:ok,MyspaceIpfs.RootCid}should probably be{:ok, :MyspaceIpfs.RootCid.t()}` (which I see you’ve defined in the struct).

Where Next?

Popular in Questions Top

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
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
Exadra37
Sometimes I want to check if the input into a function is not a blank string. My first approach: defmodule Example do def do_stuff(s...
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
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

Other popular topics Top

Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
New
peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New

We're in Beta

About us Mission Statement