1
$\begingroup$

Background

There are multiple ways to define Functions. I would assume all methods are equivalent, and allow for the same options. However, I fail to find the explicit equivalent of a Function with a List as an argument.

SetDelayed on List

In particular, consider this implicit function. This allows you to fill in a list as an argument and immediate assigns variable names to the elements of the list:

func1[{a_,b_}]:=a+b
func1[{3,4}] (** 7 **)
func1[3,4] (** func1[3,4] **)

Set on Two Arguments

Now, consider this explicit function. As defined this way, the function has two arguments and cannot deal with a list.

func2=Function[{a,b},a+b];
func2[{3,4}] (** Function::fpct **)
func2[3,4] (** 7 **)

Set on List

Finally, attempt to define a new function with a list as an argument. Similar to above, we want the elements of this list to be assigned variable names directly. This does not work.

func3=Function[{{a,b}},a+b]; (** Function::flpar **)
func3[{3,4}] (** Function::flpar **)
func3[3,4] (** Function::flpar **)

My Question

Is it possible to define a Function explicitly (using the syntax fun=Function[listarg,body] as in func3) and also directly assign names to the elements? If so, what is the correct syntax / pattern?

Answer I am Not looking for

Please note that I realise there are many work-arounds, for example using With.

func4=Function[{x},With[{a=x[[1]],b=x[[2]]},a+b]];
func4[{3,4}] (** 7 **)

This is not the point of my question. I merely want to understand Mathematica syntax and patterns better.

Answer I am looking for

Why is it possible to define func1 using SetDelayed or := and make it work directly on a List, but not using the syntax of func3. Perhaps there is no clear answer. Perhaps this is just the way Mathematica works, nothing more. But perhaps I am missing some fundamental understanding of Patterns. This is where I need help.

$\endgroup$
  • $\begingroup$ You could try f[x_List]=... $\endgroup$ – Ulrich Neumann Nov 5 '19 at 14:15
  • $\begingroup$ Note that I want fun=Function[listarg,body]. I call that 'explicit', perhaps there is a better name. $\endgroup$ – LBogaardt Nov 5 '19 at 14:18
  • $\begingroup$ @LeonidShifrin So to sum up: No, there is no out-of-the-box equivalent of func[{a_,b_}]:=a+b in terms of func=Function[{{a,b}},a+b]. However, your answer in Pure Functions with Lists as arguments provides the best self-made work-around. Am I interpreting that correctly? If so, I will indeed close this question. $\endgroup$ – LBogaardt Nov 5 '19 at 20:04
  • $\begingroup$ @LBogaardt Yeah, more or less. I can't attest to how good my answer is, since adding downvalues to Function is not the best thing in the world - it was more like an illustration. I would still ask you to not delete the question - it can serve as a gateway to that other one, once we close it as duplicate. $\endgroup$ – Leonid Shifrin Nov 5 '19 at 20:50
0
$\begingroup$
Clear["Global`*"]

Format[x[n_]] := Subscript[x, n]

The form that you request implies that the length of the list is known. If the length is known, then you can use Part to reference ("name") the individual elements of the list.

f[x_List?(Length[#] == 3 &)] := (x[[1]] + x[[2]])/x[[3]]

f@Array[x, 3]

enter image description here

f@Array[x, 5]

enter image description here

Or if the length is at least three,

f[x_List?(Length[#] > 2 &)] := (x[[1]] + x[[2]])/x[[3]]

f@Array[x, 3]

enter image description here

f@Array[x, 5]

enter image description here

However, it generally would be better to define a function of a list using list operations so that the length of the list need not be a specific value.

f1[x_List] := Total[Most[x]]/Last[x]

f1@Array[x, #] & /@ Range[4]

enter image description here

| improve this answer | |
$\endgroup$

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