Cleanest way to take a[b[c]] to a[b][c]












18












$begingroup$


As indicated in the title I'm looking for the fastest way to transform a[b[c]] into a[b][c], and the natural generalization to an arbitrary chaining of arguments. I'm sure there's got to be a convenient way that I've overlooked.



In my cases a, b, and c can be any expression with any complicated internal structure they like.



As an example, we could have some terrible deeply nested thing like:



bleh =
Nest[f, 10, 10]@
Nest[b, 100, 100]@Nest[c, RandomReal[{}, {1000, 1000}], 1000];


And then we can to convert this into:



blehm =
Nest[f, 10, 10][
Nest[b, 100, 100]][Nest[c, RandomReal[{}, {1000, 1000}], 1000]]









share|improve this question











$endgroup$








  • 1




    $begingroup$
    The solution likely would use Operate.
    $endgroup$
    – QuantumDot
    Jan 23 at 6:20










  • $begingroup$
    f = Curry[Replace][a_[b_[c_]] :> a[b][c]] also works, so that a[b[c]] // f gives the desired result.
    $endgroup$
    – Shredderroy
    Jan 23 at 6:29










  • $begingroup$
    How about generalizing the question to taking a[b[c[d[...]]]] to a[b][c][d]...?
    $endgroup$
    – David G. Stork
    Jan 23 at 6:40








  • 1




    $begingroup$
    @b3m2a1: Oh.... well I recommend you alter the question... and seem my new solution.
    $endgroup$
    – David G. Stork
    Jan 23 at 6:49






  • 1




    $begingroup$
    If you want a b c to be any expression you better show some examples, what is a[b[c], d[e, f]] supposed to be converted to?
    $endgroup$
    – Kuba
    Jan 23 at 9:14


















18












$begingroup$


As indicated in the title I'm looking for the fastest way to transform a[b[c]] into a[b][c], and the natural generalization to an arbitrary chaining of arguments. I'm sure there's got to be a convenient way that I've overlooked.



In my cases a, b, and c can be any expression with any complicated internal structure they like.



As an example, we could have some terrible deeply nested thing like:



bleh =
Nest[f, 10, 10]@
Nest[b, 100, 100]@Nest[c, RandomReal[{}, {1000, 1000}], 1000];


And then we can to convert this into:



blehm =
Nest[f, 10, 10][
Nest[b, 100, 100]][Nest[c, RandomReal[{}, {1000, 1000}], 1000]]









share|improve this question











$endgroup$








  • 1




    $begingroup$
    The solution likely would use Operate.
    $endgroup$
    – QuantumDot
    Jan 23 at 6:20










  • $begingroup$
    f = Curry[Replace][a_[b_[c_]] :> a[b][c]] also works, so that a[b[c]] // f gives the desired result.
    $endgroup$
    – Shredderroy
    Jan 23 at 6:29










  • $begingroup$
    How about generalizing the question to taking a[b[c[d[...]]]] to a[b][c][d]...?
    $endgroup$
    – David G. Stork
    Jan 23 at 6:40








  • 1




    $begingroup$
    @b3m2a1: Oh.... well I recommend you alter the question... and seem my new solution.
    $endgroup$
    – David G. Stork
    Jan 23 at 6:49






  • 1




    $begingroup$
    If you want a b c to be any expression you better show some examples, what is a[b[c], d[e, f]] supposed to be converted to?
    $endgroup$
    – Kuba
    Jan 23 at 9:14
















18












18








18


4



$begingroup$


As indicated in the title I'm looking for the fastest way to transform a[b[c]] into a[b][c], and the natural generalization to an arbitrary chaining of arguments. I'm sure there's got to be a convenient way that I've overlooked.



In my cases a, b, and c can be any expression with any complicated internal structure they like.



As an example, we could have some terrible deeply nested thing like:



bleh =
Nest[f, 10, 10]@
Nest[b, 100, 100]@Nest[c, RandomReal[{}, {1000, 1000}], 1000];


And then we can to convert this into:



blehm =
Nest[f, 10, 10][
Nest[b, 100, 100]][Nest[c, RandomReal[{}, {1000, 1000}], 1000]]









share|improve this question











$endgroup$




As indicated in the title I'm looking for the fastest way to transform a[b[c]] into a[b][c], and the natural generalization to an arbitrary chaining of arguments. I'm sure there's got to be a convenient way that I've overlooked.



In my cases a, b, and c can be any expression with any complicated internal structure they like.



As an example, we could have some terrible deeply nested thing like:



bleh =
Nest[f, 10, 10]@
Nest[b, 100, 100]@Nest[c, RandomReal[{}, {1000, 1000}], 1000];


And then we can to convert this into:



blehm =
Nest[f, 10, 10][
Nest[b, 100, 100]][Nest[c, RandomReal[{}, {1000, 1000}], 1000]]






function-construction expression-manipulation functional-style






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 23 at 12:52









Kuba

106k12204526




106k12204526










asked Jan 23 at 5:58









b3m2a1b3m2a1

28k357161




28k357161








  • 1




    $begingroup$
    The solution likely would use Operate.
    $endgroup$
    – QuantumDot
    Jan 23 at 6:20










  • $begingroup$
    f = Curry[Replace][a_[b_[c_]] :> a[b][c]] also works, so that a[b[c]] // f gives the desired result.
    $endgroup$
    – Shredderroy
    Jan 23 at 6:29










  • $begingroup$
    How about generalizing the question to taking a[b[c[d[...]]]] to a[b][c][d]...?
    $endgroup$
    – David G. Stork
    Jan 23 at 6:40








  • 1




    $begingroup$
    @b3m2a1: Oh.... well I recommend you alter the question... and seem my new solution.
    $endgroup$
    – David G. Stork
    Jan 23 at 6:49






  • 1




    $begingroup$
    If you want a b c to be any expression you better show some examples, what is a[b[c], d[e, f]] supposed to be converted to?
    $endgroup$
    – Kuba
    Jan 23 at 9:14
















  • 1




    $begingroup$
    The solution likely would use Operate.
    $endgroup$
    – QuantumDot
    Jan 23 at 6:20










  • $begingroup$
    f = Curry[Replace][a_[b_[c_]] :> a[b][c]] also works, so that a[b[c]] // f gives the desired result.
    $endgroup$
    – Shredderroy
    Jan 23 at 6:29










  • $begingroup$
    How about generalizing the question to taking a[b[c[d[...]]]] to a[b][c][d]...?
    $endgroup$
    – David G. Stork
    Jan 23 at 6:40








  • 1




    $begingroup$
    @b3m2a1: Oh.... well I recommend you alter the question... and seem my new solution.
    $endgroup$
    – David G. Stork
    Jan 23 at 6:49






  • 1




    $begingroup$
    If you want a b c to be any expression you better show some examples, what is a[b[c], d[e, f]] supposed to be converted to?
    $endgroup$
    – Kuba
    Jan 23 at 9:14










1




1




$begingroup$
The solution likely would use Operate.
$endgroup$
– QuantumDot
Jan 23 at 6:20




$begingroup$
The solution likely would use Operate.
$endgroup$
– QuantumDot
Jan 23 at 6:20












$begingroup$
f = Curry[Replace][a_[b_[c_]] :> a[b][c]] also works, so that a[b[c]] // f gives the desired result.
$endgroup$
– Shredderroy
Jan 23 at 6:29




$begingroup$
f = Curry[Replace][a_[b_[c_]] :> a[b][c]] also works, so that a[b[c]] // f gives the desired result.
$endgroup$
– Shredderroy
Jan 23 at 6:29












$begingroup$
How about generalizing the question to taking a[b[c[d[...]]]] to a[b][c][d]...?
$endgroup$
– David G. Stork
Jan 23 at 6:40






$begingroup$
How about generalizing the question to taking a[b[c[d[...]]]] to a[b][c][d]...?
$endgroup$
– David G. Stork
Jan 23 at 6:40






1




1




$begingroup$
@b3m2a1: Oh.... well I recommend you alter the question... and seem my new solution.
$endgroup$
– David G. Stork
Jan 23 at 6:49




$begingroup$
@b3m2a1: Oh.... well I recommend you alter the question... and seem my new solution.
$endgroup$
– David G. Stork
Jan 23 at 6:49




1




1




$begingroup$
If you want a b c to be any expression you better show some examples, what is a[b[c], d[e, f]] supposed to be converted to?
$endgroup$
– Kuba
Jan 23 at 9:14






$begingroup$
If you want a b c to be any expression you better show some examples, what is a[b[c], d[e, f]] supposed to be converted to?
$endgroup$
– Kuba
Jan 23 at 9:14












4 Answers
4






active

oldest

votes


















10












$begingroup$

Operate[#[[0]], First@#] &[a[b[c]]]



a[b][c]




ClearAll[deCompose]
deCompose = Nest[Operate[#[[0]], First@#] &, #, Depth[#] - 2] &;

deCompose@a[b[c]]



a[b][c]




exp = Compose[a, b, c, d, e, f, g]



a[b[c[d[e[f[g]]]]]]




deCompose @ exp



a[b][c][d][e][f][g]







share|improve this answer











$endgroup$





















    23












    $begingroup$

    test = a[b[c[d]]];

    Fold[
    Construct, (* or Compose, see [1] *)
    Level[test, {-1}, Heads -> True]
    ]



    a[b][c][d]



    [1] - Is there a name for #1@#2&?



    Alternatively, thanks to OP and Mr.Wizard:



    HeadCompose @@ Level[test, {-1}, Heads -> True]





    share|improve this answer











    $endgroup$









    • 1




      $begingroup$
      No Operate, No # and no _, a clear winner here :P
      $endgroup$
      – Kuba
      Jan 23 at 9:20












    • $begingroup$
      Oh A+ that's slick
      $endgroup$
      – b3m2a1
      Jan 23 at 9:20






    • 3




      $begingroup$
      One issue is that this will die on nested stuff like my example case, but I still like how clean this is. You could even get away with HeadCompose @@ Level[test, {-1}, Heads -> True]
      $endgroup$
      – b3m2a1
      Jan 23 at 9:22






    • 1




      $begingroup$
      @evanb Compose will do as well.
      $endgroup$
      – Kuba
      Jan 23 at 9:37






    • 3




      $begingroup$
      +1, ++clever. yet another variant: Level[test, {-1}, HeadCompose, Heads -> True]
      $endgroup$
      – WReach
      Jan 23 at 22:49



















    10












    $begingroup$

    This works on any level:



    a[b[c]] //. x_[s : _[_]] :> Operate[x, s]
    (* a[b][c] *)

    a[b[c[d[e[f[g[h]]]]]]] //. x_[s : _[_]] :> Operate[x, s]
    (* a[b][c][d][e][f][g][h] *)


    simpler syntax but same thing:



    a[b[c[d[e[f[g[h]]]]]]] //. x_[y_[z_]] -> x[y][z]
    (* a[b][c][d][e][f][g][h] *)


    Of course, if the components a, b, c etc. have such complicated internal structure that they match the pattern x_[s:_[_]] (equivalent to x_[y_[z_]]), then this proposed solution will fail by over-matching. This could be remedied by constraining the pattern and fixing which elements must be atomic with _?AtomQ. It all depends on the use case.



    This way of pattern matching can also be expanded to specific other situations like a[b[c],d[e]] etc., depending on what result is desired.






    share|improve this answer











    $endgroup$













    • $begingroup$
      For your terribly nested example, what characterizes the composition is that none of the components are atomic. With NotAtomQ[x_] := !AtomQ[x] we have blehm == bleh //. x_?NotAtomQ[s : _?NotAtomQ[_?NotAtomQ]] :> Operate[x, s]. This breaks the a[b[c]] example though. I find that pattern matching gives more fine-grained control than Level in this situation.
      $endgroup$
      – Roman
      Jan 23 at 10:19










    • $begingroup$
      Or perhaps a[b[c[d[e[f]]]]] //. a_[b_[c_]] :> a[b][c].
      $endgroup$
      – march
      Jan 23 at 16:51










    • $begingroup$
      @march that's exactly the same as I wrote, just using a slightly different syntax. Yes maybe your version is clearer, sorry for being so cryptic.
      $endgroup$
      – Roman
      Jan 23 at 17:47



















    5












    $begingroup$

    Not particularly "clean," but it works:



    Operate[Head[#], Level[#, 2][[2]]] & @ a[b[c]]


    For the full generalization:



    Nest[Operate[Head[#], Level[#, 2][[2]]] & , #, Depth[#] -2] & @
    a[b[c[d[e]]]]





    share|improve this answer











    $endgroup$













      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%2f190047%2fcleanest-way-to-take-abc-to-abc%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      10












      $begingroup$

      Operate[#[[0]], First@#] &[a[b[c]]]



      a[b][c]




      ClearAll[deCompose]
      deCompose = Nest[Operate[#[[0]], First@#] &, #, Depth[#] - 2] &;

      deCompose@a[b[c]]



      a[b][c]




      exp = Compose[a, b, c, d, e, f, g]



      a[b[c[d[e[f[g]]]]]]




      deCompose @ exp



      a[b][c][d][e][f][g]







      share|improve this answer











      $endgroup$


















        10












        $begingroup$

        Operate[#[[0]], First@#] &[a[b[c]]]



        a[b][c]




        ClearAll[deCompose]
        deCompose = Nest[Operate[#[[0]], First@#] &, #, Depth[#] - 2] &;

        deCompose@a[b[c]]



        a[b][c]




        exp = Compose[a, b, c, d, e, f, g]



        a[b[c[d[e[f[g]]]]]]




        deCompose @ exp



        a[b][c][d][e][f][g]







        share|improve this answer











        $endgroup$
















          10












          10








          10





          $begingroup$

          Operate[#[[0]], First@#] &[a[b[c]]]



          a[b][c]




          ClearAll[deCompose]
          deCompose = Nest[Operate[#[[0]], First@#] &, #, Depth[#] - 2] &;

          deCompose@a[b[c]]



          a[b][c]




          exp = Compose[a, b, c, d, e, f, g]



          a[b[c[d[e[f[g]]]]]]




          deCompose @ exp



          a[b][c][d][e][f][g]







          share|improve this answer











          $endgroup$



          Operate[#[[0]], First@#] &[a[b[c]]]



          a[b][c]




          ClearAll[deCompose]
          deCompose = Nest[Operate[#[[0]], First@#] &, #, Depth[#] - 2] &;

          deCompose@a[b[c]]



          a[b][c]




          exp = Compose[a, b, c, d, e, f, g]



          a[b[c[d[e[f[g]]]]]]




          deCompose @ exp



          a[b][c][d][e][f][g]








          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jan 23 at 6:52

























          answered Jan 23 at 6:45









          kglrkglr

          185k10202421




          185k10202421























              23












              $begingroup$

              test = a[b[c[d]]];

              Fold[
              Construct, (* or Compose, see [1] *)
              Level[test, {-1}, Heads -> True]
              ]



              a[b][c][d]



              [1] - Is there a name for #1@#2&?



              Alternatively, thanks to OP and Mr.Wizard:



              HeadCompose @@ Level[test, {-1}, Heads -> True]





              share|improve this answer











              $endgroup$









              • 1




                $begingroup$
                No Operate, No # and no _, a clear winner here :P
                $endgroup$
                – Kuba
                Jan 23 at 9:20












              • $begingroup$
                Oh A+ that's slick
                $endgroup$
                – b3m2a1
                Jan 23 at 9:20






              • 3




                $begingroup$
                One issue is that this will die on nested stuff like my example case, but I still like how clean this is. You could even get away with HeadCompose @@ Level[test, {-1}, Heads -> True]
                $endgroup$
                – b3m2a1
                Jan 23 at 9:22






              • 1




                $begingroup$
                @evanb Compose will do as well.
                $endgroup$
                – Kuba
                Jan 23 at 9:37






              • 3




                $begingroup$
                +1, ++clever. yet another variant: Level[test, {-1}, HeadCompose, Heads -> True]
                $endgroup$
                – WReach
                Jan 23 at 22:49
















              23












              $begingroup$

              test = a[b[c[d]]];

              Fold[
              Construct, (* or Compose, see [1] *)
              Level[test, {-1}, Heads -> True]
              ]



              a[b][c][d]



              [1] - Is there a name for #1@#2&?



              Alternatively, thanks to OP and Mr.Wizard:



              HeadCompose @@ Level[test, {-1}, Heads -> True]





              share|improve this answer











              $endgroup$









              • 1




                $begingroup$
                No Operate, No # and no _, a clear winner here :P
                $endgroup$
                – Kuba
                Jan 23 at 9:20












              • $begingroup$
                Oh A+ that's slick
                $endgroup$
                – b3m2a1
                Jan 23 at 9:20






              • 3




                $begingroup$
                One issue is that this will die on nested stuff like my example case, but I still like how clean this is. You could even get away with HeadCompose @@ Level[test, {-1}, Heads -> True]
                $endgroup$
                – b3m2a1
                Jan 23 at 9:22






              • 1




                $begingroup$
                @evanb Compose will do as well.
                $endgroup$
                – Kuba
                Jan 23 at 9:37






              • 3




                $begingroup$
                +1, ++clever. yet another variant: Level[test, {-1}, HeadCompose, Heads -> True]
                $endgroup$
                – WReach
                Jan 23 at 22:49














              23












              23








              23





              $begingroup$

              test = a[b[c[d]]];

              Fold[
              Construct, (* or Compose, see [1] *)
              Level[test, {-1}, Heads -> True]
              ]



              a[b][c][d]



              [1] - Is there a name for #1@#2&?



              Alternatively, thanks to OP and Mr.Wizard:



              HeadCompose @@ Level[test, {-1}, Heads -> True]





              share|improve this answer











              $endgroup$



              test = a[b[c[d]]];

              Fold[
              Construct, (* or Compose, see [1] *)
              Level[test, {-1}, Heads -> True]
              ]



              a[b][c][d]



              [1] - Is there a name for #1@#2&?



              Alternatively, thanks to OP and Mr.Wizard:



              HeadCompose @@ Level[test, {-1}, Heads -> True]






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Jan 23 at 21:59

























              answered Jan 23 at 9:18









              KubaKuba

              106k12204526




              106k12204526








              • 1




                $begingroup$
                No Operate, No # and no _, a clear winner here :P
                $endgroup$
                – Kuba
                Jan 23 at 9:20












              • $begingroup$
                Oh A+ that's slick
                $endgroup$
                – b3m2a1
                Jan 23 at 9:20






              • 3




                $begingroup$
                One issue is that this will die on nested stuff like my example case, but I still like how clean this is. You could even get away with HeadCompose @@ Level[test, {-1}, Heads -> True]
                $endgroup$
                – b3m2a1
                Jan 23 at 9:22






              • 1




                $begingroup$
                @evanb Compose will do as well.
                $endgroup$
                – Kuba
                Jan 23 at 9:37






              • 3




                $begingroup$
                +1, ++clever. yet another variant: Level[test, {-1}, HeadCompose, Heads -> True]
                $endgroup$
                – WReach
                Jan 23 at 22:49














              • 1




                $begingroup$
                No Operate, No # and no _, a clear winner here :P
                $endgroup$
                – Kuba
                Jan 23 at 9:20












              • $begingroup$
                Oh A+ that's slick
                $endgroup$
                – b3m2a1
                Jan 23 at 9:20






              • 3




                $begingroup$
                One issue is that this will die on nested stuff like my example case, but I still like how clean this is. You could even get away with HeadCompose @@ Level[test, {-1}, Heads -> True]
                $endgroup$
                – b3m2a1
                Jan 23 at 9:22






              • 1




                $begingroup$
                @evanb Compose will do as well.
                $endgroup$
                – Kuba
                Jan 23 at 9:37






              • 3




                $begingroup$
                +1, ++clever. yet another variant: Level[test, {-1}, HeadCompose, Heads -> True]
                $endgroup$
                – WReach
                Jan 23 at 22:49








              1




              1




              $begingroup$
              No Operate, No # and no _, a clear winner here :P
              $endgroup$
              – Kuba
              Jan 23 at 9:20






              $begingroup$
              No Operate, No # and no _, a clear winner here :P
              $endgroup$
              – Kuba
              Jan 23 at 9:20














              $begingroup$
              Oh A+ that's slick
              $endgroup$
              – b3m2a1
              Jan 23 at 9:20




              $begingroup$
              Oh A+ that's slick
              $endgroup$
              – b3m2a1
              Jan 23 at 9:20




              3




              3




              $begingroup$
              One issue is that this will die on nested stuff like my example case, but I still like how clean this is. You could even get away with HeadCompose @@ Level[test, {-1}, Heads -> True]
              $endgroup$
              – b3m2a1
              Jan 23 at 9:22




              $begingroup$
              One issue is that this will die on nested stuff like my example case, but I still like how clean this is. You could even get away with HeadCompose @@ Level[test, {-1}, Heads -> True]
              $endgroup$
              – b3m2a1
              Jan 23 at 9:22




              1




              1




              $begingroup$
              @evanb Compose will do as well.
              $endgroup$
              – Kuba
              Jan 23 at 9:37




              $begingroup$
              @evanb Compose will do as well.
              $endgroup$
              – Kuba
              Jan 23 at 9:37




              3




              3




              $begingroup$
              +1, ++clever. yet another variant: Level[test, {-1}, HeadCompose, Heads -> True]
              $endgroup$
              – WReach
              Jan 23 at 22:49




              $begingroup$
              +1, ++clever. yet another variant: Level[test, {-1}, HeadCompose, Heads -> True]
              $endgroup$
              – WReach
              Jan 23 at 22:49











              10












              $begingroup$

              This works on any level:



              a[b[c]] //. x_[s : _[_]] :> Operate[x, s]
              (* a[b][c] *)

              a[b[c[d[e[f[g[h]]]]]]] //. x_[s : _[_]] :> Operate[x, s]
              (* a[b][c][d][e][f][g][h] *)


              simpler syntax but same thing:



              a[b[c[d[e[f[g[h]]]]]]] //. x_[y_[z_]] -> x[y][z]
              (* a[b][c][d][e][f][g][h] *)


              Of course, if the components a, b, c etc. have such complicated internal structure that they match the pattern x_[s:_[_]] (equivalent to x_[y_[z_]]), then this proposed solution will fail by over-matching. This could be remedied by constraining the pattern and fixing which elements must be atomic with _?AtomQ. It all depends on the use case.



              This way of pattern matching can also be expanded to specific other situations like a[b[c],d[e]] etc., depending on what result is desired.






              share|improve this answer











              $endgroup$













              • $begingroup$
                For your terribly nested example, what characterizes the composition is that none of the components are atomic. With NotAtomQ[x_] := !AtomQ[x] we have blehm == bleh //. x_?NotAtomQ[s : _?NotAtomQ[_?NotAtomQ]] :> Operate[x, s]. This breaks the a[b[c]] example though. I find that pattern matching gives more fine-grained control than Level in this situation.
                $endgroup$
                – Roman
                Jan 23 at 10:19










              • $begingroup$
                Or perhaps a[b[c[d[e[f]]]]] //. a_[b_[c_]] :> a[b][c].
                $endgroup$
                – march
                Jan 23 at 16:51










              • $begingroup$
                @march that's exactly the same as I wrote, just using a slightly different syntax. Yes maybe your version is clearer, sorry for being so cryptic.
                $endgroup$
                – Roman
                Jan 23 at 17:47
















              10












              $begingroup$

              This works on any level:



              a[b[c]] //. x_[s : _[_]] :> Operate[x, s]
              (* a[b][c] *)

              a[b[c[d[e[f[g[h]]]]]]] //. x_[s : _[_]] :> Operate[x, s]
              (* a[b][c][d][e][f][g][h] *)


              simpler syntax but same thing:



              a[b[c[d[e[f[g[h]]]]]]] //. x_[y_[z_]] -> x[y][z]
              (* a[b][c][d][e][f][g][h] *)


              Of course, if the components a, b, c etc. have such complicated internal structure that they match the pattern x_[s:_[_]] (equivalent to x_[y_[z_]]), then this proposed solution will fail by over-matching. This could be remedied by constraining the pattern and fixing which elements must be atomic with _?AtomQ. It all depends on the use case.



              This way of pattern matching can also be expanded to specific other situations like a[b[c],d[e]] etc., depending on what result is desired.






              share|improve this answer











              $endgroup$













              • $begingroup$
                For your terribly nested example, what characterizes the composition is that none of the components are atomic. With NotAtomQ[x_] := !AtomQ[x] we have blehm == bleh //. x_?NotAtomQ[s : _?NotAtomQ[_?NotAtomQ]] :> Operate[x, s]. This breaks the a[b[c]] example though. I find that pattern matching gives more fine-grained control than Level in this situation.
                $endgroup$
                – Roman
                Jan 23 at 10:19










              • $begingroup$
                Or perhaps a[b[c[d[e[f]]]]] //. a_[b_[c_]] :> a[b][c].
                $endgroup$
                – march
                Jan 23 at 16:51










              • $begingroup$
                @march that's exactly the same as I wrote, just using a slightly different syntax. Yes maybe your version is clearer, sorry for being so cryptic.
                $endgroup$
                – Roman
                Jan 23 at 17:47














              10












              10








              10





              $begingroup$

              This works on any level:



              a[b[c]] //. x_[s : _[_]] :> Operate[x, s]
              (* a[b][c] *)

              a[b[c[d[e[f[g[h]]]]]]] //. x_[s : _[_]] :> Operate[x, s]
              (* a[b][c][d][e][f][g][h] *)


              simpler syntax but same thing:



              a[b[c[d[e[f[g[h]]]]]]] //. x_[y_[z_]] -> x[y][z]
              (* a[b][c][d][e][f][g][h] *)


              Of course, if the components a, b, c etc. have such complicated internal structure that they match the pattern x_[s:_[_]] (equivalent to x_[y_[z_]]), then this proposed solution will fail by over-matching. This could be remedied by constraining the pattern and fixing which elements must be atomic with _?AtomQ. It all depends on the use case.



              This way of pattern matching can also be expanded to specific other situations like a[b[c],d[e]] etc., depending on what result is desired.






              share|improve this answer











              $endgroup$



              This works on any level:



              a[b[c]] //. x_[s : _[_]] :> Operate[x, s]
              (* a[b][c] *)

              a[b[c[d[e[f[g[h]]]]]]] //. x_[s : _[_]] :> Operate[x, s]
              (* a[b][c][d][e][f][g][h] *)


              simpler syntax but same thing:



              a[b[c[d[e[f[g[h]]]]]]] //. x_[y_[z_]] -> x[y][z]
              (* a[b][c][d][e][f][g][h] *)


              Of course, if the components a, b, c etc. have such complicated internal structure that they match the pattern x_[s:_[_]] (equivalent to x_[y_[z_]]), then this proposed solution will fail by over-matching. This could be remedied by constraining the pattern and fixing which elements must be atomic with _?AtomQ. It all depends on the use case.



              This way of pattern matching can also be expanded to specific other situations like a[b[c],d[e]] etc., depending on what result is desired.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Jan 29 at 23:14

























              answered Jan 23 at 9:12









              RomanRoman

              1,756614




              1,756614












              • $begingroup$
                For your terribly nested example, what characterizes the composition is that none of the components are atomic. With NotAtomQ[x_] := !AtomQ[x] we have blehm == bleh //. x_?NotAtomQ[s : _?NotAtomQ[_?NotAtomQ]] :> Operate[x, s]. This breaks the a[b[c]] example though. I find that pattern matching gives more fine-grained control than Level in this situation.
                $endgroup$
                – Roman
                Jan 23 at 10:19










              • $begingroup$
                Or perhaps a[b[c[d[e[f]]]]] //. a_[b_[c_]] :> a[b][c].
                $endgroup$
                – march
                Jan 23 at 16:51










              • $begingroup$
                @march that's exactly the same as I wrote, just using a slightly different syntax. Yes maybe your version is clearer, sorry for being so cryptic.
                $endgroup$
                – Roman
                Jan 23 at 17:47


















              • $begingroup$
                For your terribly nested example, what characterizes the composition is that none of the components are atomic. With NotAtomQ[x_] := !AtomQ[x] we have blehm == bleh //. x_?NotAtomQ[s : _?NotAtomQ[_?NotAtomQ]] :> Operate[x, s]. This breaks the a[b[c]] example though. I find that pattern matching gives more fine-grained control than Level in this situation.
                $endgroup$
                – Roman
                Jan 23 at 10:19










              • $begingroup$
                Or perhaps a[b[c[d[e[f]]]]] //. a_[b_[c_]] :> a[b][c].
                $endgroup$
                – march
                Jan 23 at 16:51










              • $begingroup$
                @march that's exactly the same as I wrote, just using a slightly different syntax. Yes maybe your version is clearer, sorry for being so cryptic.
                $endgroup$
                – Roman
                Jan 23 at 17:47
















              $begingroup$
              For your terribly nested example, what characterizes the composition is that none of the components are atomic. With NotAtomQ[x_] := !AtomQ[x] we have blehm == bleh //. x_?NotAtomQ[s : _?NotAtomQ[_?NotAtomQ]] :> Operate[x, s]. This breaks the a[b[c]] example though. I find that pattern matching gives more fine-grained control than Level in this situation.
              $endgroup$
              – Roman
              Jan 23 at 10:19




              $begingroup$
              For your terribly nested example, what characterizes the composition is that none of the components are atomic. With NotAtomQ[x_] := !AtomQ[x] we have blehm == bleh //. x_?NotAtomQ[s : _?NotAtomQ[_?NotAtomQ]] :> Operate[x, s]. This breaks the a[b[c]] example though. I find that pattern matching gives more fine-grained control than Level in this situation.
              $endgroup$
              – Roman
              Jan 23 at 10:19












              $begingroup$
              Or perhaps a[b[c[d[e[f]]]]] //. a_[b_[c_]] :> a[b][c].
              $endgroup$
              – march
              Jan 23 at 16:51




              $begingroup$
              Or perhaps a[b[c[d[e[f]]]]] //. a_[b_[c_]] :> a[b][c].
              $endgroup$
              – march
              Jan 23 at 16:51












              $begingroup$
              @march that's exactly the same as I wrote, just using a slightly different syntax. Yes maybe your version is clearer, sorry for being so cryptic.
              $endgroup$
              – Roman
              Jan 23 at 17:47




              $begingroup$
              @march that's exactly the same as I wrote, just using a slightly different syntax. Yes maybe your version is clearer, sorry for being so cryptic.
              $endgroup$
              – Roman
              Jan 23 at 17:47











              5












              $begingroup$

              Not particularly "clean," but it works:



              Operate[Head[#], Level[#, 2][[2]]] & @ a[b[c]]


              For the full generalization:



              Nest[Operate[Head[#], Level[#, 2][[2]]] & , #, Depth[#] -2] & @
              a[b[c[d[e]]]]





              share|improve this answer











              $endgroup$


















                5












                $begingroup$

                Not particularly "clean," but it works:



                Operate[Head[#], Level[#, 2][[2]]] & @ a[b[c]]


                For the full generalization:



                Nest[Operate[Head[#], Level[#, 2][[2]]] & , #, Depth[#] -2] & @
                a[b[c[d[e]]]]





                share|improve this answer











                $endgroup$
















                  5












                  5








                  5





                  $begingroup$

                  Not particularly "clean," but it works:



                  Operate[Head[#], Level[#, 2][[2]]] & @ a[b[c]]


                  For the full generalization:



                  Nest[Operate[Head[#], Level[#, 2][[2]]] & , #, Depth[#] -2] & @
                  a[b[c[d[e]]]]





                  share|improve this answer











                  $endgroup$



                  Not particularly "clean," but it works:



                  Operate[Head[#], Level[#, 2][[2]]] & @ a[b[c]]


                  For the full generalization:



                  Nest[Operate[Head[#], Level[#, 2][[2]]] & , #, Depth[#] -2] & @
                  a[b[c[d[e]]]]






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Jan 23 at 6:53

























                  answered Jan 23 at 6:28









                  David G. StorkDavid G. Stork

                  24.4k22153




                  24.4k22153






























                      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%2f190047%2fcleanest-way-to-take-abc-to-abc%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

                      Human spaceflight

                      Can not write log (Is /dev/pts mounted?) - openpty in Ubuntu-on-Windows?

                      File:DeusFollowingSea.jpg