How to use a variable in a function that can't be clobbered by variable name collision?
Clash Royale CLAN TAG#URR8PPP
up vote
4
down vote
favorite
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?
function-construction variable-definitions
add a comment |Â
up vote
4
down vote
favorite
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?
function-construction variable-definitions
add a comment |Â
up vote
4
down vote
favorite
up vote
4
down vote
favorite
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?
function-construction variable-definitions
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?
function-construction variable-definitions
asked Sep 1 at 16:07
DavidR
1232
1232
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
6
down vote
accepted
Localize x
in a Module
:
klDivergence[d1_, d2_] := Module[x,
NExpectation[Log[PDF[d1, x]/PDF[d2, x]], x [Distributed] d1]]
A minor oversight in the language is thatWith[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
1
One could also use[FormalX]
as inklDivergence[d1_, d2_] := NExpectation[ Log[PDF[d1, [FormalX]]/ PDF[d2, [FormalX]]], [FormalX] [Distributed] d1]
. It cannot be overwritten because it isProtected
. Comes close toWith[x, ...]
, doesn't it?
– Henrik Schumacher
Sep 1 at 17:23
@HenrikSchumacher It can be overwritten withBlock[[FormalX] = 1,...]
.
– Michael E2
Sep 1 at 18:18
@MichaelE2 Oha, you're right! Okay, a further reason not to use it. =D
– Henrik Schumacher
Sep 1 at 18:20
add a comment |Â
up vote
2
down vote
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]
];
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
6
down vote
accepted
Localize x
in a Module
:
klDivergence[d1_, d2_] := Module[x,
NExpectation[Log[PDF[d1, x]/PDF[d2, x]], x [Distributed] d1]]
A minor oversight in the language is thatWith[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
1
One could also use[FormalX]
as inklDivergence[d1_, d2_] := NExpectation[ Log[PDF[d1, [FormalX]]/ PDF[d2, [FormalX]]], [FormalX] [Distributed] d1]
. It cannot be overwritten because it isProtected
. Comes close toWith[x, ...]
, doesn't it?
– Henrik Schumacher
Sep 1 at 17:23
@HenrikSchumacher It can be overwritten withBlock[[FormalX] = 1,...]
.
– Michael E2
Sep 1 at 18:18
@MichaelE2 Oha, you're right! Okay, a further reason not to use it. =D
– Henrik Schumacher
Sep 1 at 18:20
add a comment |Â
up vote
6
down vote
accepted
Localize x
in a Module
:
klDivergence[d1_, d2_] := Module[x,
NExpectation[Log[PDF[d1, x]/PDF[d2, x]], x [Distributed] d1]]
A minor oversight in the language is thatWith[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
1
One could also use[FormalX]
as inklDivergence[d1_, d2_] := NExpectation[ Log[PDF[d1, [FormalX]]/ PDF[d2, [FormalX]]], [FormalX] [Distributed] d1]
. It cannot be overwritten because it isProtected
. Comes close toWith[x, ...]
, doesn't it?
– Henrik Schumacher
Sep 1 at 17:23
@HenrikSchumacher It can be overwritten withBlock[[FormalX] = 1,...]
.
– Michael E2
Sep 1 at 18:18
@MichaelE2 Oha, you're right! Okay, a further reason not to use it. =D
– Henrik Schumacher
Sep 1 at 18:20
add a comment |Â
up vote
6
down vote
accepted
up vote
6
down vote
accepted
Localize x
in a Module
:
klDivergence[d1_, d2_] := Module[x,
NExpectation[Log[PDF[d1, x]/PDF[d2, x]], x [Distributed] d1]]
Localize x
in a Module
:
klDivergence[d1_, d2_] := Module[x,
NExpectation[Log[PDF[d1, x]/PDF[d2, x]], x [Distributed] d1]]
answered Sep 1 at 16:17
John Doty
6,0941924
6,0941924
A minor oversight in the language is thatWith[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
1
One could also use[FormalX]
as inklDivergence[d1_, d2_] := NExpectation[ Log[PDF[d1, [FormalX]]/ PDF[d2, [FormalX]]], [FormalX] [Distributed] d1]
. It cannot be overwritten because it isProtected
. Comes close toWith[x, ...]
, doesn't it?
– Henrik Schumacher
Sep 1 at 17:23
@HenrikSchumacher It can be overwritten withBlock[[FormalX] = 1,...]
.
– Michael E2
Sep 1 at 18:18
@MichaelE2 Oha, you're right! Okay, a further reason not to use it. =D
– Henrik Schumacher
Sep 1 at 18:20
add a comment |Â
A minor oversight in the language is thatWith[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
1
One could also use[FormalX]
as inklDivergence[d1_, d2_] := NExpectation[ Log[PDF[d1, [FormalX]]/ PDF[d2, [FormalX]]], [FormalX] [Distributed] d1]
. It cannot be overwritten because it isProtected
. Comes close toWith[x, ...]
, doesn't it?
– Henrik Schumacher
Sep 1 at 17:23
@HenrikSchumacher It can be overwritten withBlock[[FormalX] = 1,...]
.
– Michael E2
Sep 1 at 18:18
@MichaelE2 Oha, you're right! Okay, a further reason not to use it. =D
– Henrik Schumacher
Sep 1 at 18:20
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
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
1
1
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
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
@HenrikSchumacher It can be overwritten with
Block[[FormalX] = 1,...]
.– Michael E2
Sep 1 at 18:18
@HenrikSchumacher It can be overwritten with
Block[[FormalX] = 1,...]
.– Michael E2
Sep 1 at 18:18
@MichaelE2 Oha, you're right! Okay, a further reason not to use it. =D
– Henrik Schumacher
Sep 1 at 18:20
@MichaelE2 Oha, you're right! Okay, a further reason not to use it. =D
– Henrik Schumacher
Sep 1 at 18:20
add a comment |Â
up vote
2
down vote
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]
];
add a comment |Â
up vote
2
down vote
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]
];
add a comment |Â
up vote
2
down vote
up vote
2
down vote
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]
];
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]
];
edited Sep 1 at 20:41
answered Sep 1 at 19:00
Michael E2
140k11191457
140k11191457
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f181066%2fhow-to-use-a-variable-in-a-function-that-cant-be-clobbered-by-variable-name-col%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password