2

I am writing a function along the lines of the following:

func[basis_,coordinates_,vars_]:=Table[Function[vars,monomial]@@@coordinates,{monomial,basis}]

The idea would be to call somethings like

func[{x,x*y},{{0,1},{1,2}},{x,y}]

and then receive as output

{{0,1},{0,2}}

However, vars as it appears on the right hand side is not the same vars as appears on the left hand side because of how Function works. (Mathematica warns of this by highlighting vars in red with the message "A variable name has been used twice in a nested scoping construct, in a way that is likely to be an error.")

First, how can I get around the name scope problem that Mathematica warns about? Then, is this even a appropriate way to go about what I am trying to do?

Thanks!

Grayscale
  • 498
  • 3
  • 9

3 Answers3

3
ClearAll[func1]
func1[basis_, coordinates_, vars_] := 
 Table[(Function @@ {vars, monomial}) @@@ coordinates, {monomial, basis}]

func1[{x, x*y}, {{0, 1}, {1, 2}}, {x, y}]

{{0, 1}, {0, 2}}

or

ClearAll[func2]
func2[basis_, coordinates_, vars_] := 
 Table[(Function[x, y] /. {x -> vars, y -> monomial}) @@@ coordinates, {monomial, basis}]

func2[{x, x*y}, {{0, 1}, {1, 2}}, {x, y}]

{{0, 1}, {0, 2}}

kglr
  • 394,356
  • 18
  • 477
  • 896
2

After some tinkering, this seems to work:

func[basis_, coordinates_, vars_] := 
  Table[With[{monomial = monomial},
    Function[Evaluate@vars, monomial] @@@ coordinates], {monomial, 
    basis}]

The Evaluate@vars prevents Function from treating vars as a symbol (which would result in a one-parameter Function). Instead, it passes {x,y}, as you need. See comments on this answer for discussion of why this is wrong.

I confess I don't full understand why we need the With statement. My current level of understanding is that there's some funny business going on between the Table variable's scoping and the Function's HoldAll attribute, so we need With to force the Function to properly deal with monomial as a table variable. See other questions, e.g. (Function in Table) or perhaps (How can I create a List of Functions), for more informed discussion.

jjc385
  • 3,473
  • 1
  • 17
  • 29
  • 1
    The need for the With statement is curious... it looks like it can be replaced however by evaluating monomial within Function, like this: func[basis_, coordinates_, vars_] := Table[Function[Evaluate@vars, Evaluate@monomial] @@@ coordinates, {monomial, basis}]. Why it needs to be evaluated, I am still not sure though. – Grayscale Jul 07 '17 at 16:04
  • 1
    Also it seems like the Module[{mon},...] is not needed... how come you have that in the function definition? – Grayscale Jul 07 '17 at 16:06
  • @Grayscale Ah, good catch on the Module[{mon},...] -- it's an unwelcome relic of a bygone version of the code. I'll get rid of it presently. – jjc385 Jul 07 '17 at 16:24
  • 1
    @Grayscale Yes, I actually realized that after I read klgr's answer -- a nice trick I learned on this site is to use f@@{a,b} rather than f[Evaluate@a, Evaluate@b]. The point of the With[{monomial=monomial},... statement is to force the variable to evaluate anyway. – jjc385 Jul 07 '17 at 16:31
  • You need Evaluate@vars for a different reason. The symbol vars won't be treated as an unevaluated symbol, since the evaluation mechanism injects its value (e.g. {x, y}) into Function[..] before the HoldAll attribute applies. What you need it for is to prevent {x, y} from being renamed {x$, y$} when monomial is injected into Function. Mathematica assumes the symbols in monomial are meant to be independent symbols. To get around this, you have to do something like the variants found in your, @kglr's and my answers. – Michael E2 Jul 07 '17 at 17:08
  • @MichaelE2 Thanks for the comment -- what I said is certainly incorrect. But do {x,y} get renamed to {$x,$y}? It seems like func[basis_, coordinates_, vars_] := Table[Function[vars, Evaluate@monomial] @@@ coordinates, {monomial, basis}] actually works -- the front end just highlights vars in red. One can also remove the @@@coordinates and check the FullForm of the returned function to see they aren't renamed. – jjc385 Jul 07 '17 at 20:32
  • 1
    If you Trace[] the command, it shows the renaming: func[basis_, coordinates_, vars_] := Table[With[{monomial = monomial}, Function[vars, monomial] @@@ coordinates], {monomial, basis}]; func[{x, x*y}, {{0, 1}, {1, 2}}, {x, y}] // Trace. (Note that monomial is also renamed, but that is irrelevant to the problem, I think.) The red vars is just a warning of a potential scoping conflict, which we have in this case but not in my answer. – Michael E2 Jul 08 '17 at 03:54
  • @MichaelE2 Ah, I see. The renaming seems to only occur inside a With/Module construct, not when Function stands alone. Thanks for clarifying. func[basis_, coordinates_, vars_] := Table[With[{monomial = monomial}, Function[vars, monomial] ], {monomial, basis}]; func[{x, x*y}, {{0, 1}, {1, 2}}, {x, y}] also makes the renaming clear. – jjc385 Jul 08 '17 at 04:06
2

Another way:

func[basis_, coordinates_, vars_] := Function[vars, #] @@@ coordinates & /@ basis;

func[{x, x*y}, {{0, 1}, {1, 2}}, {x, y}]
(*  {{0, 1}, {0, 2}}  *)
Michael E2
  • 235,386
  • 17
  • 334
  • 747