John Doty's Module
method is used a lot. Alternatively, some internal functions use K[n]
, where n
is an integer chosen to make K[n]
unique, especially for the dummy variable of integration or summation. Something like the following effectively carries this out:
klDivergence[d1_, d2_] :=
With[{serno = Max@{0, Cases[{d1, d2}, K[n_Integer] :> n, Infinity]} + 1},
NExpectation[Log[PDF[d1, K[serno]]/PDF[d2, K[serno]]],
K[serno] \[Distributed] d1]
];
However K
is not Protected
, so the usage is not foolproof. A user can assign a definition to K
and mess the function up; it would also mess up internal functions that use K
. So if what's good enough for Wolfram is good enough for you, you have a solution.
A little safer would be to Block
K
.
klDivergence[d1_, d2_] := Block[{K},
With[{serno = Max@{0, Cases[{d1, d2}, K[n_Integer] :> n, Infinity]} + 1},
NExpectation[Log[PDF[d1, K[serno]]/PDF[d2, K[serno]]],
K[serno] \[Distributed] d1]
]];
This would block any user definition of K
while NExpectation
is being computed. That's probably okay in this use-case, as well as most use cases; however, to block a user's definition from working does seem like a hole for a potential bug to creep through. Of course a user should not be assigning values to K
; that explicit advice is kept from users (i.e., it is not found in the documentation, at least not easily), but it is implied by the advice, "you should always choose names for your own variables that start with lowercase letters."
Another method used sometimes is to create one's own, perhaps Private`
, context; for example, foo`x
or foo`Private`x
:
klDivergence[d1_, d2_] := Block[{foo`x},
NExpectation[Log[PDF[d1, foo`x]/PDF[d2, foo`x]],
foo`x \[Distributed] d1]
];