How to use a variable in a function that can't be clobbered by variable name collision?

How to use a variable in a function that can't be clobbered by variable name collision?



Not really sure what the right question to ask is. But here's what I'm having trouble with:


ClearAll[Evaluate[Context <> "*"]]
klDivergence[d1_, d2_] := NExpectation[Log[ PDF[d1, x]/PDF[d2, x] ], x [Distributed] d1]
d1 = NormalDistribution[0, 1];
d2 = NormalDistribution[5, 1];
klDivergence[d1, d2]
x=0
klDivergence[d1, d2]



The first call to klDivergence works fine. The second one gives me an error or warning "NIntegrate::itraw: Raw object 0 cannot be used as an iterator."



What's the right way to code this, so that I can have a variable of integration inside my function that is not affected by external code?




2 Answers
2



Localize x in a Module:


x


Module


klDivergence[d1_, d2_] := Module[x,
NExpectation[Log[PDF[d1, x]/PDF[d2, x]], x [Distributed] d1]]





A minor oversight in the language is that With[x, ...] is not allowed. It would be nice to be able to immutably localize a free variable, thus also protecting it from clobberage inside the function.
– John Doty
Sep 1 at 16:30


With[x, ...]





One could also use [FormalX] as in klDivergence[d1_, d2_] := NExpectation[ Log[PDF[d1, [FormalX]]/ PDF[d2, [FormalX]]], [FormalX] [Distributed] d1]. It cannot be overwritten because it is Protected. Comes close to With[x, ...], doesn't it?
– Henrik Schumacher
Sep 1 at 17:23


[FormalX]


klDivergence[d1_, d2_] := NExpectation[ Log[PDF[d1, [FormalX]]/ PDF[d2, [FormalX]]], [FormalX] [Distributed] d1]


Protected


With[x, ...]





@HenrikSchumacher It can be overwritten with Block[[FormalX] = 1,...].
– Michael E2
Sep 1 at 18:18


Block[[FormalX] = 1,...]





@MichaelE2 Oha, you're right! Okay, a further reason not to use it. =D
– Henrik Schumacher
Sep 1 at 18:20



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:


Module


K[n]


n


K[n]


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.


K


Protected


K


K



A little safer would be to Block K.


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."


K


NExpectation


K



Another method used sometimes is to create one's own, perhaps Private`, context; for example, foo`x or foo`Private`x:


Private`


foo`x


foo`Private`x


klDivergence[d1_, d2_] := Block[foo`x,
NExpectation[Log[PDF[d1, foo`x]/PDF[d2, foo`x]],
foo`x [Distributed] d1]
];



Thanks for contributing an answer to Mathematica Stack Exchange!



But avoid



Use MathJax to format equations. MathJax reference.



To learn more, see our tips on writing great answers.



Some of your past answers have not been well-received, and you're in danger of being blocked from answering.



Please pay close attention to the following guidance:



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)