10

I have defined a function as follows:

fDistance[pointA_, pointB_: {0, 0}, metric_: "taxi"] := 
 Module[{interval}, 
  If[metric == "taxi", 
   interval = 
    Abs[pointB[[1]] - pointA[[1]]] + Abs[pointB[[2]] - pointA[[2]]], 
   interval = 
    Sqrt[(pointB[[1]] - pointA[[1]])^2 + (pointB[[2]] - 
        pointA[[2]])^2]]; interval]

Then

fDistance[{3, 4}]
(*7; ok*)

fDistance[{3, 4}, {1, 2}, "euclid"]
(*2 Sqrt[2]; ok*)

But

fDistance[{3, 4}, "euclid"]
(*error message*)

How can I avoid that Mathematica assign the string literal 'euclid' to the variable pointB? It should have returned 5 as the output below shows

fDistance[{3, 4}, {0, 0}, "euclid"]
(*5*)

And as a second question: Is it possible to call the function in the following manner

fDistance[pointB={1, 2}, metric='normal', pointA={3, 4}]

that is, its arguments are paired with a keyword instead of being in the correct order according to the function denition?

Thank you very much.

Dimitris
  • 4,794
  • 22
  • 50

1 Answers1

14

You must add a restricting pattern to the second parameter. Define your function like this:

fDistance[pointA_, pointB : {_, _} : {0, 0}, metric_: "taxi"] := (* rest of code *)

fDistance[{3, 4}, "euclid"]
5

Recommended reading:


For your second point you should first familiarize yourself with:

Then return to the first link in this post for how this will relate to default arguments.

As a brief example of setting up your function to use only named options:

ClearAll[fDistance]

Options[fDistance] =
  {"pointA" -> {0, 0}, "pointB" -> {0, 0}, "metric" -> "taxi"};

fDistance[OptionsPattern[]] := Module[{pointA, pointB, metric},
  {pointA, pointB, metric} = OptionValue[{"pointA", "pointB", "metric"}];
  If[metric == "taxi", 
    Abs[pointB[[1]] - pointA[[1]]] + Abs[pointB[[2]] - pointA[[2]]], 
    Sqrt[(pointB[[1]] - pointA[[1]])^2 + (pointB[[2]] - pointA[[2]])^2]
  ]
]

fDistance[]
fDistance["pointA" -> {3, 4}]
fDistance["metric" -> "euclid", "pointA" -> {3, 4}]
0

7

5

This may also be of use and/or interest to you:

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • Thank you very much for your quick reply. Regarding the second question is it possible something like the following: fDistance[pointB={1, 2}, metric='normal', pointA={3, 4}] ? If yes how I should modify the definition of the function? – Dimitris Feb 26 '17 at 00:34
  • @dimitris Sorry, I overlooked that in a hurry to answer. Yes, those are known as Options in Mathematica. Let me gather some links. – Mr.Wizard Feb 26 '17 at 00:36
  • No reason to apologize:-)! Take your time. Thanks also for the useful links. I think after almost 10 years I have to revisit http://www.verbeia.com/mathematica/tips/Tricks.html – Dimitris Feb 26 '17 at 00:40
  • 1
    @dimitris In case you have somehow missed it be sure also to read: http://www.mathprogramming-intro.org/book/Book.html – Mr.Wizard Feb 26 '17 at 00:42
  • Definitely the Holy Grail of Mathematica Programming-)! – Dimitris Feb 26 '17 at 00:46
  • @dimitris I quickly reviewed the links I gave and I didn't see a short example of a function with only named options and no formal parameters so I added an example to my answer. – Mr.Wizard Feb 26 '17 at 01:02
  • Thanks again for the edited answer. – Dimitris Feb 26 '17 at 10:44
  • @Mr.Wizard I really like "recommend reading" sections in answers. In that case we not only get the "How" ( as asked ) but also the "Why". – nilo de roock Feb 28 '17 at 11:12