List comprehension

A list comprehension is a syntactic construct available in some programming languages for creating a list based on existing lists. It follows the form of the mathematical set-builder notation (set comprehension) as distinct from the use of map and filter functions.

Overview

Consider the following example in mathematical set-builder notation.

or often

This can be read, " is the set of all numbers "2 times " SUCH THAT is an ELEMENT or MEMBER of the set of natural numbers (), AND squared is greater than ."

The smallest natural number, x = 1, fails to satisfy the condition x2>3 (the condition 12>3 is false) so 2 ·1 is not included in S. The next natural number, 2, does satisfy the condition (22>3) as does every other natural number. Thus x consists of 2, 3, 4, 5... Since the set S consists of all numbers "2 times x" it is given by S = {4, 6, 8, 10,...}. S is, in other words, the set of all even numbers greater than 2.

In this annotated version of the example:

  • is the variable representing members of an input set.
  • represents the input set, which in this example is the set of natural numbers
  • is a predicate expression acting as a filter on members of the input set.
  • is an output expression producing members of the new set from members of the input set that satisfy the predicate expression.
  • braces indicate that the result is a set
  • the vertical bar is read as "SUCH THAT". The bar and the colon ":" are used interchangeably.
  • commas separate the predicates and can be read as "AND".

A list comprehension has the same syntactic components to represent generation of a list in order from an input list or iterator:

  • A variable representing members of an input list.
  • An input list (or iterator).
  • An optional predicate expression.
  • And an output expression producing members of the output list from members of the input iterable that satisfy the predicate.

The order of generation of members of the output list is based on the order of items in the input.

In Haskell's list comprehension syntax, this set-builder construct would be written similarly, as:

s = [ 2*x | x <- [0..], x^2 > 3 ]

Here, the list [0..] represents , x^2>3 represents the predicate, and 2*x represents the output expression.

List comprehensions give results in a defined order (unlike the members of sets); and list comprehensions may generate the members of a list in order, rather than produce the entirety of the list thus allowing, for example, the previous Haskell definition of the members of an infinite list.

History

The existence of related constructs predates the use of the term "List Comprehension". The SETL programming language (1969) has a set formation construct which is similar to list comprehensions. E.g., this code prints all prime numbers from 2 to N:

print([n in [2..N] | forall m in {2..n - 1} | n mod m > 0]);

The computer algebra system AXIOM (1973) has a similar construct that processes streams.

The first use of the term "comprehension" for such constructs was in Rod Burstall and John Darlington's description of their functional programming language NPL from 1977. In his retrospective "Some History of Functional Programming Languages",[1] David Turner recalls:

NPL was implemented in POP2 by Burstall and used for Darlington’s work on program transformation (Burstall & Darlington 1977). The language was first order, strongly (but not polymorphically) typed, purely functional, call-by-value. It also had “set expressions” e.g.

setofeven (X)  <=  <:x : x in X & even(x):>}}

In a footnote attached to the term "list comprehension", Turner also notes

I initially called these ZF expressions, a reference to Zermelo–Fraenkel set theory — it was Phil Wadler who coined the better term list comprehension.

Burstall and Darlington's work with NPL influenced many functional programming languages during the 1980s, but not all included list comprehensions. An exception was Turner's influential, pure, lazy, functional programming language Miranda, released in 1985. The subsequently developed standard pure lazy functional language Haskell includes many of Miranda's features, including list comprehensions.

Comprehensions were proposed as a query notation for databases[2] and were implemented in the Kleisli database query language.[3]

Examples in different programming languages

Similar constructs

Monad comprehension

In Haskell, a monad comprehension is a generalization of the list comprehension to other monads in functional programming.

Set comprehension

The Python language introduces syntax for set comprehensions starting in version 2.7. Similar in form to list comprehensions, set comprehensions generate Python sets instead of lists.

>>> s = {v for v in 'ABCDABCD' if v not in 'CB'}
>>> print(s)
{'A', 'D'}
>>> type(s)
<class 'set'>
>>>

Racket set comprehensions generate Racket sets instead of lists.

(for/set ([v "ABCDABCD"] #:unless (member v (string->list "CB")))
         v))

Dictionary comprehension

The Python language introduced a new syntax for dictionary comprehensions in version 2.7, similar in form to list comprehensions but which generate Python dicts instead of lists.

>>> s = {key: val for key, val in enumerate('ABCD') if val not in 'CB'}
>>> s
{0: 'A', 3: 'D'}
>>>

Racket hash table comprehensions generate Racket hash tables (one implementation of the Racket dictionary type).

(for/hash ([(val key) (in-indexed "ABCD")]
           #:unless (member val (string->list "CB")))
  (values key val))

Parallel list comprehension

The Glasgow Haskell Compiler has an extension called parallel list comprehension (also known as zip-comprehension) that permits multiple independent branches of qualifiers within the list comprehension syntax. Whereas qualifiers separated by commas are dependent ("nested"), qualifier branches separated by pipes are evaluated in parallel (this does not refer to any form of multithreadedness: it merely means that the branches are zipped).

-- regular list comprehension
a = [(x,y) | x <- [1..5], y <- [3..5]]
-- [(1,3),(1,4),(1,5),(2,3),(2,4) ...

-- zipped list comprehension
b = [(x,y) | (x,y) <- zip [1..5] [3..5]]
-- [(1,3),(2,4),(3,5)]

-- parallel list comprehension
c = [(x,y) | x <- [1..5] | y <- [3..5]]
-- [(1,3),(2,4),(3,5)]

Racket's comprehensions standard library contains parallel and nested versions of its comprehensions, distinguished by "for" vs "for*" in the name. For example, the vector comprehensions "for/vector" and "for*/vector" create vectors by parallel versus nested iteration over sequences. The following is Racket code for the Haskell list comprehension examples.

> (for*/list ([x (in-range 1 6)] [y (in-range 3 6)]) (list x y))
'((1 3) (1 4) (1 5) (2 3) (2 4) (2 5) (3 3) (3 4) (3 5) (4 3) (4 4) (4 5) (5 3) (5 4) (5 5))
> (for/list ([x (in-range 1 6)] [y (in-range 3 6)]) (list x y))
'((1 3) (2 4) (3 5))

In Python, we could do as follows:

>>> # regular list comprehension
>>> a = [(x, y) for x in range(1, 6) for y in range(3, 6)]
[(1, 3), (1, 4), (1, 5), (2, 3), (2, 4), ...
>>>
>>> # parallel/zipped list comprehension
>>> b = [x for x in zip(range(1, 6), range(3, 6))]
[(1, 3), (2, 4), (3, 5)]

In Julia, practically the same results can be achieved as follows:

# regular array comprehension
>>> a = [(x, y) for x in 1:5 for y in 3:5]

# parallel/zipped array comprehension
>>> b = [x for x in zip(1:3, 3:5)]

with the only difference that instead of lists, in Julia, we have arrays.

XQuery and XPath

Like the original NPL use, these are fundamentally database access languages.

This makes the comprehension concept more important, because it is computationally infeasible to retrieve the entire list and operate on it (the initial 'entire list' may be an entire XML database).

In XPath, the expression:

/library/book//paragraph[@style='first-in-chapter']

is conceptually evaluated as a series of "steps" where each step produces a list and the next step applies a filter function to each element in the previous step's output.[4]

In XQuery, full XPath is available, but FLWOR statements are also used, which is a more powerful comprehension construct.[5]

for $b in //book
where $b[@pages < 400]
order by $b//title
return
  <shortBook>
    <title>{$b//title}</title>
    <firstPara>{($book//paragraph)[1]}</firstPara>
  </shortBook>

Here the XPath //book is evaluated to create a sequence (aka list); the where clause is a functional "filter", the order by sorts the result, and the <shortBook>...</shortBook> XML snippet is actually an anonymous function that builds/transforms XML for each element in the sequence using the 'map' approach found in other functional languages.

So, in another functional language the above FLWOR statement may be implemented like this:

map(
  newXML(shortBook, newXML(title, $1.title), newXML(firstPara, $1...))
  filter(
    lt($1.pages, 400),
    xpath(//book)
  )
)

LINQ in C#

C# 3.0 has a group of related features called LINQ, which defines a set of query operators for manipulating object enumerations.

var s = Enumerable.Range(0, 100).Where(x => x * x > 3).Select(x => x * 2);

It also offers an alternative comprehension syntax, reminiscent of SQL:

var s = from x in Enumerable.Range(0, 100) where x * x > 3 select x * 2;

LINQ provides a capability over typical list comprehension implementations. When the root object of the comprehension implements the IQueryable interface, rather than just executing the chained methods of the comprehension, the entire sequence of commands are converted into an abstract syntax tree (AST) object, which is passed to the IQueryable object to interpret and execute.

This allows, amongst other things, for the IQueryable to

  • rewrite an incompatible or inefficient comprehension
  • translate the AST into another query language (e.g. SQL) for execution

C++

C++ does not have any language features directly supporting list comprehensions but operator overloading (e.g., overloading |, >>, >>=) has been used successfully to provide expressive syntax for "embedded" query domain-specific languages (DSL). Alternatively, list comprehensions can be constructed using the erase-remove idiom to select elements in a container and the STL algorithm for_each to transform them.

#include <algorithm>
#include <list>
#include <numeric>

using namespace std;

template<class C, class P, class T>
C comprehend(C&& source, const P& predicate, const T& transformation)
{
  // initialize destination
  C d = forward<C>(source);

  // filter elements
  d.erase(remove_if(begin(d), end(d), predicate), end(d));

  // apply transformation
  for_each(begin(d), end(d), transformation);

  return d;
}

int main()
{
  list<int> range(10);
      // range is a list of 10 elements, all zero
  iota(begin(range), end(range), 1);
      // range now contains 1, 2, ..., 10

  list<int> result = comprehend(
      range,
      [](int x) { return x * x <= 3; },
      [](int &x) { x *= 2; });
      // result now contains 4, 6, ..., 20
}

There is some effort in providing C++ with list-comprehension constructs/syntax similar to the set builder notation.

  • In Boost. Range [1] library there is a notion of adaptors [2] that can be applied to any range and do filtering, transformation etc. With this library, the original Haskell example would look like (using Boost.Lambda [3] for anonymous filtering and transforming functions) (Full example):
    counting_range(1,10) | filtered( _1*_1 > 3 ) | transformed(ret<int>( _1*2 ))
    
  • This[6] implementation uses a macro and overloads the << operator. It evaluates any expression valid inside an 'if', and any variable name may be chosen. It's not threadsafe, however. Usage example:
list<int> N;
list<double> S;

for (int i = 0; i < 10; i++)
    N.push_back(i);

S << list_comprehension(3.1415 * x, x, N, x * x > 3)
  • This[7] implementation provides head/tail slicing using classes and operator overloading, and the | operator for filtering lists (using functions). Usage example:
bool even(int x) { return x % 2 == 0; }
bool x2(int &x) { x *= 2; return true; }

list<int> l, t;
int x, y;

for (int i = 0; i < 10; i++)
     l.push_back(i);

(x, t) = l | x2;
(t, y) = t;

t = l < 9;
t = t < 7 | even | x2;
  • Language for Embedded Query and Traversal (LEESA[8]) is an embedded DSL in C++ that implements X-Path-like queries using operator overloading. The queries are executed on richly typed xml trees obtained using xml-to-c++ binding from an XSD. There is absolutely no string encoding. Even the names of the xml tags are classes and therefore, there is no way for typos. If a LEESA expression forms an incorrect path that does not exist in the data model, the C++ compiler will reject the code.
    Consider a catalog xml.
<catalog>
  <book>
    <title>Hamlet</title>
    <price>9.99</price>
    <author>
      <name>William Shakespeare</name>
      <country>England</country>
    </author>
  </book>
  <book>...</book>
...
</catalog>

LEESA provides >> for XPath's / separator. XPath's // separator that "skips" intermediate nodes in the tree is implemented in LEESA using what's known as Strategic Programming. In the example below, catalog_, book_, author_, and name_ are instances of catalog, book, author, and name classes, respectively.

// Equivalent X-Path: "catalog/book/author/name"
std::vector<name> author_names = 
evaluate(root, catalog_ >> book_ >> author_ >> name_);

// Equivalent X-Path: "catalog//name"
std::vector<name> author_names = 
evaluate(root, catalog_ >> DescendantsOf(catalog_, name_));

// Equivalent X-Path: "catalog//author[country=="England"]"
std::vector<name> author_names = 
evaluate(root, catalog_  >> DescendantsOf(catalog_, author_)
                         >> Select(author_, [](const author & a) { return a.country() == "England"; })
                         >> name_);

See also

Notes and references

  1. ^ Turner, David (2012). "Some history of functional programming languages" (PDF). International Symposium on Trends in Functional Programming, Springer, Berlin, Heidelberg. pp. 1–20.
  2. ^ Comprehensions, a query notation for DBPLs
  3. ^ The functional guts of the Kleisli query system
  4. ^ "2.1 Location Steps". XML Path Language (XPath). W3C. 16 November 1999. Archived from the original on 9 December 2012. Retrieved 24 December 2008.
  5. ^ "XQuery FLWOR Expressions". W3Schools. Archived from the original on 2011-10-08.
  6. ^ "Single-variable List Comprehension in C++ using Preprocessor Macros". Archived from the original on 2011-08-21. Retrieved 2011-01-09.
  7. ^ "C++ list comprehensions". Archived from the original on 2017-07-07. Retrieved 2011-01-09.
  8. ^ "Language for Embedded Query and Traversal (LEESA)".
  • List Comprehension in The Free On-line Dictionary of Computing, Editor Denis Howe.
  • Wadler, Philip (1990). "Comprehending Monads". Proceedings of the 1990 ACM Conference on LISP and Functional Programming, Nice.

Axiom

Clojure

Common Lisp

Haskell

OCaml

Python

Read other articles:

Joey Barton Joey Barton (2015)Informasi pribadiNama lengkap Joseph Anthony BartonTanggal lahir 2 September 1982 (umur 41)Tempat lahir Huyton, Merseyside, InggrisTinggi 1,80 m (5 ft 11 in)[1]Posisi bermain GelandangInformasi klubKlub saat ini BurnleyNomor 19Karier junior Everton1997–2002 Manchester CityKarier senior*Tahun Tim Tampil (Gol)2002–2007 Manchester City 130 (15)2007–2011 Newcastle United 81 (7)2011–2015 Queens Park Rangers 93 (7)2012–2013 → Ma...

 

Hiller YH-32 Hornet (perusahaan penunjukan HJ-1) adalah sebuah helikopter ultralight Amerika dibangun oleh Hiller Aircraft di awal 1950-an. Itu adalah desain yang kecil dan unik karena didukung oleh dua mesin ramjet Hiller 8RJ2B dipasang pada ujung pisau rotor yang beratnya masing-masing £13 dan memberikan setara dengan 45 hp untuk total 90 h.p. Versi dari HJ-1 Hornet dibangun untuk Angkatan Darat Amerika Serikat dan Angkatan Laut Amerika Serikat pada awal 1950-an. Hiller Museum mengidentif...

 

الرماية في الألعاب الأولمبية الصيفيةالهيئة الإداريةالاتحاد الدولي لرياضة الرمايةالمنافسات15 (رجال: 9; سيدات: 6)الألعاب 1896 1900 1904 1908 1912 1920 1924 1928 1932 1936 1948 1952 1956 1960 1964 1968 1972 1976 1980 1984 1988 1992 1996 2000 2004 2008 2012 2016 2020 قائمة الفائزين بالميداليات أدرجت الرماية في كل الألعاب الأولمبية الصيفية ...

Westinghouse Works1904 film Westinghouse Works CinematographyG. W. BitzerProductioncompanyAmerican Mutoscope and Biograph CompanyRelease date1904 Westinghouse Works, 1904 is a collection of American short silent films, each averaging about three minutes in length. The films were taken from April 18, 1904, to May 16, 1904, in Pittsburgh, Pennsylvania, and document various Westinghouse manufacturing plants.[1] They were made by G. W. Billy Bitzer of the American Mutoscope and Biograph C...

 

Gold ring discovered in Hampshire, England, in 1785 The Vyne Ring is a Roman gold ring of around the 4th century. The Vyne Ring or the Ring of Silvianus is a gold ring, dating probably from the 4th century AD, discovered in a ploughed field near Silchester, in Hampshire, England, in 1785. Originally the property of a British Roman called Silvianus, it was apparently stolen by a person named Senicianus, upon whom Silvianus called down a curse. After its discovery in the 18th century, the ring...

 

Vasilij Nikolaevič GordovNascitaMatveevka, 12 dicembre 1896 MorteMosca, 24 agosto 1950 Cause della mortecondanna a morte Dati militariPaese servito Impero russo RSFS Russa Unione Sovietica Forza armata Esercito imperiale russo Esercito sovietico Anni di servizio1915-1947 GradoColonnello generale GuerrePrima guerra mondiale Guerra civile russa Guerra d'inverno Seconda guerra mondiale CampagneOperazione Fischreiher BattaglieBattaglia di Smolensk Battaglia di Kiev Battaglia di Stal...

American fast food chain Wetson'sIndustryFast-food restaurantsFounded1959; 65 years ago (1959)FounderHerbert WetansonDefunct1975; 49 years ago (1975)FateClosedSuccessorDallas BBQHeadquartersNew York, California, U.SNumber of locations~70 (at its peak)ProductsHamburgers Wetson's was an American fast food hamburger chain that existed from 1959 to 1975. At its peak, Wetson's had approximately 70 locations in the greater New York metropolitan area. Wetson's was...

 

For other uses, see Victoria Avenue (disambiguation). Victoria Avenue, Mountain access road Victoria Avenue is a Lower City arterial road in Hamilton, Ontario, Canada. It starts off as a ramp and part of a Mountain-access road, the Claremont Access, on Hunter Street East in the Stinson neighbourhood. It's also a one-way thoroughfare that flows north through the Landsdale and the city's North End industrial neighbourhood past Burlington Street East where it ends at Pier 11. History Victoria Av...

 

周處除三害The Pig, The Snake and The Pigeon正式版海報基本资料导演黃精甫监制李烈黃江豐動作指導洪昰顥编剧黃精甫主演阮經天袁富華陳以文王淨李李仁謝瓊煖配乐盧律銘林孝親林思妤保卜摄影王金城剪辑黃精甫林雍益制片商一種態度電影股份有限公司片长134分鐘产地 臺灣语言國語粵語台語上映及发行上映日期 2023年10月6日 (2023-10-06)(台灣) 2023年11月2日 (2023-11-02)(香�...

周處除三害The Pig, The Snake and The Pigeon正式版海報基本资料导演黃精甫监制李烈黃江豐動作指導洪昰顥编剧黃精甫主演阮經天袁富華陳以文王淨李李仁謝瓊煖配乐盧律銘林孝親林思妤保卜摄影王金城剪辑黃精甫林雍益制片商一種態度電影股份有限公司片长134分鐘产地 臺灣语言國語粵語台語上映及发行上映日期 2023年10月6日 (2023-10-06)(台灣) 2023年11月2日 (2023-11-02)(香�...

 

Battle in 1184 in Japan Battle of KojimaPart of the Genpei WarUkiyo-e depiction of the Battle of FujitoDate1184LocationKojima, on the coast of the Seto Inland Sea34°33′21.5″N 133°47′58.7″E / 34.555972°N 133.799639°E / 34.555972; 133.799639Result Minamoto victoryBelligerents  Minamoto clan  Taira clanCommanders and leaders Minamoto no Noriyori Sasaki Moritsuna Taira no Yukimoriclass=notpageimage| Location within Japan vteGenpei War 1st Uji Nara Ish...

 

Irine Yusiana Roba Putri Anggota Dewan Perwakilan RakyatPetahanaMulai menjabat 1 Oktober 2014Daerah pemilihanMaluku Utara Informasi pribadiLahir4 April 1984 (umur 40)Yogyakarta, IndonesiaPartai politikPDI-PSuami/istriGoenawan AdinugrohoAlma materUniversitas Atma Jaya YogyakartaUniversitas MonashPekerjaanPolitikusSunting kotak info • L • B Irine Yusiana Roba Putri, S.Sos., M.Comn&MediaST. (lahir 4 April 1984) adalah seorang politikus Indonesia. Saat ini ia menjabat s...

Hunter BidenBiden di Center for Strategic & International Studies pada 2013 Wakil Ketua National Railroad Passenger CorporationMasa jabatan26 Juli 2006 – 29 Januari 2009PresidenGeorge W. BushBarack ObamaPenggantiDonna McLean Informasi pribadiLahirRobert Hunter Biden4 Februari 1970 (umur 54)Wilmington, Delaware, Amerika SerikatPartai politikPartai DemokratSuami/istriKathleen Buhle ​ ​(m. 1993; bercerai 2017)​ Melissa Cohen ...

 

صاحب السمو الأمير سعد الأول بن عبد الرحمن بن فيصل آل سعود معلومات شخصية تاريخ الميلاد 1890 الوفاة 1915 (25 سنة)كنزان، الأحساء، المملكة العربية السعودية سبب الوفاة قتل في معركة كنزان الإقامة الرياض، المملكة العربية السعودية الجنسية  السعودية الأولاد فهد الثاني بن سعد الأول ب...

 

Political party in the European Union Movement for European Reform Bewegung für europäische ReformMouvement pour la réforme européenneMovimento per la riforma europeaMovimiento para la reforma europeaPresidentNone appointedFounded13 July 2006 (2006-07-13)Dissolved1 October 2009 (2009-10-01)Succeeded byAlliance of European Conservatives and ReformistsHeadquarters25 Victoria Street, London SW1H 0DLIdeologyConservatismEconomic liberalismAtlanticismSoft...

Roman Catholic church in Vilnius, Lithuania St. Anne's Church Šv. Onos bažnyčiaFaçade of Saint Anne's (2014)ReligionAffiliationRoman CatholicDistrictOld TownYear consecrated1500LocationLocationVilnius, LithuaniaGeographic coordinates54°40′59″N 25°17′36″E / 54.68306°N 25.29333°E / 54.68306; 25.29333ArchitectureArchitect(s)Michael EnkingerTypeChurchStyleLate Gothic and Brick GothicCompleted1500SpecificationsDirection of façadeWestMaterialsclay bricksWebs...

 

HaryatmokoInformasi pribadiNama lahirHaryatmokoLahir9 Maret 1959 (umur 65)Sleman[1]KewarganegaraanIndonesia R.P. Dr. Johanes Haryatmoko, SJ (lahir 9 Maret 1959) adalah seorang pastor Katolik dan dosen di beberapa universitas terkemuka di Indonesia. Di samping sebagai dosen tetap Universitas Sanata Dharma (Yogayakarta), Haryatmoko adalah pengajar tamu di pasca-sarjana Universitas Indonesia (Jakarta), Universitas Gadjah Mada (Yogyakarta) dan Universitas Islam Negeri Sunan Kalijaga ...

 

Bilateral relationsBolivia-Yugoslavia relations Bolivia Yugoslavia Bolivia and Yugoslavia Bolivian-Yugoslav meeting in Cochabamba in 1963. Bolivia–Yugoslavia relations were historical foreign relations between Bolivia and now split-up Socialist Federal Republic of Yugoslavia. Relations were established and developed in the context of Yugoslav Non-Aligned policy during the Cold War in which Yugoslavia cooperated with countries both outside Eastern and Western Bloc. Bolivia was one of destina...

  لمعانٍ أخرى، طالع بايرون (توضيح). بايرون   الإحداثيات 43°04′47″N 78°03′50″W / 43.079722222222°N 78.063888888889°W / 43.079722222222; -78.063888888889   [1] تقسيم إداري  البلد الولايات المتحدة[2][3]  التقسيم الأعلى مقاطعة جينيسي  خصائص جغرافية  المساحة 32.29 ميل مربع ...

 

Area of Kingston upon Hull, East Riding of Yorkshire, England Human settlement in EnglandDrypoolHousing at Victoria DockDrypoolLocation within the East Riding of YorkshirePopulation12,500 OS grid referenceTA106286• London155 mi (249 km) SUnitary authorityKingston upon HullCeremonial countyEast Riding of YorkshireRegionYorkshire and the HumberCountryEnglandSovereign stateUnited KingdomPost townHULLPostcode districtHU8 & HU9Dialling&#...