I’d like to know how each score function contributed to the final score.
So I want to change the type being changed from a float to a list of tagged floats.
But I might changed the type again so ideally, I’d like to DRY it up to
reduce future typing.
So my thought was to encapsulate the function’s type using @type and reuse it in @spec.
The rereading the typespec documentation several times, I discovered
what I think is the correct syntax for the function @type:
You don’t need the scorer type.
what you need is just
@type score :: [{atom, float}]
@type data :: any
@spec score_feature_a(score, data) :: score
def score_feature_a(score, data), do: ...
...
end
I think you have mixed up concepts… your scorer type what it does is represent an anonymous function of arity 2. Unless you are passing or returning an anonymous function you shouldn’t use that.
To spec regular functions you just do it the way I have shown in my exmaple above.
Note: be careful to include spaces after a comma and surrounding operators with a while space as in the -> case.
But I want the scorer type.
Because when I decide all my scoring functions will have a different signature,
I only want to change that in one place: @type scorer …
Are you saying i can’t reuse the scorer type within the @spec of my scoring functions?
That’s disappointing.
I think you are a bit confused with what functions return.
Functions returns values, they do not necessarily need to return a function. The body of the spec describes the function, as we are already describing it here score_feature_a(scoring, data) so the return value (what comes after the ::) is only scoring,
A concrete example·
@spec double(integer) :: integer
def double(x), do: x * 2
I am not trying to express it like that.
That was an early attempt to illustrate what I wanted by what didn’t work.
I’m trying to figure out if there’s a way to reuse a functional @type in a function’s @spec.
I’m guessing it’s the quirk arising from the fact that Elixir has two ways to denote functions:
anonymous functions, e.g fn scoring, data -> data end
named functions, e.g. def score_feature_a(scoring, data), do: data
and maybe they have subtly different types so maybe I can’t.
The docs are very slim on functional types.
There’s a mention in the grammar and that’s it.
Someone else even posted complaining about it.
I’ve coded in many functional languages and even written a compiler or two and this
is the first language I’ve come across that distinguishes between those two use case.
In all the others,
f = fn a, b -> b end
would be equivalent to
def f(a, b), do b end
and they would have the same type.
So if I can’t use the type of the anonymous function not,
is there a way to encapsulate and reuse the named function’s type?
I’m beginning to think not…
I see what you mean now. I don’t think that out of the box that is possible, at least with the specs defined through @spec and Dialyzer. Maybe you can look into alternatives to Dialyzer.