views:

665

answers:

7

What is this language construct called?

In Python I can say:

def a(b,c): return b+c
a(*[4,5])

and get 9. Likewise in Ruby:

def a(b,c) b+c end
a(*[4,5])

What is this called, when one passes a single array to a function which otherwise requires multiple arguments?

What is the name of the * operator?

What other languages support this cool feature?

Thanks!

+2  A: 

I've been calling it "list expansion", but I don't think that's standard terminology (I don't think there's any...). Lisp in all versions (Scheme included), and Haskell and other functional languages, can do it easily enough, but I don't think it's easy to do in "mainstream" languages (maybe you can pull it off as a "reflection" stunt in some!-).

Alex Martelli
I don't know of any standard terminology either, but I've always pronounced '*args' as 'star args' and '**kwargs' 'kay word args'. I'm sure others have their own terminology, and I'm curious to hear it it.
Mark Roddy
+8  A: 

In ruby, it is often called "splat".

Also in ruby, you can use it to mean 'all of the other elements in the list'.

a, *rest = [1,2,3,4,5,6]
a     # => 1
rest  # => [2, 3, 4, 5, 6]

It can also appear on either side of the assignment operator:

a  = d, *e

In this usage, it is a bit like scheme's cdr, although it needn't be all but the head of the list.

Matthew Schinckel
The splat operator is the term used in The Ruby Programming Language, which is supposedly co-written by Matz (create of Ruby)
Svend
The "all of the other elements in the list" syntax (having a starred name on the left side of the assignment) was added in Python 3—your example will work unmodified. Also (in Python 3), the starred variable doesn't have to be last: `a, b, *middle, y, z = range(10)` works. It can't appear on the right side of an assignment, though, but it's not really needed, since you can do `l = list(a, *b)`.
Miles
Yeah, I think I remember reading that. I still use python 2.4-2.6 at work (and will continue to do so, I suspect). I just did a test with ruby 1.8, and the *var must be the last in the list.
Matthew Schinckel
+13  A: 

The Python docs call this Unpacking Argument Lists. It's a pretty handy feature. In Python, you can also use a double asterisk (**) to unpack a dictionary (hash) into keyword arguments. They also work in reverse. I can define a function like this:

def sum(*args):
    result = 0
    for a in args:
        result += a
    return result

sum(1,2)
sum(9,5,7,8)
sum(1.7,2.3,8.9,3.4)

To pack all arguments into an arbitrarily sized list.

sixthgear
I've known about this for awhile, and blindly used it once and awhile but never really understood it. Nice clear and simple explanation.
monkut
+1 "Argument unpacking" is the general term I've always heard for it.
Chuck
the repacking trick works the same in ruby
rampion
Notably, the **kwargs feature has no direct analog in ruby, although it can be almost approximated by having a Hash as the last argument. There are some differences with this, however.
Matthew Schinckel
I wish I could accept multiple answers--credit needs to go also to Matthew Schinckel and Alex Martelli for answering the Ruby side of the question. Thanks to everyone who participated!
+2  A: 

The typical terminology for this is called "applying a function to a list", or "apply" for short.

See http://en.wikipedia.org/wiki/Apply

It has been in LISP since pretty much its inception back in 1960 odd. Glad python rediscovered it :-}

Apply is typically on a list or a representation of a list such as an array. However, one can apply functions to arguments that come from other palces, such as structs. Our PARLANSE language has fixed types (int, float, string, ...) and structures. Oddly enough, a function argument list looks a lot like a structure definintion, and in PARLANSE, it is a structure definition, and you can "apply" a PARLANSE function to a compatible structure. You can "make" structure instances, too, thus:


 (define S
    (structure [t integer]
               [f float]
               [b (array boolean 1 3)]
    )structure
 )define s

  (= A (array boolean 1 3 ~f ~F ~f))

  (= s (make S -3 19.2 (make (array boolean 1 3) ~f ~t ~f))


  (define foo (function string S) ...)

  (foo +17 3e-2 A) ; standard function call

  (foo s) ; here's the "apply"

PARLANSE looks like lisp but isn't.

Ira Baxter
Calling a varargs syntax "applying a function to a list" is just plain wrong, IMO. The reference to PARLANSE doesn't seem to make a contribution either.
ThomasH
@Thomas: OP clearly said, "passes an array to a function for multiple arguments". LIke it or not, that's applying a function to a representation of a list. OP also asked for other languages "with this cool feature"; the PARLANSE example is similar but different and is provided as a contrast.
Ira Baxter
I would argue (like ThomasH) that there is a significant difference between apply, which executes the same function n times on the items of a list, and splat/var-args which calls the function once with the elements of the list as the parameters.
Matthew Schinckel
@Matthew: You are confusing "map" with "apply".See this reference:http://www.n-a-n-o.com/lisp/cmucl-tutorials/LISP-tutorial-20.html
Ira Baxter
Yes, you are correct. I meant map.
Matthew Schinckel
+2  A: 

ruby calls it 'splat', though david black has also come up with the neat "unar{,ra}y operator" (i.e. 'unary unarray operator')

Martin DeMello
+1  A: 

The majority of the questions have already been answered, but as to the question "What is the name of the * operator?": the technical term is "asterisk" (comes from the Latin word asteriscum, meaning "little star", which, in turn, comes from the Greek ἀστερίσκος). Often, though, it will be referred to as "star" or, as stated above, "splat".

JAB
+1 for the laugh, even if it wasn't intended.
nilamo
+1  A: 

Haskell has it too (for pairs), with the uncurry function:

ghci> let f x y = 2*x + y
f :: (Num a) => a -> a -> a
ghci> f 1 2
4
ghci> f 10 3
23
ghci> uncurry f (1,2)
4
ghci> uncurry f (10,3)
23

You can also make it into an operator, so it's more splat-like:

ghci> f `uncurry` (1,2)
4
ghci> let (***) = uncurry
(***) :: (a -> b -> c) -> (a, b) -> c
ghci> f *** (10,3)
23

And though it'd be easy to define similar functions for the 3-tuple, 4-tuple, etc cases, there isn't any general function for n-tuples (like splat works in other languages) because of Haskell's strict typing.

rampion