2
$\begingroup$

Background:I want to create a "palette" that contains buttons that evaluate the selected part of the expression and replace the selection with the result, just like what the built-in palette "Algebraic Manipulation" does. I found a way to achieve this feature in the documentation of Button:

Button[Defer[Expand[\[SelectionPlaceholder]]], None, BaseStyle -> "Evaluate"]

As you know, this creates a button named Expand that Expand the selected expression and replace it with the result.

(a + b)^5

Select the expression above and click the button, the expression will change to:

a^5 + 5 a^4 b + 10 a^3 b^2 + 10 a^2 b^3 + 5 a b^4 + b^5

I think this feature is very convenient, and I would like to create more stuff with it.e.g: create a button of this style with TableForm,I tried the following code:

Button[Defer[TableForm[\[SelectionPlaceholder]]], None, BaseStyle -> "Evaluate"]

Well, this is a simple imitation of the example shown above. But it gives me a button with a single SelectionPlaceholder.

Finally,I found that Defer won't work with TableForm. When you execute:

Defer[TableForm[{1, 2, 3}]]

It gives me the TableForm of {1,2,3}. But when I use the following code:

Tableform = TableForm; Defer[Tableform[{1, 2, 3}]]

it works fine:

 Tableform[{1, 2, 3}]

And then I can achieve what I want with this:

Tableform=TableForm;
Button[Defer[Tableform[\[SelectionPlaceholder]]], None, BaseStyle -> "Evaluate"]

Q: Could anyone gives me more details of how these things work?

Bonus: How can I create this kind of "inline execute" palette with more complicated user-defined functions? (I would like to add it to the Palettes Menu, but I have no idea of where to get my user-defined function initialized every time I start the palette.) And is there any other way to create a "inline execute" button?

$\endgroup$
7
  • 1
    $\begingroup$ The behaviour you are expecting is the one of Button[Defer[TableForm][\[SelectionPlaceholder]], None, BaseStyle -> "Evaluate"], right? $\endgroup$
    – Rojo
    Commented Dec 20, 2012 at 5:52
  • $\begingroup$ @Rajo Yes,I want to create a button that changes the selected List to TableForm. $\endgroup$
    – mmjang
    Commented Dec 20, 2012 at 5:58
  • $\begingroup$ Using $Pre = (Print[HoldForm @ #]; #) & one can see that MMA converts any kind of expression to a specified Form right after it parses it. When the expression is not a Form built-in symbol, it remains un-formatted. The problem originates from the way that MMA reads in the input, not Defer $\endgroup$
    – VF1
    Commented Dec 20, 2012 at 6:23
  • 1
    $\begingroup$ Who is Rajo? :P This would be a not shortened way to get the behaviour you said you wanted in a way that perhaps will let you see how to extend the behaviour and have more control... Button["Name", ToExpression[NotebookRead[SelectedNotebook[]], StandardForm, Function[in, Paste[TableForm[in]], HoldAllComplete]]] $\endgroup$
    – Rojo
    Commented Dec 20, 2012 at 7:48
  • $\begingroup$ Wow...stupid wrong type! I find your code very useful and flexible,never worried about the initialization again! $\endgroup$
    – mmjang
    Commented Dec 20, 2012 at 10:01

1 Answer 1

4
$\begingroup$

The problem is in the way that various *Form functions are handled. Most of these act as wrappers that change the way their contents are displayed by the FrontEnd (or when converted to Boxes). This is contrary to normal functions which are evaluated by the Kernel and which typically do something with their contents (arguments).

This is somewhat akin to the handling of Dynamic, so please see:
How can I compare a dynamic variable with a literal in Mathematica?

Consider:

x = Hold[TableForm[{1, 2, 3}]]

Mathematica graphics

Yet the definition of x is as we expect:

?x
x = Hold[TableForm[{1, 2, 3}]]

This property of Forms is often very useful, enabling styling without evaluation among other things.

HoldForm @ FullForm[1 + 2 + 3]
Plus[1, 2, 3]

We see that HoldForm works just as it should, preventing the evaluation of its argument but displaying invisibly, yet FullForm is correctly interpreted to display the full bracketed syntax of 1 + 2 + 3.

As Rojo shows in a comment, you just need to keep TableForm[stuff] from appearing in the output to prevent it from being active in formatting. One way to do this is to wrap it in Defer:

Button[Defer[TableForm][\[SelectionPlaceholder]], None, BaseStyle -> "Evaluate"]

You can still wrap the surrounding expression in Defer as well, to prevent other evaluation:

Button[Defer[Defer[TableForm][{1 + 2, 3 + 4}]], None, BaseStyle -> "Evaluate"]
$\endgroup$
1
  • $\begingroup$ Cool,I havan't think of using double Defer before! $\endgroup$
    – mmjang
    Commented Dec 20, 2012 at 9:50

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.