stringtranslate.com

Фьючерсы и обещания

В информатике будущее , обещание , задержка и отложенное относятся к конструкциям, используемым для синхронизации выполнения программы в некоторых параллельных языках программирования . Они описывают объект, который действует как прокси для результата, который изначально неизвестен, обычно потому, что вычисление его значения еще не завершено.

Термин «обещание» был предложен в 1976 году Дэниелом П. Фридманом и Дэвидом Уайзом [1] , а Питер Хиббард назвал его возможным . [2] Несколько похожая концепция будущего была представлена ​​в 1977 году в статье Генри Бейкера и Карла Хьюитта . [3]

Термины будущее , обещание , задержка и отсрочка часто используются как взаимозаменяемые, хотя некоторые различия в использовании между будущим и обещанием рассматриваются ниже. В частности, если различать использование, будущее представляет собой представление переменной, доступное только для чтения , а обещание — это записываемый контейнер с одним назначением , который устанавливает значение будущего. Примечательно, что будущее может быть определено без указания того, какое конкретное обещание будет устанавливать его значение, а различные возможные обещания могут устанавливать значение данного будущего, хотя это можно сделать только один раз для данного будущего. В других случаях будущее и обещание создаются вместе и связываются друг с другом: будущее — это значение, обещание — это функция, которая устанавливает значение — по сути, возвращаемое значение (будущее) асинхронной функции (промиса). Установка значения будущего также называется его разрешением , выполнением или связыванием .

Приложения

Фьючерсы и обещания возникли в функциональном программировании и связанных с ним парадигмах (таких как логическое программирование ) для отделения значения (будущего) от того, как оно было вычислено (обещание), что позволяет выполнять вычисления более гибко, в частности, путем их распараллеливания. Позже он нашел применение в распределенных вычислениях , для уменьшения задержки при передаче туда и обратно. Еще позже он получил большее распространение, позволив писать асинхронные программы в прямом стиле , а не в стиле передачи продолжения .

Неявное и явное

Использование фьючерсов может быть неявным (любое использование фьючерса автоматически получает его значение, как если бы это была обычная ссылка ) или явным (пользователь должен вызвать функцию для получения значения, например метод getв java.util.concurrent.FutureJava ) . Получение ценности явного будущего можно назвать уколом или принуждением . Явные фьючерсы могут быть реализованы в виде библиотеки, тогда как неявные фьючерсы обычно реализуются как часть языка.

В оригинальной статье Бейкера и Хьюитта описывались неявные фьючерсы, которые естественным образом поддерживаются в актерской модели вычислений и в чисто объектно-ориентированных языках программирования, таких как Smalltalk . В статье Фридмана и Уайза описаны только явные фьючерсы, что, вероятно, отражает сложность эффективной реализации неявных фьючерсов на стандартном оборудовании. Трудность заключается в том, что стандартное оборудование не поддерживает фьючерсы для примитивных типов данных, таких как целые числа. Например, инструкция добавления не знает, как обращаться с . В чистых актерских или объектных языках эту проблему можно решить, отправив сообщение , которое просит будущее добавить к себе и вернуть результат. Обратите внимание, что подход с передачей сообщений работает независимо от того, когда завершаются вычисления, и что никаких дополнительных/принудительных действий не требуется.3 + future factorial(100000)future factorial(100000)+[3]3factorial(100000)

Конвейерная обработка обещаний

Использование фьючерсов может значительно снизить задержку в распределенных системах . Например, фьючерсы позволяют использовать конвейерную обработку обещаний , [4] [5] , реализованную в языках E и Joule , которая также называлась потоком вызовов [6] на языке Argus .

Рассмотрим выражение, включающее обычные вызовы удаленных процедур , например:

t3 := ( xa() ).c( yb() )

который можно было бы расширить до

т1 := ха(); т2 := yb(); т3 := t1.c(t2);

Перед выполнением следующего запроса каждому оператору необходимо отправить сообщение и получить ответ. Предположим, например, что x, y, t1и t2все расположены на одной и той же удаленной машине. В этом случае должны произойти два полных сетевых обращения к этой машине, прежде чем третий оператор сможет начать выполняться. Третий оператор затем вызовет еще один возврат к той же удаленной машине.

Используя фьючерсы, приведенное выше выражение можно записать

t3 := (x <- a()) <- c(y <- b())

который можно было бы расширить до

t1 := x <- a(); t2 := y <- b(); t3 := t1 <- c(t2);

Используемый здесь синтаксис соответствует синтаксису языка E, где означает асинхронную x <- a()отправку сообщения в . Всем трем переменным немедленно присваиваются фьючерсы на их результаты, и выполнение переходит к последующим операторам. Более поздние попытки определить значение могут вызвать задержку; однако конвейеризация может сократить количество необходимых обращений туда и обратно. Если, как в предыдущем примере, , , и все расположены на одном и том же удаленном компьютере, конвейерная реализация может выполнять вычисления за один проход туда и обратно вместо трех. Поскольку все три сообщения предназначены для объектов, находящихся на одном и том же удаленном компьютере, необходимо отправить только один запрос и получить только один ответ, содержащий результат. Отправка не блокировалась бы, даже если бы и находились на разных машинах друг к другу, или к или к .a()xt3xyt1t2t3t1 <- c(t2)t1t2xy

Конвейерную обработку обещаний следует отличать от параллельной асинхронной передачи сообщений. В системе, поддерживающей параллельную передачу сообщений, но не конвейерную обработку, сообщение отправляется x <- a()и y <- b()в приведенном выше примере может происходить параллельно, но отправка t1 <- c(t2)должна будет ждать, пока оба t1и t2не будут получены, даже если x, y, t1, и t2находятся на одном и том же удаленном компьютере. машина. Преимущество конвейерной обработки в относительной задержке становится еще больше в более сложных ситуациях, включающих большое количество сообщений.

Конвейерную обработку обещаний также не следует путать с конвейерной обработкой сообщений в системах актеров, где актер может указать и начать выполнение поведения для следующего сообщения до завершения обработки текущего сообщения.

Представления только для чтения

В некоторых языках программирования, таких как Oz , E и AmbientTalk , можно получить доступное только для чтения представление будущего, которое позволяет читать его значение при разрешении, но не позволяет его разрешить:

Поддержка представлений только для чтения соответствует принципу наименьших привилегий , поскольку позволяет устанавливать значение только для субъектов , которым необходимо его установить. В системе, которая также поддерживает конвейерную обработку, отправитель асинхронного сообщения (с результатом) получает обещание результата только для чтения, а цель сообщения получает преобразователь.

Специфические фьючерсы

Некоторые языки, такие как Alice ML , определяют фьючерсы, связанные с определенным потоком, который вычисляет значение фьючерса. [9] Эти вычисления могут начинаться либо сразу , когда создается будущее, либо лениво, когда его значение впервые требуется. Ленивое будущее похоже на thunk в смысле отложенного вычисления.

Алиса ML также поддерживает фьючерсы, которые могут быть разрешены любым потоком, и называет эти обещания . [8] Такое использование обещания отличается от его использования в E, как описано выше. В Алисе обещание не доступно только для чтения, а конвейеризация обещаний не поддерживается. Вместо этого конвейеризация естественным образом происходит для фьючерсов, в том числе связанных с обещаниями.

Блокирующая и неблокирующая семантика

Если доступ к значению будущего осуществляется асинхронно, например, путем отправки ему сообщения или явного ожидания его с помощью конструкции, такой как whenв E, то нет никаких трудностей с отсрочкой до тех пор, пока будущее не будет решено, прежде чем сообщение может быть отправлено. получено или ожидание завершается. Это единственный случай, который следует учитывать в чисто асинхронных системах, таких как чистые языки актеров.

Однако в некоторых системах также можно попытаться немедленно или синхронно получить доступ к значению будущего времени. Далее предстоит сделать выбор дизайна:

В качестве примера первой возможности в C++11 поток, которому нужно значение будущего, может блокироваться до тех пор, пока оно не станет доступным, вызвав функции- члены wait()или get(). Вы также можете указать тайм-аут ожидания с помощью функций-членов wait_for()или wait_until(), чтобы избежать неопределенной блокировки. Если будущее возникло в результате вызова then, то std::asyncожидание блокировки (без таймаута) может привести к синхронному вызову функции для вычисления результата в ожидающем потоке.

Связанные конструкции

Фьючерсы — это частный случай примитива синхронизации « событий », который может быть завершен только один раз. В общем, события можно сбрасывать в исходное пустое состояние и, таким образом, выполнять сколько угодно раз. [11]

I -var (как и в языке Id ) — это будущее с семантикой блокировки, как определено выше. I -структура — это структура данных , содержащая I-переменные. Связанная конструкция синхронизации, которую можно устанавливать несколько раз с разными значениями, называется M-var . M-переменные поддерживают атомарные операции по получению или помещению текущего значения, при этом принятие значения также возвращает M-var в исходное пустое состояние. [12]

Параллельная логическая переменная [ нужна цитация ] похожа на фьючерсную, но обновляется путем унификации , точно так же, как логические переменные в логическом программировании . Таким образом, его можно привязать к унифицированным значениям более одного раза, но нельзя вернуть в пустое или неразрешенное состояние. Переменные потока данных Oz действуют как переменные параллельной логики, а также имеют семантику блокировки, как упоминалось выше.

Переменная параллельного ограничения — это обобщение переменных параллельной логики для поддержки программирования логики ограничений : ограничение можно сужать несколько раз, указывая меньшие наборы возможных значений. Обычно существует способ указать преобразователь, который должен запускаться всякий раз, когда ограничение еще больше сужается; это необходимо для поддержки распространения ограничений .

Отношения между выраженностью разных форм будущего

Eager фьючерсы, специфичные для потока, могут быть напрямую реализованы в фьючерсах, не специфичных для потока, путем создания потока для вычисления значения одновременно с созданием будущего. В этом случае желательно вернуть клиенту представление только для чтения, чтобы только вновь созданный поток мог разрешить это будущее.

Для реализации неявных ленивых фьючерсов, специфичных для потока (как, например, предоставлено Алисой МЛ) в терминах фьючерсов, не специфичных для потока, необходим механизм, определяющий, когда в первую очередь требуется значение фьючерса (например, конструкция WaitNeededв Oz [13] ] ). Если все значения являются объектами, то возможности реализовать прозрачные объекты пересылки достаточно, поскольку первое сообщение, отправленное в пересылку, указывает на то, что требуется будущее значение.

Неспецифические для потока фьючерсы могут быть реализованы в фьючерсах, специфичных для потока, при условии, что система поддерживает передачу сообщений, заставляя разрешающий поток отправлять сообщение собственному потоку будущего. Однако это можно рассматривать как ненужную сложность. В языках программирования, основанных на потоках, наиболее выразительным подходом, по-видимому, является обеспечение сочетания фьючерсов, не связанных с потоками, представлений только для чтения и либо конструкции WaitNeeded , либо поддержки прозрачной пересылки.

Стратегия оценки

Стратегия оценки фьючерсов, которую можно назвать вызовом будущего , недетерминирована: стоимость фьючерса будет оценена в какой-то момент между созданием фьючерса и моментом использования его значения, но точное время не определено. заранее и может меняться от запуска к запуску. Вычисление может начаться сразу после создания будущего ( активная оценка ) или только тогда, когда значение действительно необходимо ( ленивая оценка ), и может быть приостановлено на полпути или выполнено за один прогон. Как только значение будущего присвоено, оно не пересчитывается при будущих обращениях; это похоже на мемоизацию , используемую при вызове по необходимости .

Аленивое будущее — это будущее, которое детерминированно имеет семантику ленивых вычислений: вычисление значения будущего начинается, когда это значение впервые необходимо, как при вызове по необходимости. Ленивые будущие значения используются в языках, стратегия оценки которых по умолчанию не является ленивой. Например, вC++11такие ленивые фьючерсы можно создать, передавstd::launch::deferredполитику запуска вstd::async, а также функцию для вычисления значения.

Семантика будущего в модели актора

В модели актера выражение формы future <Expression>определяется тем, как оно реагирует на Evalсообщение со средой E и клиентом C следующим образом: Выражение будущего отвечает на Evalсообщение, отправляя клиенту C вновь созданного актера F (прокси для ответ оценки <Expression>) в качестве возвращаемого значения одновременно с отправкой <Expression>сообщения Evalсреде E и клиенту C. Поведение F по умолчанию следующее:

Однако некоторые фьючерсы могут обрабатывать запросы особым образом, чтобы обеспечить больший параллелизм. Например, выражение 1 + future factorial(n)может создать новое будущее, которое будет вести себя как число 1+factorial(n). Этот трюк не всегда срабатывает. Например, следующее условное выражение:

if m>future factorial(n) then print("bigger") else print("smaller")

приостанавливается до тех пор, пока будущее factorial(n)не ответит на запрос, mбольше ли оно самого себя.

История

Конструкции будущего и/или обещания были впервые реализованы в таких языках программирования , как MultiLisp и Act 1 . Использование логических переменных для связи в языках программирования параллельной логики очень похоже на фьючерсы. Они начались в Прологе с Freeze и IC Prolog и стали настоящим примитивом параллелизма с Relational Language, Concurrent Prolog , защищенными предложениями Horn (GHC), Parlog , Strand , Vulcan , Janus , Oz-Mozart , Flow Java и Alice ML . I-var с одним присвоением из языков программирования потоков данных , происходящий из Id и включенный в Concurrent ML Reppy , во многом похож на переменную параллельной логики.

Техника конвейеризации обещаний (использование фьючерсов для преодоления задержки) была изобретена Барбарой Лисков и Любой Шрирой в 1988 году [6] и независимо Марком С. Миллером , Дином Трибблом и Робом Джеллингхаусом в контексте проекта «Занаду» примерно в 1989 году . [14]

Термин обещание был придуман Лисковым и Шрирой, хотя они ссылались на механизм конвейерной обработки под названием call-stream , которое сейчас используется редко.

Как дизайн, описанный в статье Лискова и Шриры, так и реализация конвейерной обработки обещаний в Xanadu, имели ограничение, заключающееся в том, что значения обещаний не были первоклассными : аргумент или значение, возвращаемое вызовом или отправкой, не могли напрямую быть обещанием. (поэтому приведенный ранее пример конвейерной обработки обещаний, в котором обещание для результата одной отправки используется в качестве аргумента для другой, не мог быть напрямую выражен в конструкции потока вызовов или в реализации Xanadu). Похоже, что промисы и потоки вызовов никогда не были реализованы ни в одной общедоступной версии Argus, [15] языка программирования, используемого в статье Лискова и Шриры. Разработка Argus прекратилась примерно в 1988 году. [16] Реализация конвейерной обработки обещаний в Xanadu стала общедоступной только с выпуском исходного кода Udanax Gold [17] в 1999 году и никогда не объяснялась ни в одном опубликованном документе. [18] Более поздние реализации в Joule и E полностью поддерживают первоклассные промисы и преобразователи.

Несколько ранних языков актеров, включая серию Act, [19] [20] поддерживали как параллельную передачу сообщений, так и конвейерную обработку сообщений, но не конвейерную обработку обещаний. (Хотя технически возможно реализовать последнюю из этих функций в первых двух, нет никаких доказательств того, что языки Закона сделали это.)

После 2000 года произошло значительное возрождение интереса к фьючерсам и обещаниям из-за их использования в отзывчивости пользовательских интерфейсов, а также в веб-разработке из-за модели передачи сообщений « запрос-ответ ». В нескольких основных языках теперь есть языковая поддержка фьючерсов и обещаний, наиболее популяризированная FutureTaskв Java 5 (анонсировано в 2004 г.) [21] и конструкциях async/await в .NET 4.5 (анонсировано в 2010 г., выпущено в 2012 г.) [22] [23] в основном вдохновлен асинхронными рабочими процессами F#, [24] появившимися в 2007 году. [25] Впоследствии это было принято другими языками, в частности Dart (2014), [26] Python (2015), [27] Hack (HHVM), и проекты ECMAScript 7 (JavaScript), Scala и C++ (2011 г.).

Список реализаций

Некоторые языки программирования поддерживают фьючерсы, обещания, переменные параллельной логики, переменные потока данных или I-вары либо посредством прямой поддержки языка, либо в стандартной библиотеке.

Список концепций, связанных с будущим и обещаниями, по языкам программирования

Языки, также поддерживающие конвейеризацию обещаний, включают:

Список нестандартных реализаций фьючерсов на основе библиотек

Сопрограммы

Фьючерсы могут быть реализованы в сопрограммах [27] или генераторах [103] , что приводит к одной и той же стратегии оценки (например, кооперативная многозадачность или ленивая оценка).

каналы

Фьючерсы легко реализовать в каналах : фьючерс — это одноэлементный канал, а обещание — это процесс, который отправляет в канал, исполняя будущее. [104] [105] Это позволяет реализовать фьючерсы на параллельных языках программирования с поддержкой каналов, таких как CSP и Go . Полученные фьючерсы являются явными, поскольку доступ к ним должен быть получен путем чтения из канала, а не только путем оценки.

Смотрите также

Рекомендации

  1. ^ Фридман, Дэниел; Дэвид Уайз (1976). Влияние прикладного программирования на многопроцессорность . Международная конференция по параллельной обработке. стр. 263–272.
    Предварительная версия: Фридман, Дэниел; Уайз, Дэвид (апрель 1978 г.). «Аспекты прикладного программирования для параллельной обработки». Транзакции IEEE на компьютерах . С-27 (4): 289–296. CiteSeerX 10.1.1.295.9692 . дои : 10.1109/tc.1978.1675100. S2CID  16333366. 
  2. ^ Хиббард, Питер (1976). Средства параллельной обработки . Новые направления в алгоритмических языках, (ред.) Стивен А. Шуман, IRIA, 1976.
  3. ^ Генри Бейкер; Карл Хьюитт (август 1977 г.). Инкрементная сборка мусора процессов. Материалы симпозиума по языкам программирования искусственного интеллекта. Уведомления ACM SIGPLAN 12, 8. стр. 55–59. Архивировано из оригинала 4 июля 2008 года . Проверено 13 февраля 2015 г.
  4. ^ Конвейеризация обещаний на erights.org
  5. ^ Конвейеризация обещаний на вики C2
  6. ^ аб Барбара Лисков; Люба Шрира (1988). «Обещания: лингвистическая поддержка эффективных асинхронных вызовов процедур в распределенных системах». Материалы конференции SIGPLAN '88 по разработке и реализации языков программирования; Атланта, Джорджия, США . АКМ. стр. 260–267. дои : 10.1145/53990.54016. ISBN 0-89791-269-1.Также опубликовано в Уведомлениях ACM SIGPLAN 23 (7).
  7. Надежные обещания с отсрочкой Додзё, Site Pen, 3 мая 2010 г.
  8. ^ ab "Promise", Руководство Алисы , DE: Uni-SB, заархивировано из оригинала 8 октября 2008 г. , получено 21 марта 2007 г.
  9. ^ ab «Future», руководство Алисы , DE: Uni-SB, заархивировано из оригинала 6 октября 2008 г. , получено 21 марта 2007 г.
  10. ^ Обещание, права E
  11. ^ 500 строк или меньше, «Веб-сканер с сопрограммами asyncio» А. Джесси Джирью Дэвиса и Гвидо ван Россума говорят, что «реализация использует asyncio.Event вместо Future, показанного здесь. Разница в том, что событие можно сбросить, тогда как Будущее не может перейти от решенного обратно к ожидающему».
  12. Control Concurrent MVar, Haskell, заархивировано из оригинала 18 апреля 2009 г.
  13. ^ WaitNeeded, Моцарт Оз, заархивировано из оригинала 17 мая 2013 г. , получено 21 марта 2007 г.
  14. Promise, Sunless Sea, заархивировано из оригинала 23 октября 2007 г.
  15. ^ Аргус, Массачусетский технологический институт
  16. ^ Лисков, Барбара (26 января 2021 г.), Распределенные вычисления и Argus, Устная история, IEEE GHN
  17. Золото, Уданакс, архивировано из оригинала 11 октября 2008 г.
  18. ^ Трубопровод, права E
  19. ^ Генри Либерман (июнь 1981 г.). «Предварительный просмотр акта 1». Памятка MIT AI 625. {{cite journal}}: Требуется цитировать журнал |journal=( помощь )
  20. ^ Генри Либерман (июнь 1981 г.). «Думать о множестве вещей одновременно, не запутываясь: параллелизм в акте 1». Памятка MIT AI 626. {{cite journal}}: Требуется цитировать журнал |journal=( помощь )
  21. ^ Гетц, Брайан (23 ноября 2004 г.). «Параллелизм в JDK 5.0». ИБМ .
  22. ^ ab «Асинхронность в 4.5: стоит ожидания - блог .NET - главная страница сайта - блоги MSDN». Блоги.msdn.com . Проверено 13 мая 2014 г.
  23. ^ abc «Асинхронное программирование с использованием Async и Await (C# и Visual Basic)». Msdn.microsoft.com . Проверено 13 мая 2014 г.
  24. Томас Петричек (29 октября 2010 г.). «Асинхронный C# и F# (I.): одновременное введение».
  25. ^ Дон Сайм; Томас Петричек; Дмитрий Ломов (21 октября 2010 г.). «Модель асинхронного программирования F #, PADL 2011».
  26. ^ аб Гилад Браха (октябрь 2014 г.). «Поддержка асинхронности языка Dart: этап 1».
  27. ^ ab «PEP 0492 — Сопрограммы с асинхронным синтаксисом и синтаксисом ожидания».
  28. ^ Кенджиро Таура; Сатоши Мацуока; Акинори Ёнезава (1994). «ABCL / f: полиморфно-типизированный параллельный объектно-ориентированный язык будущего - его дизайн и реализация». В материалах семинара DIMACS по спецификации параллельных алгоритмов, номер 18 в серии Dimacs по дискретной математике и теоретической информатике . Американское математическое общество. стр. 275–292. CiteSeerX 10.1.1.23.1161 . 
  29. ^ "Dart SDK dart async Completer" .
  30. ^ «Задание».
  31. ^ Стив Декорте (2005). «Ио, язык программирования».
  32. ^ «Использование обещаний». Сеть разработчиков Mozilla . Проверено 23 февраля 2021 г.
  33. ^ «Упрощение асинхронного программирования с помощью async и await» . Сеть разработчиков Mozilla . Проверено 23 февраля 2021 г.
  34. ^ Рич Хики (2009). «changes.txt в версии 1.1.x из Clojure richhickey». Гитхаб .
  35. ^ «Будущее - язык программирования Kotlin» .
  36. ^ Сейф Хариди; Нильс Франзен. «Учебник страны Оз». Глобальная пользовательская библиотека Моцарта. Архивировано из оригинала 14 мая 2011 года . Проверено 12 апреля 2011 г.
  37. ^ Выпуск Python 3.2
  38. ^ Выпуск Python 3.5
  39. ^ «Параллелизм с фьючерсами». ПЛТ . Проверено 2 марта 2012 г.
  40. ^ «Обещание класса». raku.org . Проверено 19 августа 2022 г.
  41. ^ «Будущее в std::future — Rust». doc.rust-lang.org . Проверено 16 декабря 2023 г.
  42. ^ Common Lisp Blackbird
  43. ^ Common Lisp Eager Future2
  44. ^ Lisp параллельно - библиотека параллельного программирования для Common Lisp.
  45. ^ Common Lisp PCall
  46. ^ «Глава 30. Тема 4.0.0» . Проверено 26 июня 2013 г.
  47. ^ "Библиотека Dlib C++ #thread_pool" . Проверено 26 июня 2013 г.
  48. ^ «GitHub – facebook/folly: библиотека C++ с открытым исходным кодом, разработанная и используемая в Facebook» . Гитхаб . 8 января 2019 г.
  49. Ссылки 10 февраля 2019 г.
  50. ^ «Слайды тем POCO» (PDF) .
  51. ^ «QtCore 5.0: Класс QFuture» . Проект Qt. Архивировано из оригинала 1 июня 2013 года . Проверено 26 июня 2013 г.
  52. ^ "Морская звезда". Проект Систар . Проверено 22 августа 2016 г.
  53. ^ «stlab — это постоянная работа лаборатории программных технологий Adobe. Исходные библиотеки Adobe (ASL), библиотеки платформ и новые библиотеки stlab размещены на github». 31 января 2021 г.
  54. ^ Groovy GPars. Архивировано 12 января 2013 г. в Wayback Machine.
  55. ^ Куджо.js
  56. ^ JavaScript, когда.js
  57. ^ Обещания / Спецификация A +
  58. ^ обещания
  59. ^ JavaScript MochKit.Async
  60. ^ JavaScript Angularjs
  61. ^ JavaScript-обещание узла
  62. ^ "JavaScript Q" . Архивировано из оригинала 31 декабря 2018 года . Проверено 8 апреля 2013 г.
  63. ^ JavaScript RSVP.js
  64. ^ Библиотека классов YUI JavaScript
  65. ^ Класс обещаний YUI JavaScript
  66. ^ JavaScript Bluebird
  67. ^ Java JDeferred
  68. ^ Java ParSeq
  69. ^ Objective-C MAFuture GitHub
  70. ^ Objective-C MAFuture mikeash.com
  71. ^ Objective-C RXPromise
  72. ^ ObjC-CollapsingFutures
  73. ^ Objective-C PromiseKit
  74. ^ Objective-C objc-обещание
  75. ^ Objective-C OAPromise
  76. ^ OCaml Ленивый
  77. ^ Перл Будущее
  78. ^ Обещания Perl
  79. ^ Перл-рефлекс
  80. ^ Обещание Perl::ES6
  81. ^ «Promise::XS – Быстрые обещания в Perl – Metacpan.org» . Metacpan.org . Проверено 14 февраля 2021 г.
  82. ^ Реакция PHP/обещание
  83. ^ Встроенная реализация Python
  84. ^ Pythonfutures
  85. ^ «Искаженные отсрочки». Архивировано из оригинала 6 августа 2020 года . Проверено 29 апреля 2010 г.
  86. ^ Будущее пакета R
  87. ^ будущее
  88. ^ Параллельный Рубин
  89. ^ Камень Рубинового обещания
  90. ^ Рубиновая библиотека
  91. ^ "Рубиновый целлулоидный драгоценный камень" . Архивировано из оригинала 8 мая 2013 года . Проверено 19 февраля 2022 г.
  92. ^ Будущий ресурс Ruby
  93. ^ ящик Futures-RS
  94. ^ Библиотека утилит Twitter
  95. ^ «Быстрая асинхронность». Архивировано из оригинала 31 декабря 2018 года . Проверено 23 июня 2014 г.
  96. ^ Swift FutureKit
  97. ^ Swift Apple GCD
  98. ^ Swift FutureLib
  99. ^ bignerdranch/Отложенный
  100. ^ Томвис/BrightFutures
  101. ^ Белозьеров/SwiftCoroutine
  102. ^ tcl-обещание
  103. ^ Решает ли async/await реальную проблему?
  104. ^ Языковые шаблоны Go Фьючерсы
  105. ^ Языковые шаблоны Go

Внешние ссылки