Спискові вирази () — синтаксична конструкція в деяких мовах програмування, для створення списків застосуванням операцій над уже наявними списками. Вона відповідає математичній нотації побудови множини і замінює використання функцій map та filter.
Опис Розгляньмо наступний приклад запису множини:
Це можна прочитати як, « множина всіх чисел виду „2 на “, де — елемент з множини натуральних чисел (), такий що у квадраті більше, ніж .»
В мові Haskell такий запис множини можна відтворити таким списковим виразом: s = [ 2*x | x <- [1..], x^2 > 3 ]
Тут список [1..] представляє , x^2>3 представляє предикат, а 2*x — вихідний вираз.
Спискові вирази дають результати в означеному порядку (на відміну від членів множини) і можуть ґенерувати елементи за потребою, а не одразу весь список, дозволяючи таким чином, наприклад, попереднє означення членів нескінченної множини.
Історія Мова програмування SETL (кінець 1960-тих) мала інструкції конструювання множин, і система комп'ютерної алґебри AXIOM (1973) мала подібні конструкції, які обробляли потоки, але вперше термін «comprehension» для таких конструкцій був використаний Родом Бурсталом та Джоном Дарлінґтоном в описі мови програмування NPL (1977).
Smalltalk block context messages, якими є спискові вирази, були в цій мові щонайменше з часів Smalltalk-80.
Робота Бурстала та Дарглінґтона з NPL вплинула на багато мов програмування протягом 1980-тих, але не всі з них включали спискові вирази. Винятком була впливова лінива чисто функціональна мова програмування Miranda, випущена в 1985-тому. Розроблена пізніше, теж цілком функціональна мова з лінивими обчисленнями Haskell, увібрала багато особливостей Міранди, включно з списковими виразами. Мова програмування Python теж зазнала сильного впливу лінивих функціональних мов і ввела спискові вирази. Чисті функціональні мови залишаються нішевими, у той час як Python став значно популярнішим і представив спискові вирази ширшій авдиторії.
Спискові вирази пропонувались як нотація запитів до баз данихComprehensions, a query notation for DBPLs і були реалізовані в мові запитів KleisliThe functional guts of the Kleisli query system.
Приклади в різних мовах програмування Далі йтимуть приклади синтаксису спискових виразів у різних мовах програмування: Хоча в оригінальному прикладі використовується нескінченний список, виразити його можуть не всі мови, тому в деяких ми покажемо як використати підмножину замість підмножини .
C# var s = from x in Enumerable.Range(0, 100) where x * x > 3 select x * 2;
чи var s = Enumerable.Range(0, 100).Where(x => x*x > 3).Select(x => x*2);
Ceylon { for (x in 0..100) if ( x**2 > 3) x * 2 }
Clojure Clojure ґенерує нескінченні ліниві послідовності (подібно до Гаскеля, чи ґенераторів Пайтона). Використовуйте take щоб отримати перші N результатів нескінченної послідовности.
(take 20 (for [x (iterate inc 0) :when (> (* x x) 3)] (* 2 x)))
CoffeeScript (x * 2 for x in [0..20] when x*x > 3)
Common Lisp Спискові вирази можуть виражатись за допомогою ключового слова collect макроса loop. Умови виражаються за допомогою if, як показано нижче:
(loop for x from 0 to 100 if (> (* x x) 3) collect (* 2 x))
Нескінченна лінива послідовність може створюватись різними способами, наприклад за допомогою об'єктів CLOS чи макросом yield.
Erlang S = [2*X || X <- lists:seq(0,100), X*X > 3].
F# Вирази мають форму [for x in collection do ... yield expr] для списків та seq {for x in collection do ... yield expr} для послідовностей.
> seq { for x in 0..100 do if x*x > 3 then yield 2*x } ;; val it : seq<int> = seq [4; 6; 8; 10; ...]
Groovy Groovy підтримує вирази для таких колекцій в Java як list, set, map. s = (1..100).grep { it ** 2 > 3 }.collect { it * 2 }
Змінна «it» є скороченням неявного параметра замикання. Наступний код є еквівалентом попереднього s = (1..100).grep { x -> x ** 2 > 3 }.collect { x -> x * 2 }
Haskell s = [ 2*x | x <- [0..], x^2 > 3 ]
Raku my @s = ($_ * 2 if $_ ** 2 > 3 for ^100);
чи:
my @s = gather { for ^100 { take 2 * $_ if $_ ** 2 > 3 } };
PowerShell 0..100 | Where {$_ * $_ -gt 3} | ForEach {$_ * 2}
Python S = [2*x for x in range(101) if x**2 > 3]
Див. також Оператор SELECT в SQL Монади Інші конструкції для обробки послідовностей: Генератор (програмування) map (функція вищого порядку) filter (функція вищого порядку) Інші конструкції програмування, перенесені з математичних форм запису: Варта Зіставлення із взірцем Оператор (програмування)
Посилання
List Comprehension in The Free On-line Dictionary of Computing, Editor Denis Howe.
Haskell The Haskell 98 Report, chapter 3.11 List Comprehensions . The Glorious Glasgow Haskell Compilation System User's Guide, chapter 7.3.4 Parallel List Comprehensions. The Hugs 98 User's Guide, chapter 5.1.2 Parallel list comprehensions (a.k.a. zip-comprehensions).
OCaml OCaml Batteries Included Language extensions introduced in OCaml Batteries Included
Python Python Reference Manual, chapter 5.2.4 List displays. Python Enhancement Proposal PEP 202: List Comprehensions . Python Reference Manual, chapter 5.2.5 Generator expressions. Python Enhancement Proposal PEP 289: Generator Expressions .
Common Lisp Implementation of a Lisp comprehension macro by Guy Lapalme
Clojure Clojure API documentation — for macro
Axiom Axiom stream examples
Решта SQL-подібні оператори над множинами в Python Cookbook Обговорення генераторних списків та пов'язаних конструкцій в Scheme Генераторні списки в різних мовах програмування