I have a function that I am defining as (assume m,n,a,b are non-negative integers):

myfcn[x_^m_ p_^n_, x_^a_ p_^b_] := basefcn[m, n, a, b];

and then extending to all polynomials by linearity.

The way I defined the function above works as long as m,n,a,b are all greater than 1, but fails otherwise. For instance, I want myfcn[x p^2, p] to evaluate to basefcn[1,2,0,1], but mathematica does not recognize that this is what I want.

How do I extend my function definition to include these cases without explicitly writing out all possible input forms?



Some silliness with Optional i.e. : (thanks @Mr.Wizard for the -. tip). I thought I could ride the Optional gravy train all the way but just could not find a way to deal with arguments that equal to 1 i.e. x^0 p^0, so I defined another instance of the function to convert 1 to x^0 p^0 (and then pass it back to the original definition) (oh yes I can!). This also does seem to be monomial-only.

A small note: since x and p have to be specified (otherwise x could just as well stand for p_), I left the base as x and p, instead of x_ and p_; they are not used by the function anyway so it really doesn't matter much.

ClearAll[myfcn, x, p]
SetAttributes[myfcn, HoldAll]

myfcn[(c1 : 1 : 1) (x1 : x^m_. : x^0) (p1 : p^n_. : p^0),
  (c2 : 1 : 1) (x2 : x^a_. : x^0) (p2 : p^b_. : p^0)] :=
 basefcn[m, n, a, b]

myfcn[x p^2, p]
(* basefcn[1, 2, 0, 1] *)

myfcn[x p^2 + p, p]
(* myfcn[x p^2 + p, p] *)

{Defer[myfcn][Sequence @@ #], myfcn @@ #} & /@ 
  Partition[Flatten[Outer[x^#1 p^#2 &, {0, 1, 2}, {0, 1, 2}]]~Prepend~1, 2] // 
 Grid[#, Frame -> All] &

Mathematica graphics

  • 1
    $\begingroup$ I was about to post an answer using Optional. You win this time. However, you do not need to use e.g. (m_: 1) as m_. will do since 1 is the default value for Power. This significantly streamlines your code. See: (51585) $\endgroup$ – Mr.Wizard Aug 20 '14 at 3:54
  • $\begingroup$ Also I note that you are using literal x and p in your function whereas by my interpretation of the question these are arbitrary symbols or expressions. $\endgroup$ – Mr.Wizard Aug 20 '14 at 3:56
  • $\begingroup$ @Mr.Wizard Thanks so much for the _. tip! Could I edit my post to add that in? Also, the reason I chose to use explicit x and p is because the function the OP defines (with x_ and p_) is ambiguous. For example, using OP's definition, myfunc[x^2, p^3] could be matched such that x^2 matches x_^m_, and p^3 matches p_^b_. However, x^2 could just as well match with p_^n_, and p^3 with x_^a_, since x_ and p_ in OP's definition could be anything. Please let me know if I might be confused on that point. $\endgroup$ – seismatica Aug 20 '14 at 4:12
  • $\begingroup$ I also apologize if my answer had made you abandon your answer. I don't doubt your method with Optional would be better/more elegant than mine. $\endgroup$ – seismatica Aug 20 '14 at 4:17
  • $\begingroup$ Your method looks fine. I was taking a different approach but I don't think it would be useful to the OP as there were unresolved issues, which your choice of literal x and p better addressed. $\endgroup$ – Mr.Wizard Aug 20 '14 at 5:01


myfcn2[arg1_, arg2_] := basefcn @@ Flatten[Exponent[#, {x, p}, List] & /@ {arg1, arg2}]; 
myfcn2[x p^2, p]
(* basefcn[1, 2, 0, 1] *)

Update: To restrict the arguments to monomials (Thanks: @wxffles )

myfcn3[arg1_, arg2_] /; FreeQ[{arg1, arg2}, Plus] := 
      basefcn @@ Flatten[Exponent[#, {x, p}, List] & /@ {arg1, arg2}];
myfcn3[x p^2 , p]
(* basefcn[1, 2, 0, 1] *)
myfcn3[x p^2 + p , p]
(* myfcn3[p + p^2 x, p] *)
  • $\begingroup$ Is there a way I can make it only use the implementation you give when arg1 and arg2 are monomials? Because if they are polynomials (i.e. arg1 = x p + x^2 p), then this implementation does not work properly. After I define it successfully on monomials, I will extend to all polynomials by linearity. $\endgroup$ – user2397833 Aug 20 '14 at 2:51
  • $\begingroup$ Your could use arg1_ /; FreeQ[arg1, Plus] to ensure monomialism. $\endgroup$ – wxffles Aug 20 '14 at 3:07
  • $\begingroup$ Thank you @wxffles! -- this is much neater than the monster I was about to suggest: myfcnX[arg1_, arg2_] /; (And @@ (Length[MonomialList[#]] == 1 & /@ {arg1, arg2})) := ... :) $\endgroup$ – kglr Aug 20 '14 at 3:18
  • $\begingroup$ This code gives the same results for myfcn3[2 x, p] and myfcn3[x,p]. This gives problems when I try to extend it to arbitrary polynomials. $\endgroup$ – user2397833 Aug 20 '14 at 6:10
  • $\begingroup$ @user2397833, yes it does. I presume you need myfcn3[2 x, p] to return unevaluated? $\endgroup$ – kglr Aug 20 '14 at 6:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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