8

When I try to define this simple function

getCoeff[SeriesData[_, _, coeff_, _, _, _]] := coeff[[2]]

I get an error:

SeriesData: Coefficient specification coeff_ in SeriesData[_,_,coeff_,_,_,_] is not a list.

Can someone explain what's wrong with this? My understanding was that SetDelayed shouldn't complain about such things because until I actually evaluate an expression containing getCoeff it shouldn't try to evaluate Part[coeff,2].

There is no error thrown for the similar function

f[g[_, _, x_, _, _, _]] := x[[2]]

and furthermore getCoeff works as expected:

getCoeff@Series[E^(\[Pi] x), {x, 0, 3}]

outputs $\pi$.

I know the "right" way to manipulate SeriesData, I'd just like to understand this case for its own sake.

Diffycue
  • 1,834
  • 8
  • 11
  • 2
    Use unevaluated: getCoeff[Unevaluated[SeriesData[_, _, coeff_, _, _, _]]] := coeff[[2]]; Then getCoeff@Series[E^(\[Pi] x), {x, 0, 3}] = \[Pi]. – Shredderroy Sep 21 '19 at 21:10

1 Answers1

10

This is due to the special behavior of SetDelayed (:=) with regards to the first argument (see e.g. this question): The arguments of the l.h.s. are evaluated by SetDelayed, which causes the error you are seeing - after all, SeriesData[_, _, coeff_, _, _, _] is not a valid SeriesData construct. This is what HoldPattern is designed for: It prevents evaluation of its argument (like Hold), but is invisible to the pattern matcher. The solution is therefore simply:

(* prevent the l.h.s. from being evaluated *)
HoldPattern@getCoeff[SeriesData[_, _, coeff_, _, _, _]] := coeff[[2]]

getCoeff@Series[E^(π x), {x, 0, 3}]
(* π *)

(* prevent only evaluation of the first argument (equivalent in this case) *)
getCoeff[HoldPattern@SeriesData[_, _, coeff_, _, _, _]] := coeff[[2]]

getCoeff@Series[E^(π x), {x, 0, 3}]
(* π *)

As noted in the comments, the original version works perfectly fine ignoring the error message: If you look at ?getCoeff, you'll see that the definition that was actually made is the same with and without HoldPattern. If you evaluate SeriesData[_, _, coeff_, _, _, _] on its own, you will see that you get the error message, and then the input will be returned (which happens for many Mathematica functions) - if you would have gotten something else back, the definition would not work.

Lukas Lang
  • 33,963
  • 1
  • 51
  • 97
  • Thanks, this helps a lot! However I still wonder: why does the code seem to work anyway? If I left it as it was, would there be any consequences other than the error message? – Diffycue Sep 22 '19 at 16:50
  • No, in this case there would be no consequence: If you look at ?getCoeff, you'll see that the definition that was actually made is the same with and without HoldPattern. If you evaluate SeriesData[_, _, coeff_, _, _, _] on its own, you will see that you get the error message, and then the input will be returned (which happens for many Mathematica functions) - if you would have gotten something else back, the definition would not work – Lukas Lang Sep 22 '19 at 17:03