21
$\begingroup$

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?

$\endgroup$
2
  • $\begingroup$ What about renaming the question to something like "Splicing a list of arguments into a function with Sequence" or similar? $\endgroup$
    – Yves Klett
    Feb 8, 2013 at 14:01
  • $\begingroup$ Sure, sounds better to me... $\endgroup$
    – Guillochon
    Feb 8, 2013 at 19:43

7 Answers 7

3
$\begingroup$

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}

$\endgroup$
1
  • 3
    $\begingroup$ The second argument functionality was like introduced in v13.1. I use v12.2.0 and it doesn't have this feature. $\endgroup$
    – Syed
    Sep 10 at 18:04
29
$\begingroup$

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.

$\endgroup$
12
  • 7
    $\begingroup$ Half of my Mathematica questions are answered by adding one more @ symbol... :) $\endgroup$
    – Guillochon
    Feb 8, 2013 at 2:28
  • $\begingroup$ @Guillochon Thanks for the accept, although you could have given it some more time - perhaps someone would come up with a better answer. $\endgroup$ Feb 8, 2013 at 2:30
  • 2
    $\begingroup$ 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? $\endgroup$
    – Guillochon
    Feb 8, 2013 at 2:35
  • $\begingroup$ @Guillochon This may be a good idea. $\endgroup$ Feb 8, 2013 at 2:40
  • 1
    $\begingroup$ +1 Great explanation. The first sentence should be in the documentation :-) $\endgroup$ Feb 8, 2013 at 20:53
12
$\begingroup$

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]
$\endgroup$
1
  • $\begingroup$ +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. $\endgroup$ Feb 8, 2013 at 16:04
4
$\begingroup$

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:

$\endgroup$
3
$\begingroup$

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]

$\endgroup$
1
  • 1
    $\begingroup$ The first two are hardly general as other elements (a, b, c, d) cannot be assumed to be atomic. The last one is interesting but I think it better applies to a slightly different question. $\endgroup$
    – Mr.Wizard
    Jul 28, 2017 at 15:41
2
$\begingroup$

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] *)
$\endgroup$
1
$\begingroup$

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]*)
$\endgroup$

Your Answer

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

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