Спискові вирази

Генераторні списки (англ. list comprehension) — синтаксична конструкція доступна в деяких мовах програмування, яка призначена для створення списків застосуванням операцій над існуючими списками. Вона відповідає математичній нотації побудови множини і замінює використання функцій 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 став значно популярнішим і представив генераторні списки ширшій аудиторії.

Генераторні списки пропонувались як нотація запитів до баз даних[1] і були реалізовані в мові запитів Kleisli.[2]

Приклади в різних мовах програмування

Далі йтимуть приклади синтаксису генераторних списків в різних мовах програмування:

Хоча в оригінальному прикладі використовується нескінченний список, виразити його можуть не всі мови, тому в деяких ми покажемо як використати підмножину замість підмножини .

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 ]

Perl 6

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]



Дивись також

Посилання

  • List Comprehension in The Free On-line Dictionary of Computing, Editor Denis Howe.
  • Trinder, Phil (1992). Comprehensions, a query notation for DBPLs. Proceedings of the third international workshop on Database programming languages: bulk types & persistent data, Nafplion, Greece. с. 55–68.
  • Wadler, Philip (1990). Comprehending Monads. Proceedings of the 1990 ACM Conference on LISP and Functional Programming, Nice.
  • Wong, Limsoon (2000). The Functional Guts of the Kleisli Query System. Proceedings of the fifth ACM SIGPLAN international conference on Functional programming International Conference on Functional Programming. с. 1–10.

Haskell

OCaml

Python

Common Lisp

Clojure

Axiom

Решта

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.