0
$\begingroup$

In Mathematica several versions of a function can have the same name with a pattern distinguishing which version of the function should be used for which type of input. Here is a minimum working example of functions with different names and some test data. (I actually need to work with complicated modules the operation is not relevant. The data structure is relevant.).

ClearAll[fred1, fred2];
fred1[a_] := a[[3]];
fred2[a_] := a[[3, 2]];
(* Test data *)
a1 = {1, 2, 3, 4};
a2 = {{1, 10}, {2, 20}, {3, 30}};
b1 = {"s1", "s2", "s3", "s4"};
b2 = {{"s1", "s10"}, {"s2", "s20"}, {"s3", "s30"}, {"s4", "s40"} };

When the functions are applied to the test data they works correctly

(*  Test functions *)
fred1[a1]
fred2[a2]
fred1[b1]
fred2[b2]


3

30

"s3"

"s30"

Now if I want just one function name to do both of the operations given above I can try and distinguish both operations by using a pattern in the function definition. I can see a way to do this for numbers, but how do you do it for cases which are not numbers?

ClearAll[fred];
fred[a_ /; NumberQ[a[[1]]] ] := a[[3]];
fred[a_ /; NumberQ[a[[1, 1]]] ] := a[[3, 2]];

(* Test function *)
fred[a1]
fred[a2]
fred[b1]
fred[b2]

Output

There are probably several ways of defining the pattern to make this work. Some sort of pattern that distinguishes an element of a list from a list. Is there a general way of doing this? Thanks

$\endgroup$

2 Answers 2

2
$\begingroup$
Clear["Global`*"]

fred[a_?VectorQ] := a[[3]]

fred[a_?MatrixQ] := a[[3, 2]]

a1 = {1, 2, 3, 4};
a2 = {{1, 10}, {2, 20}, {3, 30}};
b1 = {"s1", "s2", "s3", "s4"};
b2 = {{"s1", "s10"}, {"s2", "s20"}, {"s3", "s30"}, {"s4", "s40"}};

fred /@ {a1, a2, b1, b2}

(* {3, 30, "s3", "s30"} *)
$\endgroup$
0
$\begingroup$

In your specific example this would do the job:

fred[a_ /; (NumberQ[a[[1]]] || StringQ[a[[1]]])] := a[[3]];
fred[a_ /; Head[a] == List && (NumberQ[a[[1, 1]]] || StringQ[a[[1, 1]]])] := a[[3,2]];

(I added the StringQ to the condition to get the same output as in your example)

This would fail for list like a1 = {{1}, {2}, {3}, {4}};, but you can also try with Depth to check level of nested lists.

$\endgroup$
1
  • $\begingroup$ That is helpful. However, a list can contain many types of elements with different types of heads. I don't want to have all sorts of heads questioned. Perhaps look for a head that is not a list? Depth might be useful. $\endgroup$
    – Hugh
    Apr 20, 2021 at 18:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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