Splicing a list of arguments into a function with Sequence

16

3

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?

Guillochon

Posted 2013-02-08T02:02:38.980

Reputation: 5 827

What about renaming the question to something like "Splicing a list of arguments into a function with Sequence" or similar? – Yves Klett – 2013-02-08T14:01:39.010

Sure, sounds better to me... – Guillochon – 2013-02-08T19:43:16.000

Answers

25

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

Posted 2013-02-08T02:02:38.980

Reputation: 108 027

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 – 2018-04-23T18:46:53.470

@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 – 2018-04-23T19:50:33.003

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 – 2018-04-23T20:11:04.407

@HaukeReddmann You might be better off creating a separate question with exact requirements you have. – Leonid Shifrin – 2018-04-23T21:30:34.990

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 – 2018-04-24T12:36:00.210

@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 – 2018-04-24T18:54:35.237

6Half of my Mathematica questions are answered by adding one more @ symbol... :) – Guillochon – 2013-02-08T02:28:46.413

@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 – 2013-02-08T02:30:10.107

2In 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 – 2013-02-08T02:35:14.800

@Guillochon This may be a good idea. – Leonid Shifrin – 2013-02-08T02:40:00.977

1+1 Great explanation. The first sentence should be in the documentation :-) – Simon Woods – 2013-02-08T20:53:40.223

@SimonWoods Thanks :-). I came up with this when writing a book, so just borrowed from there. – Leonid Shifrin – 2013-02-08T20:56:24.053

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]

user5844

Posted 2013-02-08T02:02:38.980

Reputation:

+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 – 2013-02-08T16:04:12.903

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

Posted 2013-02-08T02:02:38.980

Reputation: 259 163

0

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

Posted 2013-02-08T02:02:38.980

Reputation: 302 076

1

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.

– Mr.Wizard – 2017-07-28T15:41:48.157