# Can a pure function be constructed whose argument list is a matrix?

Can a pure function be constructed whose argument list is a matrix?

Using Function, I know it's not possible, but I'd like to get something like:

Function[{{x1, y1}, {x2, y2}}, {-2 y1 y2, 8 x1 x2 - 2 x2 y1 - 2 x1 y2}]


In general, I would like to obtain a pure function whose argument has the alternatives of being a vector or a matrix. Something like this:

MyFunction[vector | matrix, vectorfunction]:=


I appreciate any help!

There might be a more elegant way to specify the function, but this works:

Function[{-2 #[[1, 2]] #[[2, 2]], 8 #[[1, 1]] #[[2, 1]] - 2 #[[2, 1]] #[[1, 2]] - 2 #[[1, 1]] #[[2, 2]]}]


• Do you like collaborations? :) Oct 13, 2022 at 3:12
• Possibly. What’s up? Oct 13, 2022 at 3:36
• Do you remember when I asked about an unprotected symbol generator? That question is related to this post. I would like to find collaboration to finish a function that is very useful in normal forms theory. Oct 13, 2022 at 3:47
• I don’t remember, but I can try to help. Oct 13, 2022 at 4:00
• @E.Chan-López If you want to be able to do something different for matrices and vectors, I think the operator form of Replace is closer to what you want. Oct 13, 2022 at 8:22

Why not use Replace if you want to be able to use patterns?

fun = Replace[
{
{{x1_, y1_}, {x2_, y2_}}?MatrixQ :> {-2 y1 y2,
8 x1 x2 - 2 x2 y1 - 2 x1 y2},
{x1_, y1_}?VectorQ :> x1 + y1 (*or whatever *)
}
];
fun @ {a, b}
fun @ {{a1, a2}, {b1, b2}}

• Is the VectorQ and MatrixQ required in that case ? Would the structure fun[{x1_, y1_}] := x1; fun[{{x1_, y1_}, {x2_, y2_}}] := x2 have the same behavior? Oct 13, 2022 at 11:42
• @userrandrand It is if you want to make sure it does what you want. The pattern {x1_, y1_} also matches a matrix with 2 rows MatchQ[{{a1, a2}, {b1, b2}}, {x1_, y1_}]. You should always be careful with overlapping patterns like that. If you know exactly what kinds of input you can expect, you can usually do without these tests, but otherwise its best to be defensive. Oct 13, 2022 at 13:53
• Nice, thank you. Oct 13, 2022 at 21:18

One could convert the matrix to an association with string valued keys indicating matrix positions and use named slots.

For example:

(Slot["{1, 2}"]*Slot["{1, 1}"] &)@
KeyMap[ToString, Association@Most@ArrayRules@{{x1, y1}, {x2, y2}}]


Out: (* x1 y1 *)

That is rather lengthy to use. One could package that into auxiliary functions.

### Auxiliary functions

The first list/matrix to association function:

listorule[list_] := KeyMap[ToString, Association@Most@ArrayRules@list]


The second function makes it a bit easier to write the Slot arguments. One can change the notation as explained in the next section.

ss[indices__] := Slot@ToString@List[indices]


The last function replaces Function or & to control the evaluation order and makes it convenient to compose listtorule on the right.

func[a_] := Function[Evaluate[a]]@*listorule;


Note: There might be cases where one does not want to use Evaluate on the entire expression in which case func above might evaluate too much of the expression.

### Example above rewritten

Reconsidering the example above, one can code the following function

h = ss[1, 1]*ss[2, 2] // func


Test:

h@{{x1, y1}, {x2, y2}}


Out: (* x1 y2 *)

### Possible modifications

The syntax could be simplified by adding an extra dictionary/association between a user defined notation and string of positions. For example, if the size of the matrix is smaller than 10 one could consider writing ss@12*ss@11. The reason for the restriction on matrices smaller than 10 is to avoid ambiguity in something like ss@143.

One might also consider maybe rewriting some of the steps above using With and using symbols we feel comfortable with which would skip the Evaluate part. That seems reasonable for a very long function but it is a bit tedious for a small function.