Name this python/ruby language construct (using array values to satisfy function parameters)
Asked Answered
E

7

21

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?

Estheresthesia answered 17/7, 2009 at 5:20 Comment(2)
Duplicate #918949Sirmons
@seth: No, not a duplicate. The question you linked to is about the semantics of this operator (in Ruby); this question is about terminology.Bead
R
29

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.

Rowdy answered 17/7, 2009 at 5:44 Comment(4)
I've known about this for awhile, and blindly used it once and awhile but never really understood it. Nice clear and simple explanation.Gape
+1 "Argument unpacking" is the general term I've always heard for it.Acclaim
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.Infantry
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!Estheresthesia
I
10

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.

Infantry answered 17/7, 2009 at 5:26 Comment(5)
The splat operator is the term used in The Ruby Programming Language, which is supposedly co-written by Matz (create of Ruby)Jezabelle
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).Briefing
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.Infantry
@Briefing It does work but I couldn't find it in the documentation, or anywhere but here in that matter. There are also no explanations of why a, *b = (1,2,3) yields b==[2,3] instead of (2,3).Tucci
@Tucci specification is here: python.org/dev/peps/pep-3132 but for the most part it doesn't seem to have made it into the documentation proper, except for a brief mention in the reference manual and in the release notes.Briefing
T
5

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.

Timoshenko answered 17/7, 2009 at 5:48 Comment(4)
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.Bead
@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.Timoshenko
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.Infantry
@Matthew: You are confusing "map" with "apply". See this reference: n-a-n-o.com/lisp/cmucl-tutorials/LISP-tutorial-20.htmlTimoshenko
B
3

Ruby calls it splat, though David Black has also come up with the neat unar{,ra}y operator (i.e. unary unarray operator)

Brickwork answered 17/7, 2009 at 6:16 Comment(0)
H
2

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!-).

Houlberg answered 17/7, 2009 at 5:24 Comment(1)
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.Prescript
C
2

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.

Common answered 17/7, 2009 at 21:31 Comment(0)
M
1

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".

Merth answered 17/7, 2009 at 14:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.