smolcatgirl

smolcatgirl

Allow specifying the type when defining structs

Hi,
I think it would be cool to be able to require a certain type for my fields when I create structs. Like specifying one field should be a integer and another a list. So I am not talking about Ecto schemas but regular structs with type checking. What do you think?
Thanks for reading!

Most Liked

tme_317

tme_317

I use https://github.com/ejpcmac/typed_struct for all of my structs. The built-in dialyzer integration provided by the Elixir LS editor plugin does the checking.

al2o3cr

al2o3cr

What specific operations would this provide? “Type checking” can mean a lot of things in Elixir:

  • compile-time success-type checking, as provided by Dialyzer

  • runtime pattern matching and guards, like:

def some_function_that_wants_a_list(x) when is_list(x) do
  • field enforcement on structs; a mostly compile-time guarantee that specified keys will be in a map tagged with the __struct__ key. For instance, this will fail if the target struct doesn’t have a foo key already: %{target | foo: "bar"}

typed_struct (recommended in this thread) is ultimately just a shorthand for writing a Dialyzer typespec and defstruct; the compiler ultimately sees the same code.

To return to my original question, what kind of “type checking” behavior are you looking for? For concreteness, let’s imagine we have a “typed struct” called Blog that expects its tags field to be an array of strings. What should the following do:

  • %User{tags: 1234} - wrong type
  • %User{tags: ["a", 1234]) - mixed types in a field
  • %{some_user | tags: 1234} - update with wrong type
  • %{some_user | tags: ["a", 1234]} - update with mixed types
  • %{some_user | tags: value_that_might_be_a_list_at_runtime} - compiler has no information
  • Map.put(some_user, :tags, 1234) - structs are maps too

Dialyzer will catch some of these, when it has enough information to prove things are the wrong types - but it’s going to struggle with things like the value_that_might_be_a_list_at_runtime case and give up ENTIRELY on the Map.put one.

Communicating typing failures out of these constructs is going to be difficult - they don’t normally “fail”, so the only available option is to crash the process.

Also note that all of these constructs are used extensively in Elixir’s implementation - so any overhead added will be significantly amplified. That’s one reason to prefer an opt-in library like Ecto.Schema, which layers the additional functionality onto bare structs instead of adding more complexity directly to them.

mat-hek

mat-hek

Membrane Core Team

What are you worried about? A several dozen of kilobytes extra on your drive?

Maybe about

  • the need for keeping track of updates of that dependency
  • potential conflicts delaying updates of other dependencies
  • introducing potential vulnerabilities
  • extended compilation time
  • waking up when a dozen kilobytes turns into hundreds of megabytes, as in case of NPM and node_modules

So definitely having as little unused stuff in your deps as possible is a good approach :wink:

Where Next?

Popular in Discussions Top

laiboonh
Hi all, I am trying to convince my team to use liveview over the current react. What are some of the points where one should consider us...
New
WildYorkies
It seems that the more I read, the more I find Elixir users speaking about all the ways that Elixir is not good for x, y, and z use cases...
New
owaisqayum
I have a sample string sentence = "Hello, world ... 123 *** ^%&*())^% %%:>" From this string, I want to only keep the integers, ...
New
AstonJ
Are there any Elixir or Erlang libraries that help with this? I’ve been thinking how streaming services like twitch have exploded recentl...
New
Qqwy
Looking at the stacks that existing large companies have used, WhatsApp internally uses Mnesia to store the messages, while Discord uses ...
New
WolfDan
After doing a port from a c++ library to my project in phoenix I’ve seen that I need a faster way to run this algorithm and I found this ...
New
mmport80
I have put far too much effort into Dialyzer over the last year or so - and basically - I doubt it’s worth the effort. It’s not as easy ...
New
sergio
There’s a new TIOBE index report that came out that shows Elixir is still not in the top 50 used languages. It also goes on to call Elix...
New
pdgonzalez872
If this has been asked here before, please point me to where it was asked as I didn’t find it when I searched the forum. Maybe a mailing ...
New
kostonstyle
Hi all How can I compare haskell with elixir, included tools, webservices, ect. Thanks
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
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
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
hariharasudhan94
Lets say i have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => "XX...
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
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement