4
$\begingroup$

I feel stupid for not being able to do this and I think it is just a syntax error.

Let's say i have the following list:

L={x,xy,x^2+y,xyz,x^2}

How do I define 5 functions where each one is simply each polynomial in this list. Naively I would say this should work

f[i_][x_,y_,z_]:=L[[i]]

But this does not work.

f[i_][x_,y_,z_]=L[[i]]

This also does not work. What am I doing wrong? Should I be holding some expression unevalauted? I am not sure.

Thanks

$\endgroup$
1
  • 1
    $\begingroup$ x y, not xy , xy means a var called xy, x y means x times y $\endgroup$ Commented Apr 12, 2022 at 18:17

5 Answers 5

3
$\begingroup$

In order to "create" the functions you need to evaluate the assignment. For example:

Table[f[x_, y_, z_, i] = L[[i]], {i, Length[L]}]

will evaluate each assignment and correctly trigger the pattern match replacement so that, for example,

f[X,Y,Z,3]

evaluates to

X^2 + Y

$\endgroup$
4
$\begingroup$

The tricky part is to get the bindings of the pattern variables x_, y_ etc correct. For example, the natural approach:

L = {x, x y, x^2+y, x y z, x^2};

Clear[f]
With[{L = L}, f[i_][x_, y_, z_] := L[[i]]]

doesn't work because the pattern variables x_ etc. get renamed to x$_:

SubValues[f]
{HoldPattern[f[i$_][x$_, y$_, z$_]] :> {x, x y, x^2 + y, x y z, x^2}[[i$]]}

One approach that I like to use is to Inactive portions of the definition, and then Activate it. This avoids the pattern variable renaming that SetDelayed does. It would work as follows for your example:

Clear[f]
Activate @ Inactive[SetDelayed][f[i_][x_, y_, z_], Inactive[Part][L, i]]

Examples:

f[1][a, b, c]
f[2][1, 2, 3]
f[4][E, Pi, 1]

a

2

E π

$\endgroup$
2
$\begingroup$

I'd prefer not to rely on symbols appearing in one place being available for a function definition in another.

What you could do instead is specify some functions:

L = {#1 &, #1 #2 &, #1^2 + #2 &, #1 #2 #3 &, #1^2 &}

and then define your f to just select one:

f[i_] := L[[i]]

Alternatively, if you really want to use those exposed symbols, you could do this:

Set @@@ MapIndexed[{f[#2[[1]]][x_, y_, z_], #1} &, L]
$\endgroup$
0
2
$\begingroup$
l=({x,x y,x^2+y,x y z,x^2} // Map[Function[{x,y,z},#]&]);
l[[1]][1,2,3]

then use some pattern matches.

l=({x,x y,x^2+y,x y z,x^2} // Map[Function[{x,y,z},#]&]);
f[i_][x_,y_,z_]:=l[[i]][x,y,z];
f[1][a,b,c]

a

$\endgroup$
1
$\begingroup$

You have to leave space for multiplication, otherwise xy is considered a single variable. Try the following:

L = {x, x y, x^2 + y, x y z, x^2}

f[i_][x_, y_, z_] := L[[i]]

f[2][x, y, z]

xy

Edit: addressing the comment by the author of the OP

Edit 2: many thanks to @CarlWoll

L = {x, x y, x^2 + y, x y z, x^2};
ff[x_, y_, z_] := Evaluate[L]
ff[1, 1, z][[2]]

1

$\endgroup$
5
  • $\begingroup$ It's a good catch but this still does not work ''f[2][1,1,z]'' just returns ''xy'' $\endgroup$
    – 2132123
    Commented Apr 12, 2022 at 17:32
  • $\begingroup$ @2132123 ok I see. Sorry it was not clear from the OP in my eyes. So, just to make it clear, you want f[2][1,1,z] to return 1, i.e the element of the list evaluated. Right? $\endgroup$
    – bmf
    Commented Apr 12, 2022 at 17:37
  • $\begingroup$ @2132123 can you check the edit I just made? $\endgroup$
    – bmf
    Commented Apr 12, 2022 at 17:42
  • $\begingroup$ This works except for the unfortunate Part message. However, what is the point of f = MapIndexed[# &, L]? Just use Evaluate[Part[L, i]. $\endgroup$
    – Carl Woll
    Commented Apr 12, 2022 at 18:05
  • $\begingroup$ @CarlWoll oh yes, you are right. It is indeed sorter and cleaner. I guess the best way would be something like: ff[x_, y_, z_] := Evaluate[L] ff[1, 1, z][[2]] which does not produce any messages. $\endgroup$
    – bmf
    Commented Apr 12, 2022 at 18:08

Your Answer

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

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