# ReplacementAll with list elements

I'm trying to define a function that replaces certain expressions that appear when calculating scattering amplitudes (not important). Basically, I have a function spab[a_,c_,b_], where a,b are single elements and c is a list with at most two levels. For example, I can write

spab[1,{2,3,4},5]; spab[4,{3},9]; spab[5,{{3,4},{7,6},2},1];


etc. I have another function spbb[a_,c_,b_] with the same type of arguments and a last function spa[a_,b_] with only single element arguments. What I want to do is to substitute spab[a_,c_,b_] for the product

(*Sum over all i*) spa[a,c[[1,i]]]*spbb[c[[1,i]],c[[2;;]],b].


In other words, I want to take the first element of the list c and set it as the single element argument for the spa and spbb functions. If c[] is itself a list, then I want to take each element of this sublist, apply the procedure I just described and then sum over these elements. I'll write up some examples of what I want the result to look like:

spab[1,{2,3,4},5]->spa[1,2]*spbb[2,{3,4},5];
spab[5,{{3,4},{7,6},2},1]->spa[5,3]*spbb[3,{7,6},2},1] + spa[5,4]*spbb[4,{7,6},2},1]


I though I could achieve this with something like:

spab[5,{{3,4},{7,6},2},1]/.spab[a_,c_,b_]->Plus[spa[a,#]*spbb[#,c[[2;;]],b]&/@c[]]


In my mind, this first creates a list of products spa[a,c[[1,i]]]*spbb[c[[1,i]],c[[2;;]],b] by using the Map command with the list c[] and then sums over al the elements. However, the result is:

During evaluation of In:= Part::partd: Part specification c[] is longer than depth of object.

During evaluation of In:= Part::take: Cannot take positions 2 through -1 in c.

During evaluation of In:= Part::pkspec1: The expression spa[a,1] spbb[1,c[[2;;All]],b] cannot be used as a part specification.

During evaluation of In:= Part::pkspec1: The expression spa[5,1] spbb[1,{{7,6},2},1] cannot be used as a part specification.

Out= (spa[5, {{3, 4}, {7, 6}, 2}] spbb[{{3, 4}, {7, 6}, 2}, {{7, 6}, 2}, 1])[[spa[5, 1]spbb[1, {{7, 6}, 2}, 1]]]


What do all these error messages mean? Why do I get this weird result, and what is the factor between [[ ]] that appears at the very end? If someone culd help me make things clear and fix this, I would very much appreciate it.

• The reason that you're getting the errors is that the expression Plus[spa[a, #]*spbb[#, c[[2 ;;]], b] & /@ c[]] gets evaluated before being used in the replacement rule. At that moment, c has no value (and so is not a list that Part can work on). That leads to a cascade of follow on errors as the ReplaceAll is attempted with a broken rule. Mar 23, 2022 at 14:46
• For what it's worth, you could use RuleDelayed: spab[5, {{3, 4}, {7, 6}, 2}, 1] /. spab[a_, c_, b_] :> Plus[spa[a, #]*spbb[#, c[[2 ;;]], b] & /@ c[]] Mar 23, 2022 at 14:55
• That indeed seems to get rid of the error, but then it doesn't perform the sum... Mar 23, 2022 at 16:52
• Right. I was showing that RuleDelayed holds the right side of the rule unevaluated. I still think your best bet is just defining DownValues. Mar 23, 2022 at 17:02

Rather than try to do replacements, you could just define DownValues (transformation rules):

spab[a_Integer, b : {__Integer}, c_Integer] :=
spa[a, First@b]*spbb[First@b, Rest@b, c];
spab[a_Integer, b : {_List, ___}, c_Integer] :=


I'm making assumptions about the arguments being Integers and so forth, which may need to be changed. If you don't want these transformations to be applied automatically, then define them for a different symbol (e.g. spabTransform) and then use ReplaceAll with spab->spabTransform.

Update

I like this better. Fewer assumptions and removes duplicate arithmetic.

spab[a_, b : {_List, ___}, c_] :=

• Could you briefly explain what the different commands are doing? Specifically, I would love some clarification on b : {_List, ___} and b : {__} Mar 23, 2022 at 17:10
• := is infix form of SetDelayed, so we're defining some transformation rules that will become DownValues for spab (you can evaluate DownValues[spab] to see how Mathematica will now transform spab-headed expressions). These DownValues, by the way, look a lot like what you would try to do with ReplaceAll rules, but since this functionality is already built into Mathematica, using ReplaceAll is kind of re-inventing the wheel here. ... Mar 23, 2022 at 17:21
• The left had side of these expressions is the pattern to match. You're already familiar with Blank (the underscore). There are other versions, specifically BlankSequence and BlankNullSequence. So, this bit {__} (using BlankSequence) is a pattern that will match a List that has at least one element. This bit {_List, ___} is a pattern that will match a List whose first element is a List and has zero or more elements following it (that's what BlankNullSequence is for). ... Mar 23, 2022 at 17:25
• The colon is just infix for Pattern. So, b : {__} is saying, here is a pattern that we'll name b and the pattern will match a list that has at least one element). Similarly, b : {_List, ___} is saying, here is a pattern that we'll name b and that will match a list that has a list in first position and zero or more elements following. Mar 23, 2022 at 17:29