6

I have created the following TemplateBox Rule.

MakeBoxes[ActuarialSurvivalProbability[x_,t_],StandardForm]:=TemplateBox[{
        MakeBoxes[#,StandardForm]&/@x,
        MakeBoxes[t,StandardForm]
    },
    "ActuarialSurvivalProbability",
    DisplayFunction:>(RowBox[{
        SubscriptBox[
            "",
            TagBox[GridBox[{{#2}},GridBoxDividers->{}],"Grid"]
        ],
        SubscriptBox[
            "p",
            RowBox[{
                "",
                TagBox[GridBox[{#1},GridBoxDividers->{
                    "ColumnsIndexed"->{},
                    "RowsIndexed"->{1->Thickness[1]}
                }],"Grid"]
            }]
        ]
    }]&),
    Tooltip->"probability that atleast one of live(s) aged "<>ToString[x]<>" survives for "<>ToString[t]<>" year(s)"
]

Then I evaluate the following.

ActuarialSurvivalProbability[{x, y, z}, t]

I expect an answer like that generated from the following command:

RawBoxes@TemplateBox[{
        MakeBoxes[#,StandardForm]&/@{"x","y","z"},
        MakeBoxes[t,StandardForm]
    },
    "ActuarialSurvivalProbability",
    DisplayFunction:>(RowBox[{
        SubscriptBox[
            "",
            TagBox[GridBox[{{#2}},GridBoxDividers->{}],"Grid"]
        ],
        SubscriptBox[
            "p",
            RowBox[{
                "",
                TagBox[GridBox[{{"x","y","z"}},GridBoxDividers->{
                    "ColumnsIndexed"->{},
                    "RowsIndexed"->{1->Thickness[1]}
                }],"Grid"]
            }]
        ]
    }]&),
    Tooltip->"probability that atleast one of live(s) aged "<>ToString[{"x","y","z"}]<>" survives for "<>ToString[t]<>" year(s)"
]

But instead the dynamic length of input fed to GridBox in DisplayFunction in {#1} as {"x","y","z"} is not formatting correctly.

Can someone please help me?

user64494
  • 26,149
  • 4
  • 27
  • 56
user13892
  • 9,375
  • 1
  • 13
  • 41

2 Answers2

3

Thanks to jkuczm for an idea: https://mathematica.stackexchange.com/a/159407/5478:

MakeBoxes[ActuarialSurvivalProbability[x_, t_], StandardForm] := 
 With[{row = Table[Slot[i], {i, 2, Length[x] + 1}]} (*Key point,
  row of slots generated*), 
  TemplateBox[
   Prepend[MakeBoxes /@ Unevaluated@x, 
    MakeBoxes[t]] , 
   "ActuarialSurvivalProbability",
   InterpretationFunction -> (RowBox[{"ActuarialSurvivalProbability", 
        "[", RowBox[{RowBox[{"{", RowBox[Riffle[{##2}, ","]], "}"}], 
          ",", #}], "]"}] &), 
   DisplayFunction :> (RowBox[{SubscriptBox["", 
         TagBox[GridBox[{{#}}, GridBoxDividers -> {}], "Grid"]], 
        SubscriptBox["p", 
         RowBox[{"", 
           TagBox[GridBox[{row}, 
             GridBoxDividers -> {"ColumnsIndexed" -> {}, 
               "RowsIndexed" -> {1 -> Thickness[1]}}], "Grid"]}]]}] &),

   Tooltip -> 
    "probability that atleast one of live(s) aged " <> ToString[x] <> 
     " survives for " <> ToString[t] <> " year(s)"]]

enter image description here

Kuba
  • 136,707
  • 13
  • 279
  • 740
  • Thank you! you can also add a lastSlot variable like lastSlot=Slot[Length@x+1] inside With to fix the variable t in the formatting. But there is one problem if you copy this notation and evaluate it, it gives ActuarialSurvivalProbability[x, y, z, t] instead of the original ActuarialSurvivalProbability[{x, y, z}, t]. Is there a way to fix this? – user13892 Dec 10 '18 at 11:54
  • @user13892 right, take a look now – Kuba Dec 10 '18 at 12:08
  • Thanks you it works now. – user13892 Dec 10 '18 at 13:18
  • Thank you @Kuba for the excellent answer. I would like to ask why the DisplayFunction is using RuleDelayed rather than just a Rule is it necessary? because i see the documentation using it as well. – user13892 Dec 10 '18 at 14:41
  • @user13892 I am not 100% but I don't think it is necessary because Function or whatever you put there should not evaluate unless arguments are applied anyway. Otoh it is usually to follow docs because the fact that it does not matter does not imply it is implemented for Rule too :) – Kuba Dec 10 '18 at 14:51
  • Thank you one last thing. Is it possible to make the DisplayFunction conditional on the values of the input parameter say t. So if t=1. I want it to display say without presubscript. – user13892 Dec 10 '18 at 17:25
  • Or i will have to make a lot of separate definitions otherwise. – user13892 Dec 10 '18 at 17:25
  • @user13892 do you need contents to be editable? If not you can use InterpretationBox and keep original input and switch layout based on t or whatever. – Kuba Dec 10 '18 at 22:05
  • i would want the notation to be able to be copied across various formula manually and remain connected to the corresponding ActuarialSurvivalProbability[...] definition. – user13892 Dec 10 '18 at 22:34
  • @user13892 I think that deserves a separate question. If you post it please add special forms you want to care about. – Kuba Dec 11 '18 at 08:05
2

You can use TemplateSlotSequence for variable length TemplateBox arguments:

MakeBoxes[ActuarialSurvivalProbability[x_, t_], StandardForm] := TemplateBox[
    Prepend[MakeBoxes[t]] @ BoxForm`ListMakeBoxes[x, StandardForm],
    "ActuarialSurvivalProbability",
    InterpretationFunction -> (
        RowBox[{
            "ActuarialSurvivalProbability", 
            "[", 
            RowBox[{
                RowBox[{"{", RowBox[{TemplateSlotSequence[2, ","]}], "}"}],
                ",",
                #1
            }],
            "]"
        }]&
    ),
    DisplayFunction -> (
        RowBox[{
            SubscriptBox["", #1],
            SubscriptBox[
                "p",
                RowBox[{
                    "",
                    GridBox[
                        {{TemplateSlotSequence[2]}},
                        GridBoxDividers->{"RowsIndexed"->{1->Thickness[1]}}
                    ]
                }]
            ]
        }]&
    ),
    Tooltip->"probability that at least one of live(s) aged "<>ToString[x]<>
        " survives for "<>ToString[t]<>" year(s)"
]

Then:

ActuarialSurvivalProbability[{x, y, z}, t]

enter image description here

The advantage of using a TemplateSlotSequence solution is that the DisplayFunction/InterpretationFunction can be defined in a stylesheet.

A brief comment on TemplateSlotSequence

I think since the pure functions used in DisplayFunction and InterpretationFunction do not evaluate in the Wolfram Language kernel, TemplateSlotSequence was introduced as a way to enhance the creation of box structures. When the front end constructs the box expression using the DisplayFunction/InterpretationFunction, TemplateSlotSequence objects are interpreted as:

TemplateSlotSequence[1] -> Sequence[#1, #2, ...]
TemplateSlotSequence[2, ","] -> Sequence[#2, ",", #3, ",", ...]
TemplateSlotSequence[{3, 5}, " "] -> Sequence[#3, " ", #4, " ", #5]

Note that the above is not documented, and as with all undocumented functionality, it is subject to change.

Carl Woll
  • 130,679
  • 6
  • 243
  • 355
  • 1
    Any explanation why does it work? At the end those are *Functions not Templates. – Kuba May 07 '19 at 06:48
  • @Kuba Both answers are nice and works. (I came to similar solutions for variable index tensor notation.) However, suppose I want to add extra argument after I copied the Displayed form structure into a new notebook cell. Neither of the proposed solutions nor my solution allows to to this. Is it possible to extend code which would allow extra editing in the copied Display structure? – Acus May 07 '19 at 07:08
  • @user18792 you can add Editable -> True to the TemplateBox. – Kuba May 07 '19 at 07:10
  • @user18792 As far as I know, it is not possible to increase the number of template arguments through normal editing. If you use Show Expression, then of course it is possible to change the number of template arguments. – Carl Woll May 07 '19 at 07:37
  • @Kuba It does not add extra argument to the argument list. It multiplies one of arguments by a new symbol. – Acus May 07 '19 at 07:39
  • Ok. If somebody will find a solution it will be extremely handy. Just imagine: you copy a nice tensor with arguments indicated by scripts, then edit by adding new argument and send for evaluation in a nice form without a need to go back/forward with a long representation form. Of course, editing without change a number of arguments works as expected. – Acus May 07 '19 at 07:47