20
$\begingroup$

Is there any way to completely remove the head of an expression function?

For example, how would I remove the head Cos from Cos[a] to give only a as an output.

$\endgroup$
5
  • 4
    $\begingroup$ First@Cos[a]? $\endgroup$
    – C. E.
    Commented Jun 9, 2014 at 0:03
  • 1
    $\begingroup$ Note that all expressions have heads and bodies. These two are not separable. For example, a has head Symbol. All you can do is to replace a head with something else or extract parts of an expression. $\endgroup$ Commented Jun 9, 2014 at 0:50
  • $\begingroup$ @Oleksandr I agree and would think that the closest thing to a headless expression is one with Sequence as head. $\endgroup$
    – acl
    Commented Jun 9, 2014 at 2:36
  • $\begingroup$ @acl Identity $\endgroup$ Commented Jun 9, 2014 at 4:18
  • $\begingroup$ @MikeHoneychurch I was thinking about things like Sequence @@@ List[List[a, b], List[a, c]]. But you're right, for examples like in your answer Identity does the job. $\endgroup$
    – acl
    Commented Jun 9, 2014 at 12:04

6 Answers 6

27
$\begingroup$

You can actually Delete the head of the expression, which is part 0:

Delete[#, 0] & /@ {Cos[a], Sin[b], Tan[c]}
{a, b, c}

With version 10 operator forms:

Delete[0] /@ {Cos[a], Sin[b], Tan[c]}
{a, b, c}

One case of interest may be held expressions. If our expression is:

expr = HoldComplete[2 + 2];

And the head we wish to remove is Plus, we cannot use these:

Identity @@@ expr
Sequence @@@ expr
expr /. Plus -> Identity
expr /. Plus -> Sequence
Replace[expr, _[x__] :> x, 1]

All produce e.g.:

HoldComplete[Identity[2, 2]]  (* or Sequence *)

We can use Delete or FlattenAt:

Delete[expr, {1, 0}]
FlattenAt[expr, 1]
HoldComplete[2, 2]
HoldComplete[2, 2]

You could also use a pattern that includes the surrounding expression on the right-hand-side, as demonstrated here, e.g.:

expr /. h_[_[x__]] :> h[x]
HoldComplete[2, 2]

Notes

As the documentation for Delete reads:

Deleting the head of a whole expression makes the head be Sequence.

Delete[Cos[a], 0]
Sequence[a]

Since this resolves to a in normal evaluation this should usually not be an issue.

$\endgroup$
6
  • $\begingroup$ +1, I like my held expressions. About "when there is no surrounding expression", I like this remark. To see that this is really the behaviour of Delete, rather than some post-processing of the kernel, you can evaluate: SetAttributes[seqHHA, {SequenceHold, HoldAll}]; seqHHA@Evaluate@Delete[Cos[a], 0]. So I disagree with your latest edit. The "a whole expression" here is the entire first argument of Delete, rather than any "subexpression" of the expression in the first argument. $\endgroup$ Commented Jun 9, 2014 at 9:46
  • $\begingroup$ @Jacob I'm not sure what your example is intended to illustrate, and I don't know why you disagree with what I said. In your case you Evaluate Delete[Cos[a], 0] before seqHHA sees it, so there is effectively no surrounding expression. What am I missing? $\endgroup$
    – Mr.Wizard
    Commented Jun 9, 2014 at 9:51
  • $\begingroup$ @Jacob I just saw the addendum to your comment above, and I think I understand now, as well as I suppose what the documentation is saying. Nevertheless I don't think that (the documentation) is written very clearly. $\endgroup$
    – Mr.Wizard
    Commented Jun 9, 2014 at 9:58
  • 1
    $\begingroup$ @Jacob Would not your example be better written like this?: Attributes[seqHHA] = {SequenceHold}; seqHHA[Delete[Cos[a], 0]] $\endgroup$
    – Mr.Wizard
    Commented Jun 9, 2014 at 10:17
  • 1
    $\begingroup$ I agree that that is better. It seems I was too cautious or something :). I think the HoldAll is irrelevant, but caution may be good. For example, Sequence[symb] may not resolve to symb if symb is intended to be a head, in for example Delete[{Sin},0][Pi]. Also compare this with ReleaseHold, i.e. ReleaseHold[Hold[Sin]][Pi]. $\endgroup$ Commented Jun 9, 2014 at 11:51
10
$\begingroup$

Does this come close?

Cos[a] /. Cos[a] -> a

Or

Cos[a] /. _[a] -> a

Or

First@Cos[a]

Or

list = {Sin@a, Cos@b};
First /@ list

{a, b}

$\endgroup$
6
  • $\begingroup$ The second one is good because you can apply it to functions without need to retype the functions in Replace all. thanks eldo. $\endgroup$ Commented Jun 9, 2014 at 0:11
  • $\begingroup$ @Algohi- see my update :) $\endgroup$
    – eldo
    Commented Jun 9, 2014 at 0:17
  • 3
    $\begingroup$ Your second example doesn't remove the head, it just matches _[a] with literally a then always returns a. For example Cos[b] isn't matched. I guess you meant /. _[a___] -> a, so that eg lekker[b, c] /. _[a___] -> a works. $\endgroup$
    – acl
    Commented Jun 9, 2014 at 0:25
  • $\begingroup$ @acl - Thanks - Just inspected the 4 forms by applying Head and FullForm to them - everything seems to be right. $\endgroup$
    – eldo
    Commented Jun 9, 2014 at 0:33
  • 1
    $\begingroup$ Sorry, I did not mean that your examples don't work, but that if the argument is not a then it does not get matched, because the a on the right hand side of /. is not a pattern. eg Cos[b] /. _[a] -> a evaluates to Cos[b], ie, the a is matched literally. You probably meant Cos[b] /. _[a_] -> a or, more generally (allowing for multiple arguments) Cos[b] /. _[a___] -> a. $\endgroup$
    – acl
    Commented Jun 9, 2014 at 0:40
10
$\begingroup$

You remove a head by replacing it with Identity

Cos[a] /. Cos -> Identity

For doing this over lots of expressions:

list = {ArcTan[x], ArcTan[x], ArcTan[x], Cot[x], Cot[z], Cot[x], 
  ArcTan[z], ArcTanh[y], ArcTanh[x], Cot[y]};

list[[All, 0]] = Identity

or

Identity @@@ list

etc

$\endgroup$
9
$\begingroup$

Sequence might be useful if your expressions come inside other expressions. For example:

num = 10;
lst = MapThread[
  #1@#2 &,
  {
   RandomChoice[{Cos, Sin, Exp, Tan, Cot, ArcTan, ArcTanh}, num],
   RandomChoice[{x, y, z}, num]
   }
  ]

(*

{ArcTan[x], ArcTan[x], ArcTan[x], Cot[x], Cot[z], Cot[x], ArcTan[z], 
 ArcTanh[y], ArcTanh[x], Cot[y]}

*)

(this is just a long-winded way of producing a list), then

Sequence @@ # & /@ lst

(*
{x, x, x, x, z, x, z, y, x, y}
*)

Roughly, Sequence dissolves and its children get promoted whenever it appears as something other than the topmost head, eg f[Sequence[g]] evaluates to f[g]. Thus,

expr = f @@ lst
Sequence @@ # & /@ expr

(*

f[ArcTan[x], ArcTan[x], ArcTan[x], Cot[x], Cot[z], Cot[x], ArcTan[z], 
 ArcTanh[y], ArcTanh[x], Cot[y]]

f[x, x, x, x, z, x, z, y, x, y]

*)
$\endgroup$
3
  • 5
    $\begingroup$ Sequence @@ # & /@ lst can be written more compactly as Sequence @@@ lst $\endgroup$
    – Bob Hanlon
    Commented Jun 9, 2014 at 3:54
  • $\begingroup$ Note that Sequence will not evaluate inside a head with HoldAllComplete or SequenceHold attributes. $\endgroup$
    – Mr.Wizard
    Commented Jun 9, 2014 at 9:35
  • $\begingroup$ @BobHanlon Good point, thanks $\endgroup$
    – acl
    Commented Jun 9, 2014 at 12:01
4
$\begingroup$

I got same problem and did not find good answer here. Then I found Mathematica function Level is very usefull for this:

f=Cos[a];
Level[f, 1]

{a}

Second argument in level defines the depth of subexpressions to be extracted.

Level[Cos[a + b], 1]

gives you:

{a + b}

Meanwhile Level[cos[a + b], {-1}] completely opens subexpressions:

{a, b}

You strategy with more complex functions than just Cos[a] could be either to undestand and use proper levelspec parameter, or try to change it iteratively looking for your Head in the output list.

$\endgroup$
3
  • $\begingroup$ Actually, this replaced Cos by List. $\endgroup$
    – bbgodfrey
    Commented Sep 6, 2016 at 23:16
  • 1
    $\begingroup$ Level can have a third argument, that can be used to put the result in something else other than List. For example, Level[Cos[a + b], {-1}, HoldComplete] or Level[Cos[a + b], {-1}, Sequence]. $\endgroup$
    – Karsten7
    Commented Sep 7, 2016 at 4:00
  • $\begingroup$ +1 as Level is very useful for getting a list of arguments. For example Level[Plus[a,b,c],1] which you can now Map, Select or something else without having the Plus remain as a head of the output. $\endgroup$
    – Johu
    Commented Sep 17, 2018 at 2:05
1
$\begingroup$

One can also use DeleteCases (which also works inside held expressions):

DeleteCases[{Sin[Cos[x]], Cos[x], Hold[2 + 2], HoldComplete[2*3]}, 
 Cos | Plus | Times, -1, Heads -> True]

(*{Sin[x], x, Hold[2, 2], HoldComplete[2, 3]}*)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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