Defining a type that behaves like a (const) function

Dear community,

I’m trying to define a type that behaves as a function. The usual way is something like

struct T
    z::Int
end

(t::T)(x) = x * t.z 

Then, if t = T(2) we have t(3) == 6.

However there is one way in which t is not like a function. It is not a const. Hence, if I do f(x) = t(x), then f is not inferred (it relies on a non-const global)

julia> @code_warntype f(2)
Variables
  #self#::Core.Compiler.Const(f, false)
  x::Int64

Body::Any
1 ─ %1 = Main.t(x)::Any
└──      return %1

In contrast, t(2) infers fine. If t were a regular function, not just a callable type, f would be inferred, because functions are not only callable, they are consts.

The question: is there any way to define T so that t = T(2) behaves as const t = T(2) (like when one defines a regular function), without requiring that the user specify that const?

The reason, why this doesn’t infer is probably that t is a non-constant global, which is used by f. If you pass t to f as an argument or define it inside of f, this should infer just fine.

Hi @simeonschaub, yes, I understand that. I just wanted to know if I can make f(x) = t(x) inferable, just like f(x) = sin(x) is inferable, without declaring t as a const or passing it as an extra variable. I suspect there is probably no way (after all, anonymous function bindings are not const by default), but wanted to check anyhow.

It depends on what exactly you want to do. You can declare T a mutable struct and make t a constant. You can then still change t.z with t.z = 42, but everything will be type stable.

2 Likes