When and How to use Types

Maybe Memoize.jl is useful to you.

Anyway, I would probably use a more pedestrian approach, by computing keeping r as a parameter and adding the constant terms, precomputed, to a data structure to be sent to the function as a parameter as well. But of course how practical is that depends on your actual problem.

One alternative which I find cool, although I am not sure if that will fit your needs either, is to use a functor, something like this:

The struct is parametric on the constants, and the constructor computes the constants

julia> struct Test{M,D}
         c1::Float64
         c2::Float64
         Test(m,d) = new{m,d}( m*d, m/d )
       end

Define a functor, which is a function that makes the objects of type Test callable, depending on the constants:

julia> function (t::Test{M,D})(r) where {M,D}
         t.c1*r - t.c2*r
       end

When you define an instance of the type Test, you get the constants:

julia> t = Test(3,4)
Test{3,4}(12.0, 0.75)

And this object can be called with different r, to compute the result:

julia> t(2.5)
28.125