-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Type checking when defining a struct #3
Comments
Hi @mkaszubowski! As stated on the roadmap, I don’t know if this is really possible and I have no idea how to do this. It is here because it would be great and it deserves some research. I think the main problem is we are dealing with Dialyzer types, which indeed is an external tool. IdeasUsing a reduced set of typesA bit like Ecto, which defines its types. This way we could check the types at compile time, but at the cost of a lost in expressiveness. I don’t think this is a good path to explore. Calling DialyzerI don’t have checked yet if Dialyzer has an API. If yes we could call it from TypedStruct. However I don’t think it is a good idea because Dialyzer can be slow do build PLTs. Using a hackWe could produce some code that Dialyzer could then check. Things like: field :with_default, String.t(), default: 5
# Generates
@spec __with_default_default__ :: String.t()
def __with_default_default__, do: 5 # Would lead to a Dialyzer warning I didn’t test at the moment if it works, but I assume the problem would be the strangeness of the warning: the generated code is not visible to the user. |
Just an update on this: in the current version, Dialyzer warns when creating a struct with the default value if it does not match. For instance: defmodule Struct do
use TypedStruct
typedstruct do
field :with_default, String.t(), default: 5
end
@spec new :: t()
def new do
%__MODULE__{}
end
end leads to this warning:
|
Sure, I know it is hard, that's why I wanted to discuss this :) I'll try to describe my approach here (as I've said, I'd really like to have something like this available, so I hope we can finally figure something out). My idea was to "override" the defmodule TypedStruct do
defmacro __using__(_opts) do
quote do
require TypedStruct
import Kernel, except: [defstruct: 1]
import TypedStruct
end
end
# ...
end Then, in the I know, a bit of a hack, but it kind of worked... But only for constants. So I would get an error when doing
because the value of Of course, there are still some problems with that approach, even if it would be possible to implement. Some more information can be found here: https://groups.google.com/forum/#!searchin/elixir-lang-core/structs%7Csort:relevance/elixir-lang-core/U_wdxEqWj_Y/82EaD4D7AAAJ |
Maybe just attach to |
Yeah, but using Ideally, this type checking would be done when creating the struct. So if I did Important thing here is that I'm not talking about a strong type system - this check would not be performed during compilation, but in runtime. |
@mkaszubowski Sorry for my late reply, I’ve been quite busy on other subjects the past few days.
I don’t think it is a good idea to replace the standard implementation with something else. It could lead to problems if something is changed upstream, and it adds confusion about what’s going on under the hood. Plus, I think it is not necessary: we could type-check the default value in
That’s not a problem for what we want to achieve: type-check the default value and return a useful warning if it does not match. If you are talking about validating the struct, this is another story. In this very case, yes a changeset like @hauleth has mentioned can be a good idea, especially if Ecto is splitted in the future. Another idea I had and mentioned in the roadmap it guard generation. I do not intend to type-check when calling With auto-generated guards, we could do something like: # is_struct_user/1 is a guard generated by TypedStruct to enable *optional* type-checking.
def a_function(user) when is_struct_user(user), do: :something |
I would just add |
I don't have a solution for this library but if anyone else is looking for a way to achieve this today, here is how I am doing it.
and then I define my structs like this:
Maybe the solution is to consolidate :vex and :typed_struct libs? |
Just stumbled upon Qqwy/elixir-type_check:
Sounds both, simple and promising enough to give it a try? |
Hi @c-alpha, sorry for my late reply, I was on a long break after a year in a scientific station at the time you wrote this comment and I forgot to reply then. I don’t do much Elixir these times, as I’m mainly doing sysadmin and embedded Rust on my spare time right now, so I won’t have a project to try |
For info, Domo seems also very interesting for checking the types, given a |
Hi! Author of TypeCheck here. Multiple people have expressed interest in using TypeCheck and TypedStruct together, so I'd love to collaborate with TypedStruct to make a plugin. However, that would require TypedStruct's plugin system to be somewhat enhanced: Currently To make it work with TypeCheck, we'd need two changes:
If you want, I can contribute a PR with these changes. |
Hello @Qqwy, glad to hear from you here 😃 I’m starting a long-term project written in Elixir, so I’ll even have an occasion to test TypeCheck myself at some point.
Please go ahead, I’ll review this happily! How do you plan to handle the option to turn off the |
If anybody is reading this so long after the fact, you can use
|
Hi,
I've seen that you have default type checking in the roadmap and I think it would be amazing to have that. May I ask if you have any ideas how to tackle the problem? I am particularly interested in this as I tried to accomplish this few months ago, but unfortunately I failed.
I really hope that we will be able to work something out together :)
The text was updated successfully, but these errors were encountered: