Skip to main content
Added Note to clarify that you don't need to wrap Hold around your expr like I did in Examples.
Source Link

Note

In the examples, I only used Hold to prevent 2+3 from being evaluated to 5, and to prevent the two matrices being added together in the leftmost expr column. You don't need to wrap your expression with Hold before passing it into terms. terms is defined to already wrap everything in Hold before doing anything else. This also serves to show that if you are using Hold to prevent evaluation of expr before passing it into terms, then ReleaseHold will clear all instances of Hold, whether placed there by you or terms itself.

Note

In the examples, I only used Hold to prevent 2+3 from being evaluated to 5, and to prevent the two matrices being added together in the leftmost expr column. You don't need to wrap your expression with Hold before passing it into terms. terms is defined to already wrap everything in Hold before doing anything else. This also serves to show that if you are using Hold to prevent evaluation of expr before passing it into terms, then ReleaseHold will clear all instances of Hold, whether placed there by you or terms itself.

added 989 characters in body
Source Link

Applying new Heads

Baby Steps and Single Use Cases

When using the curried form (List@@expr), expr is evaluated before applying your specified head. Parentheses help protect you from this.

(Note that this first one is evaluated as (List@@a)+b+c and a has no head to replace.)

Alternatively, to be certain what you're applying your new head to, you could Defer evaluation, but then you need use the curried form of MapApply (@@@) to Apply List to the expression inside Defer, not to Defer itself.

Extracting Only Addition TermsWriting A Function To Do This

To do this right, we need something stronger than Defer. We'll need Hold and ReleaseHold.

Extracting Only Addition Terms

It's easy to use Apply to replace the top level head with List. It's still relatively easy to selectively replace Plus with List when it's the level 0 head. There's a bit of challenge preventing evaluation ofHandling the expressionmonomials (possibly replacingwhen the head is not Plus with a result) is a minor challenge. Handling the monomials is a larger challenge.

Without building If into the function, it's tricky to satisfy both conditions at the same time. Most attempts to satisfy one condition gave one too many or one too few instances of List in the other case.

It took quite a bit of debugging, but the solution is to wrap everything in List, then if Plus is the unevaluated head, replace it with Sequence. This always applies List, and if we have Plus, we get rid of it and just pass its sequence of parameters into the outer list, without creating a second list. Because we need wrap Hold around everything, we now need Extract to get at the buried Plus.

Summary

  1. Use HoldAll to ensure everything comes into the function without modification
  2. Wrap everything in Hold to prevent modification while working with the expression
  3. Reach past Hold and Extract the original head
  4. If that head is Plus, replace it with Sequence
  5. Take this head and Apply it back inside the held expression
  6. ReleaseHold
  7. Put everything inside List
    • Sequence will absorb into List and disappear, any other head will remain

When using the curried form (List@@expr), expr is evaluated before applying your specified head. Parentheses help protect you from this.

Alternatively, be certain what you're applying your head to, you could Defer evaluation, but then you need use the curried form of MapApply (@@@) to Apply List to the expression inside Defer, not to Defer itself.

Extracting Only Addition Terms

It's easy to use Apply to replace Plus with List when it's the level 0 head. There's a bit of challenge preventing evaluation of the expression (possibly replacing Plus with a result) is a minor challenge. Handling the monomials is a larger challenge.

It took quite a bit of debugging, but the solution is to wrap everything in List, then if Plus is the unevaluated head, replace it with Sequence.

Applying new Heads

Baby Steps and Single Use Cases

When using the curried form (List@@expr), expr is evaluated before applying your specified head. Parentheses help protect you from this.

(Note that this first one is evaluated as (List@@a)+b+c and a has no head to replace.)

Alternatively, to be certain what you're applying your new head to, you could Defer evaluation, but then you need use the curried form of MapApply (@@@) to Apply List to the expression inside Defer, not to Defer itself.

Writing A Function To Do This

To do this right, we need something stronger than Defer. We'll need Hold and ReleaseHold.

Extracting Only Addition Terms

It's easy to use Apply to replace the top level head with List. It's still relatively easy to selectively replace Plus with List when it's the level 0 head. Handling the monomials (when the head is not Plus) is a larger challenge.

Without building If into the function, it's tricky to satisfy both conditions at the same time. Most attempts to satisfy one condition gave one too many or one too few instances of List in the other case.

It took quite a bit of debugging, but the solution is to wrap everything in List, then if Plus is the unevaluated head, replace it with Sequence. This always applies List, and if we have Plus, we get rid of it and just pass its sequence of parameters into the outer list, without creating a second list. Because we need wrap Hold around everything, we now need Extract to get at the buried Plus.

Summary

  1. Use HoldAll to ensure everything comes into the function without modification
  2. Wrap everything in Hold to prevent modification while working with the expression
  3. Reach past Hold and Extract the original head
  4. If that head is Plus, replace it with Sequence
  5. Take this head and Apply it back inside the held expression
  6. ReleaseHold
  7. Put everything inside List
    • Sequence will absorb into List and disappear, any other head will remain
added 989 characters in body
Source Link

Mathematica has a built-in function for applying a specific head in an expression. Both of these are (almost) equivalent:

Apply[List, expr]
List@@expr

Apply replaces a head(s) in an expression with the specified head. The default levelspec is {0}, meaning it only applies to the top level (the Head of expr itself) when you don't specify anything else.

List applied to 2 expressions

When using the curried form (List@@expr), expr is evaluated before applying your specified head. Parentheses help protect you from this.

Examples of the curried form of Apply

Alternatively, be certain what you're applying your head to, you could Defer evaluation, but then you need use the curried form of MapApply (@@@) to Apply List to the expression inside Defer, not to Defer itself.

MapApply is needed when you Defer evaluation

Extracting Only Addition Terms

It's easy to use Apply to replace Plus with List when it's the level 0 head. There's a bit of challenge preventing evaluation of the expression (possibly replacing Plus with a result) is a minor challenge. Handling the monomials is a larger challenge.

  • If the head is Plus, you want it replaced with List
  • If the head is not Plus, you want to wrap List around the expression

It took quite a bit of debugging, but the solution is to wrap everything in List, then if Plus is the unevaluated head, replace it with Sequence.

You need both these lines to make it work.

SetAttributes[terms, HoldAll]
terms[expr_] := {ReleaseHold[Apply[Replace[Extract[Hold[expr], {1, 0}], Plus -> Sequence], Hold[expr], {1}]]}

Examples

The FullForm column shows that there aren't any spare Hold, Defer, or Unevaluated floating around.

Examples

Mathematica has a built-in function for applying a specific head in an expression. Both of these are (almost) equivalent:

Apply[List, expr]
List@@expr

Apply replaces a head(s) in an expression with the specified head. The default levelspec is {0}, meaning it only applies to the top level (the Head of expr itself) when you don't specify anything else.

List applied to 2 expressions

When using the curried form (List@@expr), expr is evaluated before applying your specified head. Parentheses help protect you from this.

Examples of the curried form of Apply

Alternatively, be certain what you're applying your head to, you could Defer evaluation, but then you need use the curried form of MapApply (@@@) to Apply List to the expression inside Defer, not to Defer itself.

MapApply is needed when you Defer evaluation

Mathematica has a built-in function for applying a specific head in an expression. Both of these are (almost) equivalent:

Apply[List, expr]
List@@expr

Apply replaces a head(s) in an expression with the specified head. The default levelspec is {0}, meaning it only applies to the top level (the Head of expr itself) when you don't specify anything else.

List applied to 2 expressions

When using the curried form (List@@expr), expr is evaluated before applying your specified head. Parentheses help protect you from this.

Examples of the curried form of Apply

Alternatively, be certain what you're applying your head to, you could Defer evaluation, but then you need use the curried form of MapApply (@@@) to Apply List to the expression inside Defer, not to Defer itself.

MapApply is needed when you Defer evaluation

Extracting Only Addition Terms

It's easy to use Apply to replace Plus with List when it's the level 0 head. There's a bit of challenge preventing evaluation of the expression (possibly replacing Plus with a result) is a minor challenge. Handling the monomials is a larger challenge.

  • If the head is Plus, you want it replaced with List
  • If the head is not Plus, you want to wrap List around the expression

It took quite a bit of debugging, but the solution is to wrap everything in List, then if Plus is the unevaluated head, replace it with Sequence.

You need both these lines to make it work.

SetAttributes[terms, HoldAll]
terms[expr_] := {ReleaseHold[Apply[Replace[Extract[Hold[expr], {1, 0}], Plus -> Sequence], Hold[expr], {1}]]}

Examples

The FullForm column shows that there aren't any spare Hold, Defer, or Unevaluated floating around.

Examples

added 31 characters in body
Source Link
Loading
added 693 characters in body
Source Link
Loading
added 693 characters in body
Source Link
Loading
Source Link
Loading