Perform localized, evaluation-leak free replacements












10












$begingroup$


Consider the following expression:



expr = Hold[
{
f[
{1, {Print@1}}
],
g[
{{{Print@1}}}
]
}
];


I'm looking for a way to apply a replacement rule to the contents of all expressions with head f. To give a more concrete example, let's say I want to replace Print by Echo, but only inside f.



Restrictions: I have no knowledge about the exact structure around and inside f - there could be more or less nesting going on. This means the replacement rule can't capture the wrapper with Hold attribute, nor can it capture the individual parts of f[…]. (And the evaluation of Print should be prevented of course)










share|improve this question











$endgroup$

















    10












    $begingroup$


    Consider the following expression:



    expr = Hold[
    {
    f[
    {1, {Print@1}}
    ],
    g[
    {{{Print@1}}}
    ]
    }
    ];


    I'm looking for a way to apply a replacement rule to the contents of all expressions with head f. To give a more concrete example, let's say I want to replace Print by Echo, but only inside f.



    Restrictions: I have no knowledge about the exact structure around and inside f - there could be more or less nesting going on. This means the replacement rule can't capture the wrapper with Hold attribute, nor can it capture the individual parts of f[…]. (And the evaluation of Print should be prevented of course)










    share|improve this question











    $endgroup$















      10












      10








      10


      1



      $begingroup$


      Consider the following expression:



      expr = Hold[
      {
      f[
      {1, {Print@1}}
      ],
      g[
      {{{Print@1}}}
      ]
      }
      ];


      I'm looking for a way to apply a replacement rule to the contents of all expressions with head f. To give a more concrete example, let's say I want to replace Print by Echo, but only inside f.



      Restrictions: I have no knowledge about the exact structure around and inside f - there could be more or less nesting going on. This means the replacement rule can't capture the wrapper with Hold attribute, nor can it capture the individual parts of f[…]. (And the evaluation of Print should be prevented of course)










      share|improve this question











      $endgroup$




      Consider the following expression:



      expr = Hold[
      {
      f[
      {1, {Print@1}}
      ],
      g[
      {{{Print@1}}}
      ]
      }
      ];


      I'm looking for a way to apply a replacement rule to the contents of all expressions with head f. To give a more concrete example, let's say I want to replace Print by Echo, but only inside f.



      Restrictions: I have no knowledge about the exact structure around and inside f - there could be more or less nesting going on. This means the replacement rule can't capture the wrapper with Hold attribute, nor can it capture the individual parts of f[…]. (And the evaluation of Print should be prevented of course)







      evaluation replacement hold






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 6 at 20:07









      Kuba

      104k12203522




      104k12203522










      asked Jan 5 at 16:56









      Lukas LangLukas Lang

      6,6651930




      6,6651930






















          3 Answers
          3






          active

          oldest

          votes


















          11












          $begingroup$

          Here's a way making use of Block to cause f to be inert:



          Block[{f},
          SetAttributes[f, HoldAllComplete];
          expr /. f[args__] :>
          RuleCondition[f[args] /. Print -> Echo]
          ]

          Hold[{f[{1, {Echo[1]}}], g[{{{Print[1]}}}]}]


          Note of course that this only works if you have a pattern of the form _Symbol[...]






          share|improve this answer









          $endgroup$





















            8












            $begingroup$

            [Edit: For most situations, @Kuba's answer is better]



            I can think of one (ugly) way to do it:



            Attributes[myHold] = {HoldAll};

            expr /.
            f[args__] :> With[
            {res = myHold[args] /. Print -> Echo},
            f @@ res /; True
            ] /.
            HoldPattern[f_ @@ myHold[args__]] :> f[args]
            (* Hold[{f[{1, {Echo[1]}}], g[{{{Print[1]}}}]}] *)


            The idea is to wrap the contents of f inside a function with HoldAll attribute (not Hold, to be able to identify it uniquely later on). In a first step, the expression is returned with myHold[…] still in place. In a second round of replacements, myHold is stripped out again.






            share|improve this answer











            $endgroup$









            • 2




              $begingroup$
              +1. If we use the vanishing macro defined in (43096), we can write vanishing[{h}, expr /. x_f :> RuleCondition[h[x] /. Print -> Echo]].
              $endgroup$
              – WReach
              Jan 5 at 18:16



















            7












            $begingroup$

            Alternatively:



            expr /. 
            foo_f :> RuleCondition[Hold[foo] /. Print -> Echo] /.
            Hold[foo_f] :> foo


            We can safely perform the second replacement because we just wrapped every f[..] with Hold.






            share|improve this answer











            $endgroup$













            • $begingroup$
              +1 - In general, this is definitely better than my solution - the only potential issue is the fact that the pattern _f has to be written twice - so for complex patterns, this might lead to some code-duplication/performance cost
              $endgroup$
              – Lukas Lang
              Jan 7 at 9:18










            • $begingroup$
              @LukasLang yes, consider this a quick solution to a specific problem. In general something like b3m2a1 shows is needed or a dummy vanishing head.
              $endgroup$
              – Kuba
              Jan 7 at 9:21











            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',
            autoActivateHeartbeat: false,
            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%2f188887%2fperform-localized-evaluation-leak-free-replacements%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            11












            $begingroup$

            Here's a way making use of Block to cause f to be inert:



            Block[{f},
            SetAttributes[f, HoldAllComplete];
            expr /. f[args__] :>
            RuleCondition[f[args] /. Print -> Echo]
            ]

            Hold[{f[{1, {Echo[1]}}], g[{{{Print[1]}}}]}]


            Note of course that this only works if you have a pattern of the form _Symbol[...]






            share|improve this answer









            $endgroup$


















              11












              $begingroup$

              Here's a way making use of Block to cause f to be inert:



              Block[{f},
              SetAttributes[f, HoldAllComplete];
              expr /. f[args__] :>
              RuleCondition[f[args] /. Print -> Echo]
              ]

              Hold[{f[{1, {Echo[1]}}], g[{{{Print[1]}}}]}]


              Note of course that this only works if you have a pattern of the form _Symbol[...]






              share|improve this answer









              $endgroup$
















                11












                11








                11





                $begingroup$

                Here's a way making use of Block to cause f to be inert:



                Block[{f},
                SetAttributes[f, HoldAllComplete];
                expr /. f[args__] :>
                RuleCondition[f[args] /. Print -> Echo]
                ]

                Hold[{f[{1, {Echo[1]}}], g[{{{Print[1]}}}]}]


                Note of course that this only works if you have a pattern of the form _Symbol[...]






                share|improve this answer









                $endgroup$



                Here's a way making use of Block to cause f to be inert:



                Block[{f},
                SetAttributes[f, HoldAllComplete];
                expr /. f[args__] :>
                RuleCondition[f[args] /. Print -> Echo]
                ]

                Hold[{f[{1, {Echo[1]}}], g[{{{Print[1]}}}]}]


                Note of course that this only works if you have a pattern of the form _Symbol[...]







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 5 at 18:38









                b3m2a1b3m2a1

                27.1k257156




                27.1k257156























                    8












                    $begingroup$

                    [Edit: For most situations, @Kuba's answer is better]



                    I can think of one (ugly) way to do it:



                    Attributes[myHold] = {HoldAll};

                    expr /.
                    f[args__] :> With[
                    {res = myHold[args] /. Print -> Echo},
                    f @@ res /; True
                    ] /.
                    HoldPattern[f_ @@ myHold[args__]] :> f[args]
                    (* Hold[{f[{1, {Echo[1]}}], g[{{{Print[1]}}}]}] *)


                    The idea is to wrap the contents of f inside a function with HoldAll attribute (not Hold, to be able to identify it uniquely later on). In a first step, the expression is returned with myHold[…] still in place. In a second round of replacements, myHold is stripped out again.






                    share|improve this answer











                    $endgroup$









                    • 2




                      $begingroup$
                      +1. If we use the vanishing macro defined in (43096), we can write vanishing[{h}, expr /. x_f :> RuleCondition[h[x] /. Print -> Echo]].
                      $endgroup$
                      – WReach
                      Jan 5 at 18:16
















                    8












                    $begingroup$

                    [Edit: For most situations, @Kuba's answer is better]



                    I can think of one (ugly) way to do it:



                    Attributes[myHold] = {HoldAll};

                    expr /.
                    f[args__] :> With[
                    {res = myHold[args] /. Print -> Echo},
                    f @@ res /; True
                    ] /.
                    HoldPattern[f_ @@ myHold[args__]] :> f[args]
                    (* Hold[{f[{1, {Echo[1]}}], g[{{{Print[1]}}}]}] *)


                    The idea is to wrap the contents of f inside a function with HoldAll attribute (not Hold, to be able to identify it uniquely later on). In a first step, the expression is returned with myHold[…] still in place. In a second round of replacements, myHold is stripped out again.






                    share|improve this answer











                    $endgroup$









                    • 2




                      $begingroup$
                      +1. If we use the vanishing macro defined in (43096), we can write vanishing[{h}, expr /. x_f :> RuleCondition[h[x] /. Print -> Echo]].
                      $endgroup$
                      – WReach
                      Jan 5 at 18:16














                    8












                    8








                    8





                    $begingroup$

                    [Edit: For most situations, @Kuba's answer is better]



                    I can think of one (ugly) way to do it:



                    Attributes[myHold] = {HoldAll};

                    expr /.
                    f[args__] :> With[
                    {res = myHold[args] /. Print -> Echo},
                    f @@ res /; True
                    ] /.
                    HoldPattern[f_ @@ myHold[args__]] :> f[args]
                    (* Hold[{f[{1, {Echo[1]}}], g[{{{Print[1]}}}]}] *)


                    The idea is to wrap the contents of f inside a function with HoldAll attribute (not Hold, to be able to identify it uniquely later on). In a first step, the expression is returned with myHold[…] still in place. In a second round of replacements, myHold is stripped out again.






                    share|improve this answer











                    $endgroup$



                    [Edit: For most situations, @Kuba's answer is better]



                    I can think of one (ugly) way to do it:



                    Attributes[myHold] = {HoldAll};

                    expr /.
                    f[args__] :> With[
                    {res = myHold[args] /. Print -> Echo},
                    f @@ res /; True
                    ] /.
                    HoldPattern[f_ @@ myHold[args__]] :> f[args]
                    (* Hold[{f[{1, {Echo[1]}}], g[{{{Print[1]}}}]}] *)


                    The idea is to wrap the contents of f inside a function with HoldAll attribute (not Hold, to be able to identify it uniquely later on). In a first step, the expression is returned with myHold[…] still in place. In a second round of replacements, myHold is stripped out again.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Jan 7 at 9:20

























                    answered Jan 5 at 16:56









                    Lukas LangLukas Lang

                    6,6651930




                    6,6651930








                    • 2




                      $begingroup$
                      +1. If we use the vanishing macro defined in (43096), we can write vanishing[{h}, expr /. x_f :> RuleCondition[h[x] /. Print -> Echo]].
                      $endgroup$
                      – WReach
                      Jan 5 at 18:16














                    • 2




                      $begingroup$
                      +1. If we use the vanishing macro defined in (43096), we can write vanishing[{h}, expr /. x_f :> RuleCondition[h[x] /. Print -> Echo]].
                      $endgroup$
                      – WReach
                      Jan 5 at 18:16








                    2




                    2




                    $begingroup$
                    +1. If we use the vanishing macro defined in (43096), we can write vanishing[{h}, expr /. x_f :> RuleCondition[h[x] /. Print -> Echo]].
                    $endgroup$
                    – WReach
                    Jan 5 at 18:16




                    $begingroup$
                    +1. If we use the vanishing macro defined in (43096), we can write vanishing[{h}, expr /. x_f :> RuleCondition[h[x] /. Print -> Echo]].
                    $endgroup$
                    – WReach
                    Jan 5 at 18:16











                    7












                    $begingroup$

                    Alternatively:



                    expr /. 
                    foo_f :> RuleCondition[Hold[foo] /. Print -> Echo] /.
                    Hold[foo_f] :> foo


                    We can safely perform the second replacement because we just wrapped every f[..] with Hold.






                    share|improve this answer











                    $endgroup$













                    • $begingroup$
                      +1 - In general, this is definitely better than my solution - the only potential issue is the fact that the pattern _f has to be written twice - so for complex patterns, this might lead to some code-duplication/performance cost
                      $endgroup$
                      – Lukas Lang
                      Jan 7 at 9:18










                    • $begingroup$
                      @LukasLang yes, consider this a quick solution to a specific problem. In general something like b3m2a1 shows is needed or a dummy vanishing head.
                      $endgroup$
                      – Kuba
                      Jan 7 at 9:21
















                    7












                    $begingroup$

                    Alternatively:



                    expr /. 
                    foo_f :> RuleCondition[Hold[foo] /. Print -> Echo] /.
                    Hold[foo_f] :> foo


                    We can safely perform the second replacement because we just wrapped every f[..] with Hold.






                    share|improve this answer











                    $endgroup$













                    • $begingroup$
                      +1 - In general, this is definitely better than my solution - the only potential issue is the fact that the pattern _f has to be written twice - so for complex patterns, this might lead to some code-duplication/performance cost
                      $endgroup$
                      – Lukas Lang
                      Jan 7 at 9:18










                    • $begingroup$
                      @LukasLang yes, consider this a quick solution to a specific problem. In general something like b3m2a1 shows is needed or a dummy vanishing head.
                      $endgroup$
                      – Kuba
                      Jan 7 at 9:21














                    7












                    7








                    7





                    $begingroup$

                    Alternatively:



                    expr /. 
                    foo_f :> RuleCondition[Hold[foo] /. Print -> Echo] /.
                    Hold[foo_f] :> foo


                    We can safely perform the second replacement because we just wrapped every f[..] with Hold.






                    share|improve this answer











                    $endgroup$



                    Alternatively:



                    expr /. 
                    foo_f :> RuleCondition[Hold[foo] /. Print -> Echo] /.
                    Hold[foo_f] :> foo


                    We can safely perform the second replacement because we just wrapped every f[..] with Hold.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Jan 7 at 8:59

























                    answered Jan 6 at 20:04









                    KubaKuba

                    104k12203522




                    104k12203522












                    • $begingroup$
                      +1 - In general, this is definitely better than my solution - the only potential issue is the fact that the pattern _f has to be written twice - so for complex patterns, this might lead to some code-duplication/performance cost
                      $endgroup$
                      – Lukas Lang
                      Jan 7 at 9:18










                    • $begingroup$
                      @LukasLang yes, consider this a quick solution to a specific problem. In general something like b3m2a1 shows is needed or a dummy vanishing head.
                      $endgroup$
                      – Kuba
                      Jan 7 at 9:21


















                    • $begingroup$
                      +1 - In general, this is definitely better than my solution - the only potential issue is the fact that the pattern _f has to be written twice - so for complex patterns, this might lead to some code-duplication/performance cost
                      $endgroup$
                      – Lukas Lang
                      Jan 7 at 9:18










                    • $begingroup$
                      @LukasLang yes, consider this a quick solution to a specific problem. In general something like b3m2a1 shows is needed or a dummy vanishing head.
                      $endgroup$
                      – Kuba
                      Jan 7 at 9:21
















                    $begingroup$
                    +1 - In general, this is definitely better than my solution - the only potential issue is the fact that the pattern _f has to be written twice - so for complex patterns, this might lead to some code-duplication/performance cost
                    $endgroup$
                    – Lukas Lang
                    Jan 7 at 9:18




                    $begingroup$
                    +1 - In general, this is definitely better than my solution - the only potential issue is the fact that the pattern _f has to be written twice - so for complex patterns, this might lead to some code-duplication/performance cost
                    $endgroup$
                    – Lukas Lang
                    Jan 7 at 9:18












                    $begingroup$
                    @LukasLang yes, consider this a quick solution to a specific problem. In general something like b3m2a1 shows is needed or a dummy vanishing head.
                    $endgroup$
                    – Kuba
                    Jan 7 at 9:21




                    $begingroup$
                    @LukasLang yes, consider this a quick solution to a specific problem. In general something like b3m2a1 shows is needed or a dummy vanishing head.
                    $endgroup$
                    – Kuba
                    Jan 7 at 9:21


















                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Mathematica Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    Use MathJax to format equations. MathJax reference.


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




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f188887%2fperform-localized-evaluation-leak-free-replacements%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

                    How do I know what Microsoft account the skydrive app is syncing to?

                    When does type information flow backwards in C++?

                    Grease: Live!