0
$\begingroup$

Between all the different commands about defining options, I cannot figure out how to do what seems like a fairly simple thing.

I want to define a function that sends default options to one nested in the main command so that on occasion I can also send additional options.

More specifically, I now have

txt[a_, b_, c_: {0, 0}, d_: {1, 0}, e_: ftsz ] :=
 Text[Style[a, FontFamily -> "Times", FontSize -> e], b, c, d]

This lets me send a default font and size to the Style command inside the Text command so that I can mostly use txt[string,coordinates] and avoid the cumbersome nested structure of Text[Style[string, options],coordinates,more specifications]. But I occasionally want to send to the Style command an option like FontSlant->Italic or FontWeight->Bold. Under my current definition of the function I am forced to abandon it and use the entire cumbersome syntax, repeating the font and size specifications. I would like to be able to just use txt[string,coords,FontSlant->Italic] while also being able to use txt[string,coords,boxcoords,FontSlant->Italic] and txt[string,coords,boxcoords,directioncoords,FontSlant->Italic].

Thanks for your attention.

$\endgroup$
8
  • 4
    $\begingroup$ Do these help? mathematica.stackexchange.com/q/124199/12 I don't understand your problem well enough to decide if it is a duplicate. $\endgroup$
    – Szabolcs
    Nov 10 '16 at 12:38
  • $\begingroup$ Thanks @Szabolcs. I found those. I do not think they answer my question. If they do, they are too complex to answer my question simply and clearly. $\endgroup$
    – Nicholas G
    Nov 10 '16 at 12:42
  • $\begingroup$ I re-read your question and I am not sure that there is a difference. See my answer specifically: mathematica.stackexchange.com/a/124208/12 Two steps: Make the patterns for c and d specific enough that they can't match any options. See the name : patt : value syntax. e should be e : OptionsPattern[]. $\endgroup$
    – Szabolcs
    Nov 10 '16 at 12:48
  • 2
    $\begingroup$ txt[a_, b_, c : {_?NumericQ, _?NumericQ} : {0, 0}, d : {_?NumericQ, _?NumericQ} : {1, 0}, opt : OptionsPattern[]] := Text[Style[a, opt, FontFamily -> "Times"], b, c, d] to be specific. This is from following the steps in the linked answer directly. It may not be trivial but I don't think it can be made simpler. In Style opt must come before any default options you give, to make sure the defaults are overridable. $\endgroup$
    – Szabolcs
    Nov 10 '16 at 12:51
  • $\begingroup$ All I can say is that I just tried in 10.0 and it worked... If I had to guess why it may not work on some systems: Make sure that the "Arial" font name is valid. It may not be installed on Mac/Linux. i.stack.imgur.com/Q3Ohg.png $\endgroup$
    – Szabolcs
    Nov 10 '16 at 14:45
2
$\begingroup$

I think I now understand the code of Szabolcs and can try to explain it.

The code is txt[a_,b_,c:{_?NumericQ,_?NumericQ}:{0,0},d:{_?NumericQ,_?NumericQ}:{1,0},opt:OptionsPattern[]]:=Text[Style[a,opt,FontFamily->"Times",FontSize->ftsz],b,c,d] and it does what I asked. But it is not simple, so I explain.

Starting from the end, opt:OptionsPattern[], takes any rules that appear in a syntax like txt[string,coords,rules]. Those will get passed to the Style command inside Text. That was easy. The hard part is allowing the addition of two more optional arguments before the rules for the text alignment and direction.

Before the options come two specifications like c:{_?NumericQ,_?NumericQ}. The first corresponds to text alignment and its default is set to {0,0}. The second corresponds to text direction and its default is set to {1,0}. The entire syntax of this element is c:{_?NumericQ,_?NumericQ}:{0,0}, to use the example of the first case of alignment. The second colon establishes the default value. The first colon tests for the existence of a pattern. The pattern follows the first colon and is a list with two elements, the two underscores inside the braces. Test this with tst[x:{_,_}]:=Plus@@x; this remains unevaluated unless it receives a list of two elements. Similarly, txt as defined remains unevaluated if it gets a list of three numbers where it expects the alignment list, which should have length of two.

Then, the syntax ?NumericQ following each underscore in each list checks so that the pattern is recognized only if it is a list of two numbers. Thus, again, a list of a number and a symbol will remain unevaluated.

Note that c is not followed with an underscore but with a pattern-matching test because the intent is to not let the function receive any expression as c. Rather, we saw that the pattern was defined to only be a list, only of two elements, and only of numerical elements.

Finally, the default nature of the specification of the font and its size relies on the fact that Mma allows duplication of option assignments and uses only the first assignment. Thus, if the user sends txt[string,coords,FontSize->20], the Style command receives two FontSize rules, one from the user and one from the function definition. In this case, Style ignores the second rule and prints with size 20. If no options are passed, then Style receives only one rule about font size only from the definition of the function and the FontSize will be the default set when we defined the function, ftsz.

Also, as you are experimenting with defining something like this, precede it with a ClearAll[definedfunction] so that tests that deviate from the new definition do not end up applying an older one.

I think this answers it. I hope I understood the code correctly. Please advise so I can correct it. Many thanks for helping me out.

$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.