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

The name of the pictureThe name of the pictureThe name of the pictureClash 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?







share|improve this question
























    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?







    share|improve this question






















      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?







      share|improve this question












      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?









      share|improve this question











      share|improve this question




      share|improve this question










      asked Sep 1 at 16:07









      DavidR

      1232




      1232




















          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]]





          share|improve this answer




















          • 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




            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










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

















          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]
          ];





          share|improve this answer






















            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "387"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            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






























            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]]





            share|improve this answer




















            • 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




              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










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














            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]]





            share|improve this answer




















            • 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




              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










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












            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]]





            share|improve this answer












            Localize x in a Module:



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






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Sep 1 at 16:17









            John Doty

            6,0941924




            6,0941924











            • 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




              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










            • @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






            • 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










            • @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















            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










            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]
            ];





            share|improve this answer


























              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]
              ];





              share|improve this answer
























                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]
                ];





                share|improve this answer














                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]
                ];






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Sep 1 at 20:41

























                answered Sep 1 at 19:00









                Michael E2

                140k11191457




                140k11191457



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    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













































































                    Comments

                    Popular posts from this blog

                    What does second last employer means? [closed]

                    List of Gilmore Girls characters

                    Confectionery