8
$\begingroup$

Is there a good universal method that allows the making of a frame around every function. In the output, functions should remain unchanged (no evaluation, or any other changes) and each function should have frame.

For example, to make the frame around Plus[1, Plus[Plus[1, 1], Plus[Plus[1, 1], 1]]] something like MakeNiceFrames[Plus[1, Plus[Plus[1, 1], Plus[Plus[1, 1], 1]]]]. An output should look exactly same as in input Plus[1, Plus[Plus[1, 1], Plus[Plus[1, 1], 1]]] with every function (including head and closing bracket) separately framed.

It will be nice to have that kind of framing for visual separations of functions while debugging. I have experimented with Framed[]. But each function needs the use of separate Framed[] function and functions are actually evaluated, what makes it makes inconvenient to use.

$\endgroup$
4
  • $\begingroup$ Related: 15516. $\endgroup$
    – Kuba
    Commented Sep 17, 2018 at 16:19
  • 2
    $\begingroup$ For formal clarity you should specify if you need framed function together with all its arguments or just the function's name framed (i suspect the former). A side note: triple-click any function name (Head) and it will be selected from Head start to the closing bracket. Perhaps somehow useful for this problem if you don't want to have too many frames, which could be confusing. $\endgroup$ Commented Sep 17, 2018 at 16:42
  • $\begingroup$ @VitaliyKaurov First assumption is right. I edited question and part of it looks as "An output should look exactly same as in input Plus[1, Plus[Plus[1, 1], Plus[Plus[1, 1], 1]]] with every function (including head and closing bracket) separately framed." Do you think anything other should be added? $\endgroup$
    – vasili111
    Commented Sep 17, 2018 at 16:56
  • 4
    $\begingroup$ TreeForm[Hold[ Plus[1, Plus[Plus[1, 1], Plus[Plus[1, 1], 1]]] ]] meets the use case in a different (and possibly more useful) way. $\endgroup$
    – Alan
    Commented Sep 17, 2018 at 18:20

3 Answers 3

8
$\begingroup$

Update

A slightly cleaner version of my first answer:

ReplaceAll[
    Inactivate[Plus[1,Plus[Plus[1,1],Plus[Plus[1,1],1]]]],
    Inactive[h_] :> Framed @* HoldForm[h]
]

Original answer

I don't know how useful this construct would be, but one idea is to use Inactivate:

ReplaceRepeated[
    Inactivate[Plus[1,Plus[Plus[1,1],Plus[Plus[1,1],1]]]],
    Inactive[h_][a___] :> Framed[HoldForm[h][a]]
]

enter image description here

$\endgroup$
1
  • 4
    $\begingroup$ Could you please add how Inactivate, HoldForm and Hold differ. This seems to enable much shorter code than mine. $\endgroup$
    – Johu
    Commented Sep 17, 2018 at 19:17
7
$\begingroup$

But each function needs the use of separate Framed[] function

Will solve it by using RuleDelayed and Replace with levelspec.

and functions are actually evaluated, what makes it makes inconvenient to use.

Will keep it from evaluating using Hold.

f = Hold[Plus[1, Plus[Plus[1, 1], Plus[Plus[1, 1], 1]]]];
Replace[f, z_ :> Framed[z], {2, -1}]

enter image description here

And my attempt to keep the head from evaluating

f = Hold[Plus[1, Plus[Plus[1, 1], Plus[Plus[1, 1], 1]]]];
Replace[f, 
  z : h_[args___] :> Row[{h, Framed[Row[{args}, ","]]}], {1, -1}][[1]]

Replace[f, 
  h_[args___] :> 
   Row[{h, "[", Row[{args}, ","], "]"}, Frame -> True], {1, -1}][[1]]

enter image description here enter image description here

To be honest, I was amazed when I learned z:h_ kind of syntax. You can understand how it works, if you read carefully the description part of Pattern.

$\endgroup$
6
$\begingroup$
ClearAll[frameAll]
frameAll = Map[Framed, # /. Inactive -> HoldForm, {0, -2}] &;

frameAll @ Inactivate[Plus[1,foo[1,1], Plus[Plus[1, 1], Plus[Times[1, 1,1], 1]]] ]

enter image description here

Alternatively,

ClearAll[frameAll2]
frameAll2 =  MapAll[#  /. h : _[__] :> Framed[h] &, # /. Inactive -> HoldForm] &;

frameAll2 @ Inactivate[Plus[1,foo[1,1], Plus[Plus[1, 1], Plus[Times[1, 1,1], 1]]] ]

same result

ClearAll[frameAll3]
frameAll3 = Block[{Inactive = Framed @* HoldForm[##]&}, #]&

frameAll3 @ Inactivate[Plus[1,foo[1,1], Plus[Plus[1, 1], Plus[Times[1, 1,1], 1]]] ]

same result

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.