Distances.jl
Distances.jl copied to clipboard
rename evaluate to distance
unless it was a conscious decision to avoid a distance function.
Not sure what we gain from making this change.
I just feel like the name evaluate is much more general than what this package does.
evaluate() is also just a longer form of eval() which does something completely different.
I agree in part with it, the name evaluate() is too general, but the function call is unambiguous, no confusion with eval(). I vote to close the issue.
Why don't we use call overloading of each distance type here?
compare would work well (like in this Scala library).
Just to clarify my proposal. I think, it would be better with
julia> Euclidean()(randn(10), randn(10))
4.28348729614181
Are there any places where this would cause trouble?
@andreasnoack I think I still prefer the current syntax euclidean(rand(10), rand(10)) than Euclidean()(randn(10), randn(10))
my compare idea is not great either: two vectors are comparable when they're distant, so it's more of an antonym.
I opened this issue because, while I dislike evaluate, I wanted to keep a consistent API in a package I'm writing that computes string distance. I just now define compare there to compute similarity scores, and so it works out. Feel free to close.
How would the euclidean way work with distances that store data in internal fields? Andreas' way feels more natural where you create the type and call it.
@andreasnoack The first set of parentheses is not necessary when you do call overloading on the type rather than the instance. Here's what a different example looks like:
immutable SavitzkyGolayFilter{M,N} end
Base.call{M,N,T}(::Type{SavitzkyGolayFilter{M,N}}, data::AbstractVector{T}) = ...
...
julia> SavitzkyGolayFilter{2,3}([1:11])
[0.9142857142857141,1.9999999999999996,3.0,3.9999999999999987,4.999999999999998,5.999999999999998,6.999999999999998,7.999999999999998,8.999999999999998,11.028571428571425,7.999999999999998]
this is old now, but as I am starting to potentially use this package, I wanted to add I like both the call overloading and the evaluate better than any of the other approaches. Both feel natural. To avoid breaking compatibility one could just make the call overloading syntax sugar for evaluate.
I (still) think that call overloading of instances is the way to go here.
related issue: #109
an advantage of overloading of instances is to make evaluate not so ambiguous. For example,
# generic.jl
evaluate(d::PreMetric, a, b) = d(a, b)
# metrics.jl
# we need to move current definition from evaluate to concrete distances
function (d::Euclidean)(a, b)
...
end
That is to say, if someone implemented a too general version of Euclidean, it won't affect evaluate at all, the ambiguity stays in Euclidean, which eases the debug as well.
I suffer a lot fixing ambiguities expanding evaluate in ImageDistances.jl for image inputs.
@KristofferC Would like to hear your advice on https://github.com/JuliaImages/ImageDistances.jl/issues/28
evaluate is a verb while distance is a noun. Except for the widely used Base symbols, IMO a verb is more important in Julia's dispatching system; by calling evaluate(d, a, b) it pronounces as "evaluate the distance d on data a and b".
To avoid name conflict, it should be evaluate_distance.