1
$\begingroup$

I'm trying to use Manipulate[] and I need to have a non-fixed amount of sliders.

I tried writing something like:

Manipulate[x,Sequence@@{{x,0,1},{y,0,1}}]

I wrote only two parameters in this example, but I want a solution that works for an unknown amount of parameters.

If I learned this correctly, the Sequence head should "fall off" and the expression should become:

Manipulate[x,{x,0,1},{y,0,1}]

as it does in the case of:

f[Sequence@@{{x,0,1},{y,0,1}}]==f[{x,0,1},{y,0,1}]

but it doesn't. Instead, I get the following error:

Manipulate::vsform: Manipulate argument Sequence@@{{x,0,1},{y,0,1}} does not have the correct form for a variable specification.

Why doesn't it work?

I've seen the docs page of Sequence[] and I know that functions with either the SequenceHold or the HoldAllComplete attributes do not splice automatically, but Attributes[Manipulate] shows me that Manipulate doesn't have either of those.

Does it have to do with Manipulate[] having the ReadProtected attribute?

I also know Dynamic[] should do the trick, but I don't really want to learn about it (even thought I probably will, eventually)

Thanks

$\endgroup$
6
  • 1
    $\begingroup$ The Head of Sequence @@ {{x, 0, 1}, {y, 0, 1}} is Apply. So the HoldAll attribute of Manipulate keeps it from applying Sequence to the list. You could use Evaluate[Sequence @@ {{x, 0, 1}, {y, 0, 1}}], perhaps, but x and y will be evaluated. $\endgroup$
    – Michael E2
    Jul 21, 2023 at 0:54
  • $\begingroup$ This may be a good alternative: Manipulate[x, ##] & @@ Hold[{x, 0, 1}, {y, 0, 1}]. Probably depends on your actual use-case. You could also use Hold[{x, 0, 1}, {y, 0, 1}] /. Hold[i1_, i2_] :> Manipulate[x, i1, i2], which can be more flexible. For instance Hold[{x, 0, 1}, {y, 0, 1}] /. Hold[i1__] :> Manipulate[x, i1], where now i1 represents all sliders. $\endgroup$
    – Michael E2
    Jul 21, 2023 at 0:58
  • 1
    $\begingroup$ Or Manipulate @@ {x, {x, 0, 1}, {y, 0, 1}} $\endgroup$
    – Bob Hanlon
    Jul 21, 2023 at 1:03
  • $\begingroup$ @MichaelE2 Manipulate[x, ##] & @@ Hold[{x, 0, 1}, {y, 0, 1}] worked, thanks. Maybe it wasn't clear but I want this to work for a variable amount of parameters, and it does. $\endgroup$ Jul 21, 2023 at 15:24
  • $\begingroup$ @BobHanlon Thanks, that also works, even though I don't fancy the idea of writing all the arguments to Manipulate in a separate list and only then applying it. $\endgroup$ Jul 21, 2023 at 15:25

1 Answer 1

2
$\begingroup$

I would suggest that you build your Manipulate up out of pre-computed components rather than try to one-line it. Something like this:

With[
  {controls = Sequence[{x, 0, 1}, {y, 0, 1}],
   body = {x, y, Sin[x] Cos[y]}},
  Manipulate[
    body,
    controls]]

As for your requirement that it works for an unknown number of parameters, that's still doable, but you need to get creative in how you create the symbols associated to each control.

MyManipulate[n_] :=
  With[
    {symbols = Symbol[StringJoin["x" <> ToString[#]]] & /@ Range@n},
    With[
      {controls = Sequence @@ Table[{sym, 0, 1}, {sym, symbols}],
       body = symbols},
      Manipulate[
        body,
        controls]]]

Of course, I don't know how things work in your actual context, so this probably won't work directly--it's just a demo.

$\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.