Message Boards Message Boards

4
|
7157 Views
|
8 Replies
|
22 Total Likes
View groups...
Share
Share this post:

How to get Defer to behave with Manipulate/Dynamic?

Posted 12 years ago
Hello, I am struggling to make simple notebook programming code work.
Note that:
CellPrint[ExpressionCell[
Defer[
       Table[x, {x, 0, 10, 1}]
  ],"Input"]]
Behaves differently than:
CellPrint[ExpressionCell[
Defer[
       Manipulate[x, {x, 0, 10, 1}]
],"Input"]]
The front end seems to ignore the Defer request when a command would have dynamic output. Is there any way to get the same behavior (i.e., that for Table) as for Manipulate?

Thanks, Craig
POSTED BY: W. Craig Carter
8 Replies
I suppose this happens because the evaluation occurs in the FrontEnd rather than in the Kernel.  You could work around it by wrapping just the Head in the Defer statement, rather than wrapping the whole expression.  Thus
CellPrint[ExpressionCell[
    Defer[Manipulate][x, {x, 0, 10, 1}],
  "Input"
]]
POSTED BY: Mark McClure
Bravo! I wouldn't have guessed that nice solution. Thanks. Craig
POSTED BY: W. Craig Carter
Mark's suggestion is elegant and simple, and I'm ashamed that I didn't think of it at first.  But it can be difficult to apply to arbitrary inputs.  Here's a response I just sent to MathGroup which is more complex and relies on some knowledge of Mathematica internals, but solves the problem generally.  And also better explains why things are the way they are.

As you may know, when you do an evaluation in Mathematica, there are two steps for preparing that evaluation to return as an output.

First, the evaluation is actually performed. Then the evaluation is "typeset", which is to say the kernel runs MakeBoxes on the result of the evaluation and sends the boxes back to the front end.

There are some functions which don't do anything particularly interesting at evaluation time, but do something interesting as a result of typesetting. For example, Grid[] is very boring at evaluation time. When you evaluate it, it evaluates its arguments, but the Grid[] itself still remains as something of an inert wrapper. But when you typeset it, you suddenly get this new and interesting behavior where you get a grid onscreen. Since CellPrint of ExpressionCell is doing typesetting, that's the kind of behavior you're getting. E.g.,

CellPrint[ExpressionCell[Grid[{{1, 2}, {3, 4}}]]]

What may not be obvious is that things like Dynamic, DynamicModule, and Manipulate are exactly like Grid in this regard. The evaluation properties of Dynamic and Manipulate vary slightly since they hold their arguments. But otherwise, these are functions which essentially do nothing interesting until you typeset them. And since we know that CellPrint of ExpressionCell does typesetting, that explains the behavior you're seeing. So Defer isn't helpful, since all Defer does is prevent evaluation…not typesetting.

There's no documented way to do anything different. Even if you call MakeBoxes or ToBoxes by hand, that won't help, as they're also going to just typeset the result. By any documented means, it looks hopeless. But Mathematica does know how to do this. If you use the Cell->Convert To->StandardForm menu command on a cell, it doesn't turn all Grids into GridBoxes or all Manipulates into live active Manipulates. So it's definitely possible. Which means, to answer this question, I'm going to have to go way off the rails into undocumented (and unsupported) territory.

So, the best answer I can give to your question involves calling ToBoxes under controlled circumstances. And the controlled circumstance involves setting the following internal variable to True:

BoxForm`$UseTextFormattingWhenEvaluating

This variable is looked at by the internal typesetting system to determine whether to format things like Grid and Manipulate textually or as GridBoxes and interactive interfaces. Setting it to True gets the typesetting we want. So let's use that to define a new CellPrint-ing function:

SetAttributes[newCellPrint, HoldAll];
newCellPrint[cell_] :=
CellPrint[
ExpressionCell[
Block[{BoxForm`$UseTextFormattingWhenEvaluating = True},
RawBoxes[MakeBoxes[cell]]], "Input"]]

Notice I'm not using Defer here because MakeBoxes is HoldAll and our new function is HoldAll, so Defer is no longer necessary. But now I've locally changed the behavior of our MakeBoxes call by changing BoxForm`$UseTextFormattingWhenEvaluating in the Block[] to get the behavior your'e looking for.

Although this is undocumented and unsupported, it works from at least v7 (and probably v6, but I didn't test it) to v9, and I don't anticipate any reason why this would change in the foreseeable future.

EDIT: The InputForm solution added below is probably superior to my approach.  I hadn't realized that InputForm would work here...my oversight.
POSTED BY: John Fultz
I found the above really useful for some of my tasks, but if you're going to be using CreateDocument to generate notebooks there's an alternative approach you can use,

CreateDocument[{ExpressionCell[InputForm[Manipulate[x, {x, -10, 10}]], "Input"]}]
POSTED BY: Martin Hadley
This is related to the original post because I am trying to achieve the same goal: to create a set of tutorials with exercises and "example solutions" for a series of materials science classes.
Following John Fultz's offline advice, I've switched my method to NotebookWrite[].

'd like to have NotebookWrite[] create an input cell *exactly* as I have typed that input cell, line returns, indentation and all.
I'm trying to create set of tutorials with exercises and worked solutions.

Here are two *almost working* method derived from John's reply, however they don't reproduce the code (expr_ in expressionCell below) exactly as it is written---which is what I'm trying to do. I'm stuck.

(*--------------------------Method 1, almost works but produces 2d output and removes indentation--------------------------------*)
 SetAttributes[expressionCell, HoldAll];
 
 expressionCell[expr_] :=
 NotebookWrite[EvaluationNotebook[],
 Cell[Block[{BoxForm`$UseTextFormattingWhenEvaluating = True},
   RawBoxes[MakeBoxes[expr]]], "Input",
  LanguageCategory -> "Mathematica"]]
 
 (*examples---these "almost" work, but the FrontEnd converts to StandardForm 2d form and removes indentation. I'm trying to make it look more like InputForm*)

expressionCell[Integrate[x y^2, {y, 1, 2}]]

expressionCell[
Manipulate[x y^2,
{y, 1, 2}]
]

expressionCell[
Module[{x, y, z},
x y z
]
]

(*--------------------------Method 2, wrap expr in InputForm, indentation lost and * is inserted--------------------------------*)
 Clear[expressionCell]
 SetAttributes[expressionCell, HoldAll];
 
 expressionCell[expr_] :=
 NotebookWrite[EvaluationNotebook[],
 Cell[Block[{BoxForm`$UseTextFormattingWhenEvaluating = True},
   RawBoxes[MakeBoxes[InputForm[expr]]]], "Input",
  LanguageCategory -> "Mathematica"]]
 
(*examples---these work, but I am trying to indicate to students what I am typing, and so wish to eliminate the explicit *-multiplication, and I'd like to keep my line returns and indentation on the Module example *)

expressionCell[Integrate[x y^2, {y, 1, 2}]]

expressionCell[Manipulate[x y^2, {y, 1, 2}]]

expressionCell[
Module[{x, y, z},
x y z
]
]
POSTED BY: W. Craig Carter
Craig,

My first suggestion would be to simply store the exact cell expressions you need in a list and use those in your code.

If that is not possible, perhaps the following might be of use.

We have a package called RobotTools, which simulates typing of keystrokes.

I've uploaded it here: https://download.wolfram.com/?key=TJHPTZ

After you unzip it in your application directory, you can call it like so:

Needs["RobotTools`"]

nb = CreateDocument[];
KeyType[nb, "Module[{x, y, z},\[EnterKey]x y z\[EnterKey]]"]

Which should give you the 100% typing fidelity you seek.
POSTED BY: Arnoud Buzing
Very interesting, Craig, in that I had the same goal of creating hints for teaching materials and struggled with the same problem of creating Manipulates that did not evaluate.  Wish I'd noticed your question and the answers earlier.
POSTED BY: Seth Chandler
Hello Seth,
My experience is that this teaching method lends itself well to "longer problems" that are built from many subproblems: teaching by integrating by parts.

For a concrete example, I have a tutorial that takes about 3-4 hours that starts from the Shrodinger equation and ends with visualizing the band structure in a one-dimensional crystal.  This is a classic problem; but, as classically taught, the students get `bogged down with the math more than the concepts' and visualization is not easy.

I give them a notebook and a bunch of encoded .m files.  The notebook sets up each subproblem, does some example coding and visualization, and then sets a problem for the students. These problems would typically take 15-30 minutes to solve depending on their experience.  After the students have either struggled enough or solved the subproblem, I give them a "key" to source an encoded .m file which contains an example solution.  The solutions are required to make it to the next subproblem. Supplying solutions this way helps ensure that students who get stuck don't get left behind.   The encoding is there so that the student can't just click for the solution when they get frustrated.

I haven't implemented the RobotKeys package that is mentioned above yet; but my initial exploration is very promising.  It will also lend itself to "video how-tos."   Creating a suite of these is a longer term project.
POSTED BY: W. Craig Carter
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract