Skip to content

Conversation

@Keno
Copy link
Member

@Keno Keno commented Aug 27, 2025

There is some persistent confusion around the term functor. There is of course a well established mathematical definition, but some programming languages have taken to reuse the term for various sorts of callable objects. Julia should not be one of them, and we did (as mentioned below) actually reach this conclusion ten years ago. Yet the terminology has somewhat stubbornly persisted. This commit removes it. However, it is only fair that when one makes sweeping categorical proclamations on terminology, there should be some history and justification that can be linked to in the future, so I will attempt to do so in this commit message.

History

(Claude helped with the research in this section, if I missed something,
please let me know, so I can go yell at Claude)

The first use of the term functors in Julia was in 2014 5c91960, introducing special function objects for common generic functions to improve performance of reductions. This was before we were able to specialize. These were refactored a bit in 0c631f8 (using call overloading instead), and 6e715da (split out into a separate file functors.jl), before ultimately being deprecated and removed in 2016. However, it should be noted that this only ever referred to this very particular design pattern, which hasn't been in the code base since 2016.

The use that is still in there stems from the documentation and was introduced in Jan 2015 in 11ab1b3. That said, while even this documentation called the callable objects themselves functors, julia looked a fair bit different at the time with call overloading using a generic function Base.call(f, args...) (i.e. there was a much stronger distinction between generic functions and ordinary objects). Moreover, this transformation is functorial in the mathematical sense. That no longer holds true as much in modern julia. In any case, by 6 months later (aac4eca) we had decided not to use the term functor for this and switched mostly to function object although additional references remained.

However, as I hope this makes clear, this terminology was never wide-spread in julia itself.

Argument

I think the central use of the term functor in mathematics and (compatibly) in functional programming is dispositive of the debate, particularly given the strong functional programming influences in julia.

However, suppose we didn't care about that. Even in that case functor would still be bad terminology in modern Julia. In C++, the distinction is clear. There are first class functions and then there are classes that implement operator() and they are very much not the same, so it makes sense to distinguish them (even if the precise choice of terminology is unforunate). In the original version in Julia where we had Base.call, this was arguably analogous, but in modern julia where there is just one big method table and no fundamental distinction between functions and other kinds of objects, we can no longer make a semantic distinction. I also think it's unclear what people exactly mean by functor, and I think for any of the possible meanings there is a better and more precise term we use more commonly.

  1. For something that can be called, I think we generally just use function, but if you want to emphasize that it applies to non-Function types as well, callable is a fine term.

  2. Specifically for structs that have (::Foo)(a, b) methods. However, callable struct is precise here.

  3. Only for those structs 2 that are also non-singleton or contain mutable state. I think it's pretty rare to specifically need to refer to these and I think when people do, they often forget that closure are also non-singleton and can reference mutable state (through implicitly introduced boxes). If that's what you mean, I think you just need to be precise about it.

  4. To emphasize the struct that contains such data itself (as opposed to the function called). Here, I think function object is the best terminology we have, specifically since it emphasizes the object.

It's possible I've missed a meaning that people have in mind, but I think that's precisely the problem. So, let's remove this term (as we had already decided 10 years ago).

There is some persistent confusion around the term functor.
There is of course a well established mathemtical definitions, but
some programming langauges have taken to reuse the term for various
sorts of callable objects. Julia should not be one of them, and we
did (as mentioned below) actually reach this conclusion ten years ago.
Yet the terminology has somewhat stubbornly persisted. This commit
removes it. However, its only fair that when one makes sweeping
categorical proclamations on terminology, there should be some history
and justification that can be linked to in the future, so I will attempt
to do so in this commit message.

# History

(Claude helped with the research in this section, if I missed something,
 please let me know, so I can go yell at Claude)

The first use of the term functors in Julia was in 2014 5c91960,
introducing special function objects for common generic functions
to improve performance of reductions. This was before we were able to
specialize. These were refactored a bit in 0c631f8 (using call
overloading instead), and 6e715da (split out into a separate file
functors.jl), before ultimately being deprecated and removed in 2016.
However, it should be noted that this only ever referred to this very
particular design pattern, which hasn't been in the code base since
2016.

The use that is still in there stems from the documentation and was
introduced ini Jan 2015 in 11ab1b3. That said, while even this
documentation called the callable objects themselves `functors`,
julia looked a fair bit different at the time with call overloading
using a generic function `Base.call(f, args...)` (i.e. there was
a much stronger distinction between generic functions and ordinary
objects). Moreover, this transformation is functorial in the
mathematical sense. That no longer holds true as much in modern
julia. In any case, by 6 months later (aac4eca) we had decided not to use
the term `functor` for this and switched mostly to `function object`
although additional references remained.

# Argument

I think the central use of the term `functor` in mathematics and
(compatibly) in functional programming is dispositive of the debate,
particularly given the strong functional programming influences in
julia.

However, suppose we didn't care about that. Even in that case `functor`
would still be bad terminology in modern Julia. In C++, the distinction
is clear. There are first class functions and then there are classes
that implement `operator()` and they are very much not the same, so it
makes sense to distinguish them (even if the precise choice of
terminology is unforunate). In the original version in Julia where we
had `Base.call`, this was arguably analogous, but in modern julia where
there is just one big method table and no fundamental distinction
between functions and other kinds of objects, we can no longer make a
semantic distinction. I also think it's unclear what people exactly mean
by `functor`, and I think for any of the possible meanings there is a
better and more precise term we use more commonly.

1. For something that can be called, I think we generally just use
   function, but if you want to emphasize that it applies to non-Function
   types as well, `callable` is a fine term.

2. Specifically for structs that have `(::Foo)(a, b)` methods. However,
   `callable struct` is precise here.

3. Only for those structs 2 that are also non-singleton or contain
   mutable state. I think it's pretty rare to specifically need to
   refer to these and I think when people do, they often forget that
   closure are also non-singleton and can reference mutable state
   (through implicitly introduced boxes). If that's what you mean,
   I think you just need to be precise about it.

4. To emphasize the struct that contains such data itself (as opposed
   to the function called). Here, I think `function object` is the
   best terminology we have, specifically since it emphasizes the object.

It's possible I've missed a meaning that people have in mind, but
I think that's precisely the problem. So, let's remove this term
(as we had already decided 10 years ago).
@nsajko nsajko added the docs This change adds or pertains to documentation label Aug 27, 2025
@Keno Keno merged commit d335458 into master Aug 28, 2025
13 checks passed
@Keno Keno deleted the kf/nofunctor branch August 28, 2025 01:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs This change adds or pertains to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants