# Operators without built-in meaning are incompatible with parallel evaluation

Mathematica has a useful set of Operators Without Built-In Meanings. For example: CenterDot, CircleDot, CirclePlus, Star, etc. According to the linked documentation, a user is allowed to define evaluation rules for these symbols. Unfortunately, these symbols are not compatible with parallel evaluation. The following example shows how parallel evaluation leads to an incorrect result when user-defined evaluation rule for CenterDot is used:

CenterDot = Times;
DistributeDefinitions[CenterDot];
f[n_] := Coefficient[CenterDot[n, x], x];

Table[f[n],{n,1,5}]


{1,2,3,4,5} (* correct *)

ParallelTable[f[n],{n,1,5}]


{0,0,0,0,0} (* wrong *)

I think that the root cause of this bug is that parallel evaluation routines are not allowed to distribute definitions of any symbols from System context while all Operators Without Built-In Meanings are defined in this very context.

Is there a practical way to use Operators Without Built-In Meanings in parallel calculations?

This question is based on observations made here, where accepted workaround was just to abandon such operators altogether.

• Some comments to one of your linked questions suggest using ParallelEvaluate: (1), (2) Aug 6, 2019 at 10:31

Is there a practical way to use Operators Without Built-In Meanings in parallel calculations?

The simpler workaround is to create the definition directly on the parallel kernels.

CenterDot = Times
ParallelEvaluate[CenterDot = Times]


This must be done every time after a new subkernel is started.

A better solution is to put the definitions in a package and load that package using ParallelNeeds. This is more robust because ParallelNeeds affects not only currently running subkernels, but also subkernels that will be started in the future. I'd recommend this second approach.

Yes, I agree that this is a bug but one stemming from Operators without built-in meanings being placed in the System context and not in the Globalcontext. While Szabolcs' solution works for computations in parallel as a single user (and assuming you haven't used this operator in the distant past) it doesn't solve the more general problem that you can't distribute more broadly (parallel or otherwise, in packages or otherwise) and be confident in your code's robustness.

This is because you run the risk of interfering with, or being interfered by, end-users own definitions of CenterDot (hardly a negligible risk). In other words, even package encapsulation and/or public shadowing can't manage any potential naming conflicts when these operators reside in the System context. Perhaps WRI is signalling an option to give these operators built-in meanings down the track but this is diametrically opposed to their whole promotion as being Operators without Built-in Meanings and the reasonable, accompanying expectation that it will ever be thus.

It's a serious issue for the whole operator framework since these definitions don't even have to involve public definitions/notation with any presence deep inside a package exposing the package to this insidious risk.

The takeaway is that if you intend your code to be robustly used by others (or your future self or at least want to keep these possibilities open) then it is best to avoid using operators without built-in meaning unless they appear in the Global context (currently none appear to).

To highlight this point this post's title might be more accurately changed from:

Operators without built-in meaning are incompatible with parallel evaluation.

to

Operators without built-in meaning are incompatible with robust, portable code.