21

Not sure if this has been asked, but I have a fairly simple operation that I don't know the syntax for. Say I have an array with some values, and a function f that accepts an arbitrary number of arguments. The following:

array = {e,f};
f[a, b, c, d, array];

...is functionally equivalent to:

f[a, b, c, d, {e, f}];

OK, will Sequence help? Nope, this does the same thing:

f[a, b, c, d, Sequence@array];

Essentially, I want to include e and f into the list of arguments, i.e. I want to know the syntax for telling Mathematica I want it to evaluate this:

f[a, b, c, d, e, f];

How do I go about doing this?

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
Guillochon
  • 6,117
  • 2
  • 31
  • 57

7 Answers7

29

Sequence means more or less "no head". What you want to do is to remove the head List from an inner list. Or, put in another way, you want to replace this head with "no head". The operation that changes one head to another is Apply. Therefore, what you really want is

f[a, b, c, d, Sequence @@ array]

where @@ stands for Apply.

Leonid Shifrin
  • 114,335
  • 15
  • 329
  • 420
  • 7
    Half of my Mathematica questions are answered by adding one more @ symbol... :) – Guillochon Feb 08 '13 at 02:28
  • @Guillochon Thanks for the accept, although you could have given it some more time - perhaps someone would come up with a better answer. – Leonid Shifrin Feb 08 '13 at 02:30
  • 2
    In this case, the answer was so simple that I didn't think anyone could do better. That being said, perhaps something should be added to the Etiquette section of the FAQ to indicate that one should wait some amount of time before accepting? – Guillochon Feb 08 '13 at 02:35
  • @Guillochon This may be a good idea. – Leonid Shifrin Feb 08 '13 at 02:40
  • 1
    +1 Great explanation. The first sentence should be in the documentation :-) – Simon Woods Feb 08 '13 at 20:53
  • @SimonWoods Thanks :-). I came up with this when writing a book, so just borrowed from there. – Leonid Shifrin Feb 08 '13 at 20:56
  • Incidently, the answer also solved my problem, i.e. appending a given argument to a given function with other given arguments, like input G(a,b), output G(a,b,c). f[z_, y_] := G @@ Join[List @@ z, {y}] (Which can be done more elegantly, I guess, but it works.) – Hauke Reddmann Apr 23 '18 at 18:46
  • @HaukeReddmann You could just do Append[Unevaluated[G[a, b]], c], given that both input and output for your case have the same head. – Leonid Shifrin Apr 23 '18 at 19:50
  • I realized that actually I need a bit more: Lists with arbitrary occurences of G like {uG[a,b],vG[c,d]} shall be replaced by {uG[a,b,e],vG[c,d,e]}. The list part a /@ should do, but how to fish out the G? – Hauke Reddmann Apr 23 '18 at 20:11
  • @HaukeReddmann You might be better off creating a separate question with exact requirements you have. – Leonid Shifrin Apr 23 '18 at 21:30
  • Wanted to try it myself first :-) Here is my hack: Convert to string, replace ] by ,e] , revert to expression, done. :-) (Of course this only works since my requirements are weak - ] doesn't occur elsewhere.) – Hauke Reddmann Apr 24 '18 at 12:36
  • @HaukeReddmann I would avoid converting to strings and back, like a plague. You never know when this will bite you. There certainly are much better options available. – Leonid Shifrin Apr 24 '18 at 18:54
12

You can certainly bypass the use of Sequence[] (though it is certainly a neat thing):

f[a, b, c, d, ##] & @@ array
   f[a, b, c, d, e, f]
  • +1. The extent to which this can be called "bypassing" depends on whether or not SlotSequence (##) uses Sequence internally. One thing I am certain about is that both use the same underlying mechanism. In particular, Sequence @@ array can be also written as ##& @@ array (a form beloved by @Mr.Wizard). The discussion in comments below my answer to this question seems relevant here. – Leonid Shifrin Feb 08 '13 at 16:04
4

For completeness, neither of the existing answers will work as written when working with held expressions. That case is addressed in:

The most concise solution I know is what I have come to call the "injector pattern" in reference to that Q&A, for lack of another term.

Let's say our function is foo and we want to insert arguments from seq.

SetAttributes[foo, HoldAll];

seq = Hold[1/0, 8/4];

seq /. _[x__] :> foo[1, 2, x]
foo[1, 2, 1/0, 8/4]

Compare this to the result of the other two methods shown:

foo[1, 2, Sequence @@ seq]
foo[1, 2, Sequence @@ seq]
foo[1, 2, ##] & @@ seq

Power::infy: Infinite expression 1/0 encountered. >>

foo[1, 2, ComplexInfinity, 2]

The SlotSequence method can be adapted by giving the anonymous function a HoldAll attribute but this requires the use of an undocumented form:

Function[, foo[1, 2, ##], HoldAll] @@ seq
foo[1, 2, 1/0, 8/4]

Reference:

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
3

Also

Sequence @@@ g[a, b, c, d, array]
## & @@@ g[a, b, c, d, array]
FlattenAt[g[a, b, c, d, array], -1]

g[a, b, c, d, e, f]

kglr
  • 394,356
  • 18
  • 477
  • 896
3

Splice came with V 12.1:

array = {e, f};

foo[a, b, c, d, Splice[array, foo]]

foo[a, b, c, d, e, f]

If we Splice a list of elements inside an expression with a Head other than List we must pass this Head (foo) as 2nd argument.

Compare to

List[a, b, c, d, Splice[array]]

{a, b, c, d, e, f}

eldo
  • 67,911
  • 5
  • 60
  • 168
  • 3
    The second argument functionality was like introduced in v13.1. I use v12.2.0 and it doesn't have this feature. – Syed Sep 10 '23 at 18:04
2

Another way is to delete the Head with Delete

array = {e, f};

foo[a, b, c, d, Delete[array,0]]

(* foo[a,b,c,d,e,f] *)

Delete[{-1,0}]@foo[a, b, c, d,array]

(* foo[a,b,c,d,e,f] *)

user1066
  • 17,923
  • 3
  • 31
  • 49
1

Another way to do this is to use Replace for the particular position the array has in your example:

array = {e, f};
Replace[#, x_ :> Sequence @@ x, {1 - Depth[#]}] &@g[a, b, c, d, e, h, array];

(g[a, b, c, d, e, h, e, f])

Or using ReplacePart, Position and Extract for any positions of the arrays:

s = ReplacePart[#, Thread[Position[#, x_List] -> 
    Function[x, Sequence @@ x[[1]]]@
    Extract[#, Position[#, x_List]]]] &;

s@g[a, b, c, d, array, m, h, array]

(g[a, b, c, d, e, f, m, h, e, f])

E. Chan-López
  • 23,117
  • 3
  • 21
  • 44