# Extracting terms with certain heads in a function

Given a function with several arguments

func[a,b,g1[x],g1[x,y],g2[1],g2[g1[1]],3]


I would like to extract all arguments with the head g1 and g2 as a list. So the output I am looking for is

{g1[x],g1[x,y],g2[1],g2[g1[1]]}


The way I used to extract one head, say g1, is simply using the rule

/.func[l___,x__g1,r___]:> {x}


However, with two heads, this method does not work. I could write a module to do that but I wonder if there is a simpler way like the above rule for one head. Thank you so much!

Either

takeHeads = Cases[#, _g1 | _g2] &;
func[a, b, g1[x], g1[x, y], g2[1], g2[g1[1]], 3] // takeHeads


{g1[x], g1[x, y], g2[1], g2[g1[1]]}

or define func itself as

func = Cases[{##}, _g1 | _g2] &;
func[a, b, g1[x], g1[x, y], g2[1], g2[g1[1]], 3]


{g1[x], g1[x, y], g2[1], g2[g1[1]]}

• thank you, the method using cases is very useful. I did not know that Cases works inside the function func – mastrok Apr 17 '19 at 16:34
• You could also use the 1-arg form of Cases, e.g. takeHeads = Cases[_g1 | _g2]. – Carl Woll Apr 17 '19 at 18:09
• @mastrok If that surprised you that Cases worked on your custom func expression have a look at Everything is an Expression. Hope this helps to understand why this worked. – Thies Heidecke Apr 17 '19 at 18:12
• @Thies Heidecke Yes, I know that everything is an expression. However I thought that Cases only works with List only but not a general head. Thanks! – mastrok Apr 17 '19 at 18:16
Select[{##&@@func[a,b,g1[x],g1[x,y],g2[1],g2[g1[1]],3]},h=#;Head@#==h&]&/@{g1,g2}


{{g1[x], g1[x, y]}, {g2[1], g2[g1[1]]}}