# Optional arguments with lists as function parameter

I'm developing a function f which should support optional arguments {x_, y_} in list form. A simple example looks like this:

f[{x_, y_}] := {x, y}


How can I set default values for the list argument {x_, y_}? My first attempt was

f[{x_:1, y_:2}] := {x, y}


which matches f[{}] and correctly returns {1, 2} but which does not match f[].

How can I define the function f so that f[] gives the desired default values?

• reference.wolfram.com/language/tutorial/… – LLlAMnYP Apr 17 '15 at 13:35
• add f[] = f[{}] later, it this ok? – Kuba Apr 29 '15 at 8:26
• This seems not to be a nice solution. There are many internal MMA functions like ImageTake which use optinal and default arguments in list form. Basically I want to implement the same functionality regarding optional arguments as in ImageTake, see the documentation. – Robinaut Apr 29 '15 at 8:33
• @Kuba Sorry for being unprecise. I'm just wondering if your solution is the "official" way to deal with optional list arguments like in ImageTake. I also tried f[args:{x_, y_}:{1,2}] := {x, y}which seems to work. However, I'm not sure if understand it the right way... – Robinaut Apr 29 '15 at 11:07
• @Robinaut Use Needs["GeneralUtilities"]; and evaluate PrintDefinitions@Cells, as you can see, WRI is not trying to put everything in one pattern either. It is not handy nor readable. – Kuba Apr 29 '15 at 11:14

Sorry for being unprecise. I'm just wondering if your solution is the "official" way to deal with optional list arguments like in ImageTake. I also tried f[args:{x_, y_}:{1,2}] := {x, y}which seems to work. However, I'm not sure if understand it the right way...

I do not believe I have seen a guideline or even a standard practice for this particular case. I quite like Kuba's solution and I often make use of that method, e.g.: Can I make a default for an optional argument the value of another argument?

You chose ImageTake as a model. For this function there is no need for the optional behavior that you describe as the syntax is already handled by Take. Note:

This syntax is valid for each argument of ImageTake (after the first) just as it is for Take. Therefore a trivial reimplementation is:

myImageTake[i : _Image | _Image3D, spec__] :=


Test:

img = Import["http://cdn.sstatic.net/mathematica/img/logo@2.png"]  (* site logo *)

myImageTake[img, -66, {30, 120}]
ImageTake[img, -66, {30, 120}]


img3D = ExampleData[{"TestImage3D", "CThead"}];

myImageTake[img3D, -20, {80, 180}, 120]
ImageTake[img3D, -20, {80, 180}, 120]


If I wanted tighter control of the input than spec__ I would use something like:

p1 = (All | _Integer | {Repeated[_Integer, {1, 3}]})?(FreeQ[#, 0] &);

ClearAll[myImageTake]

myImageTake[i : _Image | _Image3D, spec : p1 ..] /;
Length[{spec}] <= Length@ImageDimensions[i] :=


This example may be a bit too specific but it is the one that you gave. For other examples the pattern you found (args:{x_, y_}:{1,2}) or the method of passing arguments back to the function (Kuba's answer and my linked post above) may be more appropriate. If you give another example or model function I shall try to address that as well.

There are many ways to achieve this, I'd probably do something simple like

f[] = f[{}]
(*set or set delayed, depends of context*)


But you can also do something more fancy, although it is not compact enough for me to like it :P

Default[f] = {};
f[Optional@{x_: 1, y_: 2}] := {x, y}

f[]
f[{}]

{1, 2}
{1, 2}
`