Does anybody else feel this way about @spec (visually overpowering)?

And keep up with bug fixes, patches and releases. Which is why I said it’s not necessarily a simple thing to do. :frowning:

I’m not trying to change the language or compiler. I’m trying to see if there are other people who feel the same way I do and if they have found or come up with any good solutions.

1 Like

It gives you information, for readability and understanding. It does not enforce types in the function, and as far as I know it does not change anything about the function when compiled and is not part of the function execution. That is my argument for considering it closer to documentation than code.

That’s only if you want to enforce the argument types.

1 Like

@ryanwinchester This seam like a really good case for a PR there would make the styling more flexible
it could be nice to be able to define it in the settings.

the only other option here is just not to use specs.

1 Like

Well, considering you’re running VS Code, the extension you (should) use actually does continuous checking of type specs by way of dialyzer without any additional configuration, so with that in mind it’s not quite as deferred as you make it seem. Normally, I’d agree with your sentiment, but not with this specific extension.

1 Like

They are annotations for you to read, and that tools can also use to help you. There are tools (and IDEs) that also use PHP docblocks to do the same thing.

That feeling may simply be informed by your previous personal experience.

For example someone who has worked primarily with dynamically typed languages may not attach a lot of importance to explicitly declared types.

It does not enforce types in the function, and as far as I know it does not change anything about the function when compiled and is not part of the function execution.

The specs are an input for success typing so they actually go beyond “mere” documentation. But viewing syntax highlighted code in an editor is entirely for the benefit of the human reader anyway.

I for one consider the intended types to be important and useful information regardless whether the actual code requires them or not - so I appreciate the additional emphasis even against the “real code” (the whole “thinking in types” thing).

But obviously that is a YMMV issue that can to be controlled via configuration of the viewing/editing tools.

1 Like

Yep. It’s a pity it’s not enforcing types in compilation time.

But in some way it can enforce some kind of type cheks when you are using dialyzer - as some kind of additional step before compilation.

You know that you can move it closer to documentation by defining just empty function clause and place your @spec there with documentation anywhere in your file. It will not pollute your function definition with implementation.


# you got here just plain function
def some_function(some_arg) do
  #some implementation
end


#Many code here


@doc """
Quite good docs.
"""
@spec some_function(SomeType.t()) :: SomeOtherType.t()
def some_function(some_arg)

But that way you lost some code readability and it’s harder to understand what is going on in some_function() implementation. :slight_smile:

1 Like

… and the one you use happens to be one of the tools that does this by default, which means that this feeling you have of them not being important while developing, other than informing the programmer, is practically speaking misguided.

I’m still wondering exactly what it is that you hope to do about this, considering you’re basically shooting down any suggestion that you’ve been given. You have the tools to change this for yourself in order to make the type specs less pronounced. What’s this discussion actually about?

2 Likes

Uhh, why would you not want to? Types put into comments is as good as no types at all as far as the compiler is concerned… o.O

Do note, dialyzer is part of and comes with the BEAM/OTP.

Add it as a git pre-commit hook or in your CI or as part of your compilation command itself. :wink:

I would so very much love this instead:

def some_function(some_arg :: SomeType.t()) :: SomeOtherType.t() do
  ...
end

Then have each head be properly combined and all finally as a BEAM spec. :slight_smile:

6 Likes

:slight_smile: Yeah I got it in script additionally with credo --strict

It reminds me statically typed languages with “looong” function heads. :wink:

Personally I like more the way with annotation like in Haskell or Elixir, why?, because firstly I write @spec so I need only to name function and define its types (how it works - inputs and output). After that I have to think up the name for arguments. I got some separation from named things and types.

2 Likes

I prefer them together (if the type cannot be left out entirely due to it being properly inferred) so I can see what type and name something is both as I’m using it. I don’t need to see just the type in a file as when I’m programming the IDE will show my the types of things as I type to call something anyway. :slight_smile:

I guess it’d be better if they were on their own lines if you had to have types if you did not have an IDE worth using, but thankfully that is not today’s world. ^.^

1 Like

I could not agree more. @specs are really quite ugly.

I suggest putting a blank line between your @specs and function heads.

2 Likes

I think you are missing my point. I never said they were not important. They are there to provide info, to you or to tools. That’s important.

1 Like

Yes, I think that’s a concise summary. Hence the question in my previous post: What’s the goal here? I think making your own modification to ElixirLS is trivial and the only upkeep you’d need to do personally is to git pull their changes whenever you feel like it. Considering the minor changes you’d make for this conflicts are extremely unlikely. At “worst”, you’d make a PR to make the syntax highlighting of @spec configurable.

1 Like

Because type-hinting in PHP actually kind of sucks for a really long time (although they are fixing it). If you want to pass in an iterable object, or an array you couldn’t enforce a type if you want the users of your library to be able to use either, even though either are iterable. You can typehint for array or ArrayAccess but not both. You could type hint for an iterable object or an array, but not both. So, there are cases where enforcing types in PHP can kind of suck for your users. A docblock in PHP is similar to a @spec in elixir. You can have static analysis, IDEs can provider autocomplete and hints, etc. but they aren’t used by compiler or execution.

Exactly why you should use a language with better types! Great example! ^.^

1 Like

Have any recommendations?

@spec some_function(SomeType.t()) :: SomeOtherType.t()
def some_function(some_arg)

This feels so heavy and much harder to read. Strong/static typing is the feature I really miss in Elixir. Esp. from a security standpoint I really like to know what types of data get in/get out.

+1, this is much better, concise and readable

btw does anybody know where I could find Elixir grammar/formal spec if it exists ?

1 Like

I think the sources of the tokenizer and the parser come closest to what you are asking for.

3 Likes

Again this relates entirely to what you are familiar with.

I used to feel the same way until I realized that declaring names and types in the same definition forced multi-line signatures much faster. Some might argue that keeping names and types separate is actually more concise - similar to how header and row information in a table interact, The spec focuses on typing while the function header focuses on naming - sacrificing easy parameter name/type correlation for focus.

The first approach declares a function type while the second approach types the parameters and the return value - producing a function type as a side effect. (Sometimes “preferences” can get in the way - accept whats there and move on).

3 Likes