Remembering Previously Evaluated Function Values with Optional Argument











up vote
6
down vote

favorite
2












I am trying to implement a "Function That Remembers Values It Has Found" (name adjusted from the similarly named Mathematica guide (clicky here)). I have an optional argument and I believe that is giving me some issues, I know that it would be easy if I just gave the value of the optional argument when attempting to recall the function, but that seems to defeat the point of such a mechanism.



Here is an example of my problem (function anonymised for privacy reasons, it is not a function specific issue):



In[1]:= myFun[d_,m_,method_String,degrees_:False]:=
myFun[d,m,method,degrees]=foo[d,m,method,degrees];


If I run it and time it without the optional argument specified, it does not save the result.



In[2]:= Timing[myFun[2,6,"myMethod"];]
Out[2]= {1.73822, Null}

In[3]:= Timing[myFun[2,6,"myMethod"];]
Out[3]= {1.74781, Null}


So I checked with ? myFun and saw that it had indeed been saved with the optional argument specified, so gave that a try:



In[4]:= Timing[myFun[2,6,"myMethod",False];]
Out[4]= {0.000102, Null}


Giving what would have been expected. Is there any way so that I do not have to include my optional argument, it would be a shame if it were no longer optional!










share|improve this question


























    up vote
    6
    down vote

    favorite
    2












    I am trying to implement a "Function That Remembers Values It Has Found" (name adjusted from the similarly named Mathematica guide (clicky here)). I have an optional argument and I believe that is giving me some issues, I know that it would be easy if I just gave the value of the optional argument when attempting to recall the function, but that seems to defeat the point of such a mechanism.



    Here is an example of my problem (function anonymised for privacy reasons, it is not a function specific issue):



    In[1]:= myFun[d_,m_,method_String,degrees_:False]:=
    myFun[d,m,method,degrees]=foo[d,m,method,degrees];


    If I run it and time it without the optional argument specified, it does not save the result.



    In[2]:= Timing[myFun[2,6,"myMethod"];]
    Out[2]= {1.73822, Null}

    In[3]:= Timing[myFun[2,6,"myMethod"];]
    Out[3]= {1.74781, Null}


    So I checked with ? myFun and saw that it had indeed been saved with the optional argument specified, so gave that a try:



    In[4]:= Timing[myFun[2,6,"myMethod",False];]
    Out[4]= {0.000102, Null}


    Giving what would have been expected. Is there any way so that I do not have to include my optional argument, it would be a shame if it were no longer optional!










    share|improve this question
























      up vote
      6
      down vote

      favorite
      2









      up vote
      6
      down vote

      favorite
      2






      2





      I am trying to implement a "Function That Remembers Values It Has Found" (name adjusted from the similarly named Mathematica guide (clicky here)). I have an optional argument and I believe that is giving me some issues, I know that it would be easy if I just gave the value of the optional argument when attempting to recall the function, but that seems to defeat the point of such a mechanism.



      Here is an example of my problem (function anonymised for privacy reasons, it is not a function specific issue):



      In[1]:= myFun[d_,m_,method_String,degrees_:False]:=
      myFun[d,m,method,degrees]=foo[d,m,method,degrees];


      If I run it and time it without the optional argument specified, it does not save the result.



      In[2]:= Timing[myFun[2,6,"myMethod"];]
      Out[2]= {1.73822, Null}

      In[3]:= Timing[myFun[2,6,"myMethod"];]
      Out[3]= {1.74781, Null}


      So I checked with ? myFun and saw that it had indeed been saved with the optional argument specified, so gave that a try:



      In[4]:= Timing[myFun[2,6,"myMethod",False];]
      Out[4]= {0.000102, Null}


      Giving what would have been expected. Is there any way so that I do not have to include my optional argument, it would be a shame if it were no longer optional!










      share|improve this question













      I am trying to implement a "Function That Remembers Values It Has Found" (name adjusted from the similarly named Mathematica guide (clicky here)). I have an optional argument and I believe that is giving me some issues, I know that it would be easy if I just gave the value of the optional argument when attempting to recall the function, but that seems to defeat the point of such a mechanism.



      Here is an example of my problem (function anonymised for privacy reasons, it is not a function specific issue):



      In[1]:= myFun[d_,m_,method_String,degrees_:False]:=
      myFun[d,m,method,degrees]=foo[d,m,method,degrees];


      If I run it and time it without the optional argument specified, it does not save the result.



      In[2]:= Timing[myFun[2,6,"myMethod"];]
      Out[2]= {1.73822, Null}

      In[3]:= Timing[myFun[2,6,"myMethod"];]
      Out[3]= {1.74781, Null}


      So I checked with ? myFun and saw that it had indeed been saved with the optional argument specified, so gave that a try:



      In[4]:= Timing[myFun[2,6,"myMethod",False];]
      Out[4]= {0.000102, Null}


      Giving what would have been expected. Is there any way so that I do not have to include my optional argument, it would be a shame if it were no longer optional!







      functions






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 10 at 20:43









      Daniel Wilson-Nunn

      412210




      412210






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          7
          down vote



          accepted










          You can name the user-call with a pattern and use that for memoization:



          call : myFun2[x_, y_: 23] := call = (Pause[1]; x + y);

          call : myFun3[x_, y_: 23] := call = myFun3[x, y] = (Pause[1]; x + y);


          The first memoizes just the call:



          AbsoluteTiming[myFun2[3]]
          (* {1.00087, 26} *)

          AbsoluteTiming[myFun2[3]]
          (* {1.*10^-6, 26} *)

          AbsoluteTiming[myFun2[3, 23]] (* not memoized *)
          (* {1.00064, 26} *)


          The second memoizes the call, if the call was of the form myFun3[x], and it will memoize the call with the default, myFun3[x, 23], too:



          AbsoluteTiming[myFun3[3]]
          (* {1.00028, 26} *)

          AbsoluteTiming[myFun3[3]]
          (* {1.*10^-6, 26} *)

          AbsoluteTiming[myFun3[3, 23]]
          (* {1.*10^-6, 26} *)


          The double assigment call = myFun3[x, y] =... is innocuously redundant if the call is of the form myFun3[x, y].






          share|improve this answer




























            up vote
            6
            down vote













            There might be more elegant ways to handle this, but a very simple one is to use an extra definition. That means instead of:



            f[x_, n_: 2] := (f[x, n] = (Pause[1]; x^n))


            (note that it usually is a good idea to include a minimal working example in your questions so that people who answer have something to start with...)



            use this:



            ClearAll@f
            f[x_] := f[x, 2]
            f[x_, n_] := (f[x, n] = (Pause[1]; x^n))





            share|improve this answer





















            • Beat me to it :) +1.
              – Leonid Shifrin
              Nov 10 at 21:02










            • Thank you for this, I had been trying to include a MWE, but couldn't think of a function simple enough that would still take a while to evaluate, had completely forgotten about Pause. This solution is very good, but I feel it is rather disappointing that Mathematica cannot handle the optional argument here without additional prompting. Is there a reason for this that I am missing?
              – Daniel Wilson-Nunn
              Nov 10 at 21:07












            • @DanielWilson-Nunn: as you can see from the other answer this can be handled with only one definition. Which of these solutions is preferable will depend on various details of the problem and personal preferences. You would also have to try which variant is faster if that is an issue (I tend to always try performance claims with the actual problem and never guess...)
              – Albert Retey
              Nov 12 at 20:54











            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: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            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%2f185766%2fremembering-previously-evaluated-function-values-with-optional-argument%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            7
            down vote



            accepted










            You can name the user-call with a pattern and use that for memoization:



            call : myFun2[x_, y_: 23] := call = (Pause[1]; x + y);

            call : myFun3[x_, y_: 23] := call = myFun3[x, y] = (Pause[1]; x + y);


            The first memoizes just the call:



            AbsoluteTiming[myFun2[3]]
            (* {1.00087, 26} *)

            AbsoluteTiming[myFun2[3]]
            (* {1.*10^-6, 26} *)

            AbsoluteTiming[myFun2[3, 23]] (* not memoized *)
            (* {1.00064, 26} *)


            The second memoizes the call, if the call was of the form myFun3[x], and it will memoize the call with the default, myFun3[x, 23], too:



            AbsoluteTiming[myFun3[3]]
            (* {1.00028, 26} *)

            AbsoluteTiming[myFun3[3]]
            (* {1.*10^-6, 26} *)

            AbsoluteTiming[myFun3[3, 23]]
            (* {1.*10^-6, 26} *)


            The double assigment call = myFun3[x, y] =... is innocuously redundant if the call is of the form myFun3[x, y].






            share|improve this answer

























              up vote
              7
              down vote



              accepted










              You can name the user-call with a pattern and use that for memoization:



              call : myFun2[x_, y_: 23] := call = (Pause[1]; x + y);

              call : myFun3[x_, y_: 23] := call = myFun3[x, y] = (Pause[1]; x + y);


              The first memoizes just the call:



              AbsoluteTiming[myFun2[3]]
              (* {1.00087, 26} *)

              AbsoluteTiming[myFun2[3]]
              (* {1.*10^-6, 26} *)

              AbsoluteTiming[myFun2[3, 23]] (* not memoized *)
              (* {1.00064, 26} *)


              The second memoizes the call, if the call was of the form myFun3[x], and it will memoize the call with the default, myFun3[x, 23], too:



              AbsoluteTiming[myFun3[3]]
              (* {1.00028, 26} *)

              AbsoluteTiming[myFun3[3]]
              (* {1.*10^-6, 26} *)

              AbsoluteTiming[myFun3[3, 23]]
              (* {1.*10^-6, 26} *)


              The double assigment call = myFun3[x, y] =... is innocuously redundant if the call is of the form myFun3[x, y].






              share|improve this answer























                up vote
                7
                down vote



                accepted







                up vote
                7
                down vote



                accepted






                You can name the user-call with a pattern and use that for memoization:



                call : myFun2[x_, y_: 23] := call = (Pause[1]; x + y);

                call : myFun3[x_, y_: 23] := call = myFun3[x, y] = (Pause[1]; x + y);


                The first memoizes just the call:



                AbsoluteTiming[myFun2[3]]
                (* {1.00087, 26} *)

                AbsoluteTiming[myFun2[3]]
                (* {1.*10^-6, 26} *)

                AbsoluteTiming[myFun2[3, 23]] (* not memoized *)
                (* {1.00064, 26} *)


                The second memoizes the call, if the call was of the form myFun3[x], and it will memoize the call with the default, myFun3[x, 23], too:



                AbsoluteTiming[myFun3[3]]
                (* {1.00028, 26} *)

                AbsoluteTiming[myFun3[3]]
                (* {1.*10^-6, 26} *)

                AbsoluteTiming[myFun3[3, 23]]
                (* {1.*10^-6, 26} *)


                The double assigment call = myFun3[x, y] =... is innocuously redundant if the call is of the form myFun3[x, y].






                share|improve this answer












                You can name the user-call with a pattern and use that for memoization:



                call : myFun2[x_, y_: 23] := call = (Pause[1]; x + y);

                call : myFun3[x_, y_: 23] := call = myFun3[x, y] = (Pause[1]; x + y);


                The first memoizes just the call:



                AbsoluteTiming[myFun2[3]]
                (* {1.00087, 26} *)

                AbsoluteTiming[myFun2[3]]
                (* {1.*10^-6, 26} *)

                AbsoluteTiming[myFun2[3, 23]] (* not memoized *)
                (* {1.00064, 26} *)


                The second memoizes the call, if the call was of the form myFun3[x], and it will memoize the call with the default, myFun3[x, 23], too:



                AbsoluteTiming[myFun3[3]]
                (* {1.00028, 26} *)

                AbsoluteTiming[myFun3[3]]
                (* {1.*10^-6, 26} *)

                AbsoluteTiming[myFun3[3, 23]]
                (* {1.*10^-6, 26} *)


                The double assigment call = myFun3[x, y] =... is innocuously redundant if the call is of the form myFun3[x, y].







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 10 at 22:09









                Michael E2

                143k11192462




                143k11192462






















                    up vote
                    6
                    down vote













                    There might be more elegant ways to handle this, but a very simple one is to use an extra definition. That means instead of:



                    f[x_, n_: 2] := (f[x, n] = (Pause[1]; x^n))


                    (note that it usually is a good idea to include a minimal working example in your questions so that people who answer have something to start with...)



                    use this:



                    ClearAll@f
                    f[x_] := f[x, 2]
                    f[x_, n_] := (f[x, n] = (Pause[1]; x^n))





                    share|improve this answer





















                    • Beat me to it :) +1.
                      – Leonid Shifrin
                      Nov 10 at 21:02










                    • Thank you for this, I had been trying to include a MWE, but couldn't think of a function simple enough that would still take a while to evaluate, had completely forgotten about Pause. This solution is very good, but I feel it is rather disappointing that Mathematica cannot handle the optional argument here without additional prompting. Is there a reason for this that I am missing?
                      – Daniel Wilson-Nunn
                      Nov 10 at 21:07












                    • @DanielWilson-Nunn: as you can see from the other answer this can be handled with only one definition. Which of these solutions is preferable will depend on various details of the problem and personal preferences. You would also have to try which variant is faster if that is an issue (I tend to always try performance claims with the actual problem and never guess...)
                      – Albert Retey
                      Nov 12 at 20:54















                    up vote
                    6
                    down vote













                    There might be more elegant ways to handle this, but a very simple one is to use an extra definition. That means instead of:



                    f[x_, n_: 2] := (f[x, n] = (Pause[1]; x^n))


                    (note that it usually is a good idea to include a minimal working example in your questions so that people who answer have something to start with...)



                    use this:



                    ClearAll@f
                    f[x_] := f[x, 2]
                    f[x_, n_] := (f[x, n] = (Pause[1]; x^n))





                    share|improve this answer





















                    • Beat me to it :) +1.
                      – Leonid Shifrin
                      Nov 10 at 21:02










                    • Thank you for this, I had been trying to include a MWE, but couldn't think of a function simple enough that would still take a while to evaluate, had completely forgotten about Pause. This solution is very good, but I feel it is rather disappointing that Mathematica cannot handle the optional argument here without additional prompting. Is there a reason for this that I am missing?
                      – Daniel Wilson-Nunn
                      Nov 10 at 21:07












                    • @DanielWilson-Nunn: as you can see from the other answer this can be handled with only one definition. Which of these solutions is preferable will depend on various details of the problem and personal preferences. You would also have to try which variant is faster if that is an issue (I tend to always try performance claims with the actual problem and never guess...)
                      – Albert Retey
                      Nov 12 at 20:54













                    up vote
                    6
                    down vote










                    up vote
                    6
                    down vote









                    There might be more elegant ways to handle this, but a very simple one is to use an extra definition. That means instead of:



                    f[x_, n_: 2] := (f[x, n] = (Pause[1]; x^n))


                    (note that it usually is a good idea to include a minimal working example in your questions so that people who answer have something to start with...)



                    use this:



                    ClearAll@f
                    f[x_] := f[x, 2]
                    f[x_, n_] := (f[x, n] = (Pause[1]; x^n))





                    share|improve this answer












                    There might be more elegant ways to handle this, but a very simple one is to use an extra definition. That means instead of:



                    f[x_, n_: 2] := (f[x, n] = (Pause[1]; x^n))


                    (note that it usually is a good idea to include a minimal working example in your questions so that people who answer have something to start with...)



                    use this:



                    ClearAll@f
                    f[x_] := f[x, 2]
                    f[x_, n_] := (f[x, n] = (Pause[1]; x^n))






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 10 at 21:00









                    Albert Retey

                    20.4k4391




                    20.4k4391












                    • Beat me to it :) +1.
                      – Leonid Shifrin
                      Nov 10 at 21:02










                    • Thank you for this, I had been trying to include a MWE, but couldn't think of a function simple enough that would still take a while to evaluate, had completely forgotten about Pause. This solution is very good, but I feel it is rather disappointing that Mathematica cannot handle the optional argument here without additional prompting. Is there a reason for this that I am missing?
                      – Daniel Wilson-Nunn
                      Nov 10 at 21:07












                    • @DanielWilson-Nunn: as you can see from the other answer this can be handled with only one definition. Which of these solutions is preferable will depend on various details of the problem and personal preferences. You would also have to try which variant is faster if that is an issue (I tend to always try performance claims with the actual problem and never guess...)
                      – Albert Retey
                      Nov 12 at 20:54


















                    • Beat me to it :) +1.
                      – Leonid Shifrin
                      Nov 10 at 21:02










                    • Thank you for this, I had been trying to include a MWE, but couldn't think of a function simple enough that would still take a while to evaluate, had completely forgotten about Pause. This solution is very good, but I feel it is rather disappointing that Mathematica cannot handle the optional argument here without additional prompting. Is there a reason for this that I am missing?
                      – Daniel Wilson-Nunn
                      Nov 10 at 21:07












                    • @DanielWilson-Nunn: as you can see from the other answer this can be handled with only one definition. Which of these solutions is preferable will depend on various details of the problem and personal preferences. You would also have to try which variant is faster if that is an issue (I tend to always try performance claims with the actual problem and never guess...)
                      – Albert Retey
                      Nov 12 at 20:54
















                    Beat me to it :) +1.
                    – Leonid Shifrin
                    Nov 10 at 21:02




                    Beat me to it :) +1.
                    – Leonid Shifrin
                    Nov 10 at 21:02












                    Thank you for this, I had been trying to include a MWE, but couldn't think of a function simple enough that would still take a while to evaluate, had completely forgotten about Pause. This solution is very good, but I feel it is rather disappointing that Mathematica cannot handle the optional argument here without additional prompting. Is there a reason for this that I am missing?
                    – Daniel Wilson-Nunn
                    Nov 10 at 21:07






                    Thank you for this, I had been trying to include a MWE, but couldn't think of a function simple enough that would still take a while to evaluate, had completely forgotten about Pause. This solution is very good, but I feel it is rather disappointing that Mathematica cannot handle the optional argument here without additional prompting. Is there a reason for this that I am missing?
                    – Daniel Wilson-Nunn
                    Nov 10 at 21:07














                    @DanielWilson-Nunn: as you can see from the other answer this can be handled with only one definition. Which of these solutions is preferable will depend on various details of the problem and personal preferences. You would also have to try which variant is faster if that is an issue (I tend to always try performance claims with the actual problem and never guess...)
                    – Albert Retey
                    Nov 12 at 20:54




                    @DanielWilson-Nunn: as you can see from the other answer this can be handled with only one definition. Which of these solutions is preferable will depend on various details of the problem and personal preferences. You would also have to try which variant is faster if that is an issue (I tend to always try performance claims with the actual problem and never guess...)
                    – Albert Retey
                    Nov 12 at 20:54


















                     

                    draft saved


                    draft discarded



















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f185766%2fremembering-previously-evaluated-function-values-with-optional-argument%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Full-time equivalent

                    Bicuculline

                    さくらももこ