Share to: share facebook share twitter share wa share telegram print page

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

Спискові вирази (англ. 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].

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

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

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);
{ for (x in 0..100) if ( x**2 > 3) x * 2 }

Clojure ґенерує нескінченні ліниві послідовності (подібно до Гаскеля, чи ґенераторів Пайтона). Використовуйте take щоб отримати перші N результатів нескінченної послідовности.

(take 20 (for [x (iterate inc 0) :when (> (* x x) 3)] (* 2 x)))
 (x * 2 for x in [0..20] when x*x > 3)

Спискові вирази можуть виражатись за допомогою ключового слова collect макроса loop. Умови виражаються за допомогою if, як показано нижче:

(loop for x from 0 to 100 if (> (* x x) 3) collect (* 2 x))

Нескінченна лінива послідовність може створюватись різними способами, наприклад за допомогою об'єктів CLOS чи макросом yield.

 S = [2*X || X <- lists:seq(0,100), X*X > 3].

Вирази мають форму [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 підтримує вирази для таких колекцій в 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 }
s = [ 2*x | x <- [0..], x^2 > 3 ]
my @s = ($_ * 2 if $_ ** 2 > 3 for ^100);

чи:

my @s = gather { for ^100 { take 2 * $_ if $_ ** 2 > 3 } };
0..100 | Where {$_ * $_ -gt 3} | ForEach {$_ * 2}
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. Архів оригіналу за 29 березня 2008. Процитовано 22 липня 2011.
  • 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

Решта

Kembali kehalaman sebelumnya