2

So that you don't have to read all of the below, the crux of the matter was when using custom controls in Control or Manipulate, you have to use pure functions. As WReach pointed out, this is hidden in the Manipulate documentation at the end of Scope, Controls.

So defining a function like inField[x_Dynamic] below is fine, so long as it's passed to Control[] as the pure function inField[##]&.

The confusing aspect of this question was that my inField was a customized InputField. And, as pointed out by joebolte, InputField is the default fall-back position of Control if it's given a nonsensical function. It does this without any warning, making the debugging a little tricky.


Original Question (slightly modified to address WReach's 1st point)

Let's define a custom InputField[]

inField[Dynamic[x_]] := InputField[Dynamic[x], Expression, FieldSize -> 5]

Then use it in a Manipulate[] command

Manipulate[Table[{h, i, j, k}^n, {n, 1, 5}] // TableForm,
 {{h, 1, "hhh"}, inField},
 {{i, 1, "iii"}, inField[#] &},
 {{j, 2, "jjj"}, InputField[#, Expression, FieldSize -> 5] &}, 
 {{k, 3, "kkk"}, InputField[#, Expression, FieldSize -> 20] &},
 ControlPlacement -> Left]

Manipulate

Note this problem does not occur when inField[] is called by itself inFields

but does when Control[] is used (which is implicit in the Manipulate construction) Controls

My question is: Why does the Controler wtih inField different to inField[#]&? Is there an underlying reason or is it a bug? This behaviour occurs in Mathematica 7 and 8.


Edit: My motivation for wanting a custom inField is to catch and correct user inputs - more than just the validation than InputField provides. E.g.

inFieldRat[Dynamic[var_]] := Dynamic[If[TrueQ[Element[N[var] // Chop, Reals]], 
       var = Rationalize[var, .05], var = Null, var = Null]; 
       InputField[Dynamic[var], Expression, FieldSize -> 5]]
Simon
  • 14,631
  • 4
  • 41
  • 101

3 Answers3

2

Try changing your definition of inField as follows:

Clear@inField
inField[x_Dynamic] := InputField[x, Expression, FieldSize -> 5]

The original definition was stripping the Dynamic wrapper from the argument, causing it to be evaluated immediately and remain constant thereafter.

I suspect that the observed behaviour differences are due to non-standard evaluation in Control (which is HoldFirst).

Responding to @Simon's Comment

My misunderstanding: I was addressing the problem where the control was not updating its value correctly, as opposed to the visual disparity.

The documentation for Manipulate states that the function must be a pure function (under Scope, Controls). The documentation for Control is silent on the matter, but presumably it is the same since Manipulate is built upon Control. Control[{h, inField}] is not a valid form. However, Mathematica is not issuing an error message in this case. Rather, it is simply ignoring inField altogether and acting as if Control[{h}] had been specified. I would call this a bug.

I suspect that Control demands a pure function because a symbol has ambiguous meaning. Should it use the down-values or the own-values of the symbol (or even the up-values)? WRI apparently has gone for the own-values answer. I still think a message is justified if the expression evaluates to something not understood by Control.

WReach
  • 18,098
  • 3
  • 49
  • 93
  • +1 sounds probable. Not sure how to verify the stripping of Dynamic! – Dr. belisarius Feb 08 '11 at 00:47
  • That doesn't work. It produces identical outputs to the original `inField`. i.e. compare `Control[{h, inField}]` with `Control[{h, inField[#] &}]`, which naively should be the same. – Simon Feb 08 '11 at 01:06
  • (@belisarius: I like your +1 which doesn't actually signify an upvote!) – Simon Feb 08 '11 at 01:08
  • I missed that part in the `Manipulate` documentation. I agree, a warning message is definitely warranted. The problem I stumbled across was even more confusing since, as @joebolte said, `InputField` is the default fall-back behaviour. – Simon Feb 08 '11 at 03:32
  • I'm still not sure why `inField[x_Dynamic]` works but `inField[Dynamic[x_]]` doesn't. The latter construction was used in [this SO question](http://stackoverflow.com/questions/4420967/circular-angular-slider) and the Advanced Manipulate Functionality tutorial linked within... – Simon Feb 08 '11 at 03:49
  • @Simon ... just forgot. Fixed now :D – Dr. belisarius Feb 08 '11 at 11:08
  • @Simon: the original definition of `inField` used `InputField[x...` instead of `InputField[Dynamic@x...]`. `x_Dynamic` is an equivalent way to express the same thing. – WReach Feb 08 '11 at 14:30
1

Just an observation

Control and Manipulate are masking whatever happens inside InputField, syntax errors included.

Try this nonsensical construct:

Control[{h, InputField[1, 1, 1, 1, pp -> 1, , FieldSize -> MyError]}]
Dr. belisarius
  • 60,527
  • 15
  • 115
  • 190
  • You're right, but I'm providing inField as a function, while your example above is giving InputField[...] to Control as an Expression. It's probably a related behaviour. I think that your example *should* yield an error - as the dynamical variable `h` is not getting passed properly. – Simon Feb 07 '11 at 21:43
  • @Simon My intention was just showing that something fishy is going on inside Control and Manipulate. I started testing your case, and reducing it to it's more "elemental" expression, just to see if somewhere in the middle the problem disappeared. But it is still there, using just Control and InputField, and what is more, many other features of InputField (like syntax validation!) do not work either. – Dr. belisarius Feb 07 '11 at 21:47
  • I understand, but I still think that my example should work, whilst yours should give an error. So, do you think that it's a bug or a feature? – Simon Feb 07 '11 at 22:58
  • 1
    @Simon As I understand it, a syntax error is a ... syntax error, no matter how deep you shove, it should be reported. I vote for bug. – Dr. belisarius Feb 08 '11 at 00:43
1

Your example is somewhat confused because InputField is what Control returns when the domain doesn't evaluate to anything sensible. Consider Control[{h, z}] (where z is undefined) as an even more striking version of belisarius's example.

inField2 = Function[{x}, InputField[x, Expression, FieldSize -> 5]]

works correctly, though if you just want to set the size of the input field, I recommend

Manipulate[x, {{x, 5, "x"}, InputField, FieldSize -> 5} ]

Edit: If you want a Manipulate that can dynamically reset its own variables, as your edit indicates, I recommend something like

Manipulate[ If[x < 5, x = 5]; x, {x, 0, 10, InputField} ]

joebolte
  • 406
  • 2
  • 5
  • Hi Joe, welcome to SO (I've noticed a few WRI employees recently). Your first point is a very good one. Which explains what was going on in belisarius's examples - and why they don't produce errors. I've edited my question to give motivation. – Simon Feb 07 '11 at 23:42