Вопрос

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

  1. Что на практике означает функциональное реактивное программирование (FRP)?
  2. Из чего состоит реактивное программирование (в отличие от нереактивного программирования?)?

Я имею опыт работы с императивными/OO-языками, поэтому буду признателен за объяснение, относящееся к этой парадигме.

Это было полезно?

Решение

Если вы хотите почувствовать FRP, вы можете начать со старого Учебное пособие по Фрэн 1998 года с анимированными иллюстрациями.Для документов начните с Функциональная реактивная анимация а затем просматривайте ссылки на публикации на моей домашней странице и на стеклопластик ссылка на Хаскелл вики.

Лично мне нравится думать о том, что такое FRP. означает прежде чем говорить о том, как это можно реализовать.(Код без спецификации — это ответ без вопроса и, следовательно, «даже не неправильный».) Поэтому я не описываю FRP в терминах представления/реализации, как это делает Томас К. в другом ответе (графы, узлы, ребра, срабатывание, выполнение и т.д.).Существует множество возможных стилей реализации, но ни одна реализация не говорит, что такое FRP. является.

Я согласен с простым описанием Лоуренса Джи о том, что FRP — это «типы данных, которые представляют значение «с течением времени»».Традиционное императивное программирование фиксирует эти динамические значения лишь косвенно, через состояние и мутации.Полная история (прошлое, настоящее, будущее) не имеет первоклассного представления.Более того, только дискретно развивающийся ценности могут быть (косвенно) зафиксированы, поскольку императивная парадигма дискретна во времени.Напротив, FRP отражает эти развивающиеся ценности. напрямую и не испытывает затруднений с непрерывно развивающиеся ценности.

FRP также необычен тем, что он работает одновременно, не вступая в противоречие с теоретическими и прагматическими крысиными гнездами, которые мешают императивному параллелизму.Семантически параллелизм FRP мелкозернистый, определенный, и непрерывный.(Я говорю о смысле, а не о реализации.Реализация может включать или не включать параллелизм или параллелизм.) Семантическая детерминированность очень важна для рассуждений, как строгих, так и неформальных.Хотя параллелизм значительно усложняет императивное программирование (из-за недетерминированного чередования), в FRP он не требует усилий.

Итак, что такое ФРП?Вы могли бы придумать это сами.Начните с этих идей:

  • Динамические/развивающиеся ценности (т. е. ценности «с течением времени») сами по себе являются ценностями первого класса.Вы можете определять их и комбинировать, передавать в функции и из них.Я назвал эти вещи «поведением».

  • Поведения строятся из нескольких примитивов, таких как постоянное (статическое) поведение и время (например, часы), а затем из последовательной и параллельной комбинации. н поведения комбинируются путем применения n-арной функции (к статическим значениям) «поточечно», т. е. непрерывно во времени.

  • Чтобы объяснить дискретные явления, создайте другой тип (семейство) «событий», каждое из которых имеет поток (конечный или бесконечный) событий.Каждое событие имеет связанное время и значение.

  • Чтобы придумать композиционный словарь, на основе которого можно построить все виды поведения и события, поиграйте с несколькими примерами.Продолжайте разбирать на более общие/простые части.

  • Чтобы вы знали, что находитесь на твердой почве, дайте всей модели композиционную основу, используя технику денотационной семантики, которая просто означает, что (а) каждому типу соответствует простой и точный математический тип «значений», и ( б) каждый примитив и оператор имеет простое и точное значение в зависимости от значений составляющих.Никогда, никогда добавляйте соображения по реализации в свой процесс исследования.Если это описание кажется вам бредом, обратитесь к (а) Денотационный дизайн с морфизмами классов типов, (б) Двухтактное функциональное реактивное программирование (игнорируя биты реализации) и (c) Денотационная семантика Страница викибуков по Haskell.Помните, что денотационная семантика состоит из двух частей, предложенных двумя ее основателями Кристофером Стрейчи и Даной Скотт:более простая и полезная часть Стрейчи и более сложная и менее полезная (для разработки программного обеспечения) часть Скотта.

Если вы будете придерживаться этих принципов, я ожидаю, что вы получите что-то более или менее в духе FRP.

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

Правильно и эффективно реализовать эту модель было непросто, но это уже другая история.

Другие советы

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

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

Основная идея реактивного программирования заключается в том, что существуют определенные типы данных, которые представляют значение " в течение времени " ;. Вычисления, которые включают эти изменяющиеся во времени значения, сами по себе будут иметь значения, которые изменяются со временем.

Например, вы можете представить координаты мыши в виде пары целочисленных значений по времени. Допустим, у нас было что-то вроде (это псевдокод):

x = <mouse-x>;
y = <mouse-y>;

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

Если мы затем сделаем некоторые вычисления, основанные на этом, результирующие значения также будут значениями, которые меняются со временем. Например:

minX = x - 16;
minY = y - 16;
maxX = x + 16;
maxY = y + 16;

В этом примере minX всегда будет на 16 меньше координаты x указателя мыши. С библиотеками, поддерживающими реагирование, вы можете сказать что-то вроде:

rectangle(minX, minY, maxX, maxY)

А вокруг указателя мыши будет нарисован блок размером 32x32, который будет отслеживать его, где бы он ни двигался.

Вот довольно хороший функциональный документ реактивное программирование .

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

Это обязательно упускается довольно много. Метафора разрушается довольно быстро, когда вы на самом деле используете систему FRP. Например, обычно предпринимаются попытки смоделировать отдельные события (например, нажатие мыши). Я просто помещаю это здесь, чтобы дать вам представление о том, на что это похоже.

Для меня это примерно 2 разных значения символа =:

<Ол>
  • В математике x = sin(t) означает, что x это другое имя для sin(t). Так что написание x + y - это то же самое, что и sin(t) + y. Функционально-реактивное программирование в этом отношении похоже на математику: если вы пишете t, оно вычисляется с любым значением <=> на момент его использования.
  • В C-подобных языках программирования (императивные языки) <=> - это назначение: это означает, что <=> сохраняет значение <=>, полученное во время назначения.
  • Хорошо, исходя из базовых знаний и чтения страницы Википедии, на которую вы указали, кажется, что реактивное программирование - это что-то вроде вычислений с потоками данных, но с определенными внешними «стимулами», запускающими набор узлов для запуска и выполнения своих вычислений.

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

    Различные узлы, имеющие ребра из этого узла «значения объема», будут автоматически запускаться, и любые необходимые вычисления и обновления естественным образом будут проходить через приложение.Приложение «реагирует» на действия пользователя.Функциональное реактивное программирование будет просто реализацией этой идеи на функциональном языке или вообще в рамках парадигмы функционального программирования.

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

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

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

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

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

    Прочитав много страниц о FRP, я наконец наткнулся на этот Поучительные статьи о FRP помогли мне наконец понять, что такое FRP на самом деле.

    Ниже я цитирую Генриха Апфельмуса (автора реактивного банана).

    В чем суть функционального реактивного программирования?

    Распространенным ответом будет следующее: «FRP — это описание системы в изменяющихся во времени функций вместо изменяемого состояния", и что точно не ошибется.Это семантическая точка зрения.Но в По моему мнению, более глубокий и удовлетворительный ответ дает по чисто синтаксическому критерию:

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

    Например, возьмем пример счетчика:у вас есть две кнопки помечены как «Вверх» и «Вниз», которые можно использовать для увеличения или уменьшения Счетчик.Сначала необходимо указать начальное значение а затем изменять его при каждом нажатии кнопки;что-то вроде этого:

    counter := 0                               -- initial value
    on buttonUp   = (counter := counter + 1)   -- change it later
    on buttonDown = (counter := counter - 1)
    

    Дело в том, что на момент объявления только начальное значение для счетчика;Динамическое поведение счетчика неявно в остальном тексте программы.В отличие от этого, функциональные Реактивное программирование определяет все динамическое поведение в данный момент времени декларирования, например:

    counter :: Behavior Int
    counter = accumulate ($) 0
                (fmap (+1) eventUp
                 `union` fmap (subtract 1) eventDown)
    

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

    Итак, в Мое понимание Программа FRP представляет собой набор уравнений:enter image description here

    j дискретен:1,2,3,4...

    f зависит от t так что это включает в себя возможность моделировать внешние стимулы

    все состояние программы инкапсулировано в переменных x_i

    Библиотека FRP заботится о прогрессе времени, другими словами, принимая во внимание j к j+1.

    Я объясняю эти уравнения более подробно в этот видео.

    РЕДАКТИРОВАТЬ:

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

    Уравнения для x_i-s описывают граф зависимостей.Когда некоторые из x_i меняется во времени j тогда не все остальное x_i' значения в j+1 необходимо обновить, поэтому не все зависимости необходимо пересчитывать, поскольку некоторые x_i' может быть независимым от x_i.

    Более того, x_i-s, которые изменяются, могут быть постепенно обновлены.Например, давайте рассмотрим операцию карты f=g.map(_+1) в Скале, где f и g являются List из Ints.Здесь f соответствует x_i(t_j) и g является x_j(t_j).Теперь, если я добавлю элемент к g тогда было бы расточительно проводить map операция для всех элементов в g.Некоторые реализации FRP (например, рефлекс-фрп) стремятся решить эту проблему.Эта проблема также известна как инкрементальные вычисления.

    Другими словами, поведение (т. x_i-s ) в FRP можно рассматривать как кэшированные вычисления.Задача механизма FRP — эффективно аннулировать и перевычислить эти кэши ( x_i-s) если некоторые из f_i-s меняются.

    Статья Просто эффективная функциональная реактивность . Автор Конал Эллиотт ( прямой PDF , 233 & nbsp; КБ) это довольно хорошее введение. Соответствующая библиотека также работает.

    Теперь этот документ заменен другим документом, двухтактное функциональное реактивное программирование ( прямой PDF , 286 NBSP &;. KB)

    Отказ от ответственности:мой ответ находится в контексте rx.js - библиотеки «реактивного программирования» для Javascript.

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

    Основными преимуществами использования наблюдаемых являются:
    i) он абстрагирует состояние от вашего кода, например, если вы хотите, чтобы обработчик событий запускался только для каждого 'n'го события, или прекращал срабатывание после первых 'n' событий, или начинал срабатывание только после первого 'n' события. ', вы можете просто использовать HoF (filter, takeUntil, Skip соответственно) вместо установки, обновления и проверки счетчиков.
    ii) это улучшает локальность кода — если у вас есть 5 разных обработчиков событий, изменяющих состояние компонента, вы можете объединить их наблюдаемые и вместо этого определить один обработчик событий для объединенного наблюдаемого, эффективно объединяя 5 обработчиков событий в 1.Это позволяет очень легко рассуждать о том, какие события во всей вашей системе могут повлиять на компонент, поскольку все они присутствуют в одном обработчике.

    • Observable — это двойник Iterable.

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

    Наблюдаемый объект — это лениво создаваемая последовательность — каждый элемент передается наблюдателю всякий раз, когда он добавляется в последовательность, и, следовательно, перечисление управляется производителем.

    Чувак, это чертовски блестящая идея! Почему я не узнал об этом еще в 1998 году? В любом случае, вот моя интерпретация Fran учебника. Предложения приветствуются, я думаю о запуске игрового движка, основанного на этом.

    import pygame
    from pygame.surface import Surface
    from pygame.sprite import Sprite, Group
    from pygame.locals import *
    from time import time as epoch_delta
    from math import sin, pi
    from copy import copy
    
    pygame.init()
    screen = pygame.display.set_mode((600,400))
    pygame.display.set_caption('Functional Reactive System Demo')
    
    class Time:
        def __float__(self):
            return epoch_delta()
    time = Time()
    
    class Function:
        def __init__(self, var, func, phase = 0., scale = 1., offset = 0.):
            self.var = var
            self.func = func
            self.phase = phase
            self.scale = scale
            self.offset = offset
        def copy(self):
            return copy(self)
        def __float__(self):
            return self.func(float(self.var) + float(self.phase)) * float(self.scale) + float(self.offset)
        def __int__(self):
            return int(float(self))
        def __add__(self, n):
            result = self.copy()
            result.offset += n
            return result
        def __mul__(self, n):
            result = self.copy()
            result.scale += n
            return result
        def __inv__(self):
            result = self.copy()
            result.scale *= -1.
            return result
        def __abs__(self):
            return Function(self, abs)
    
    def FuncTime(func, phase = 0., scale = 1., offset = 0.):
        global time
        return Function(time, func, phase, scale, offset)
    
    def SinTime(phase = 0., scale = 1., offset = 0.):
        return FuncTime(sin, phase, scale, offset)
    sin_time = SinTime()
    
    def CosTime(phase = 0., scale = 1., offset = 0.):
        phase += pi / 2.
        return SinTime(phase, scale, offset)
    cos_time = CosTime()
    
    class Circle:
        def __init__(self, x, y, radius):
            self.x = x
            self.y = y
            self.radius = radius
        @property
        def size(self):
            return [self.radius * 2] * 2
    circle = Circle(
            x = cos_time * 200 + 250,
            y = abs(sin_time) * 200 + 50,
            radius = 50)
    
    class CircleView(Sprite):
        def __init__(self, model, color = (255, 0, 0)):
            Sprite.__init__(self)
            self.color = color
            self.model = model
            self.image = Surface([model.radius * 2] * 2).convert_alpha()
            self.rect = self.image.get_rect()
            pygame.draw.ellipse(self.image, self.color, self.rect)
        def update(self):
            self.rect[:] = int(self.model.x), int(self.model.y), self.model.radius * 2, self.model.radius * 2
    circle_view = CircleView(circle)
    
    sprites = Group(circle_view)
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == QUIT:
                running = False
            if event.type == KEYDOWN and event.key == K_ESCAPE:
                running = False
        screen.fill((0, 0, 0))
        sprites.update()
        sprites.draw(screen)
        pygame.display.flip()
    pygame.quit()
    

    Короче говоря: если каждый компонент можно рассматривать как число, вся система может рассматриваться как математическое уравнение, верно?

    Книга Пола Гудака, Школа выражений Haskell , не является только хорошее введение в Haskell, но он также тратит немало времени на FRP. Если вы новичок в FRP, я настоятельно рекомендую вам понять, как работает FRP.

    Существует также то, что выглядит как новое переписывание этой книги (выпущено в 2011 году, обновлено в 2014 году), Музыкальная школа Хаскелла .

    Согласно предыдущим ответам кажется, что математически мы просто мыслим в более высоком порядке. Вместо того, чтобы думать о значении x , имеющем тип X , мы думаем о функции x : T & # 8594; X , где T - тип времени, будь то натуральные числа, целые числа или континуум. Теперь, когда мы пишем y : = x + 1 на языке программирования, мы фактически имеем в виду уравнение y ( t ) = x ( t ) + 1.

    Действует как электронная таблица, как отмечено. Обычно основано на фреймворке, управляемом событиями.

    Как и во всех " парадигмах " его новизна спорна.

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

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

    Точно так же некоторые состояния могут быть не достигнуты, несмотря на то, что они имеют четко определенные ребра, поскольку глобальное состояние отклоняется от решения. 2 + 2 может или не может быть 4 в зависимости от того, когда 2 стали 2, и остались ли они таким образом. Таблицы имеют синхронные часы и обнаружение петель. Распределенные актеры обычно не делают.

    Всем хорошего веселья :).

    Я нашел это хорошее видео в субреддите Clojure о FRP. Это довольно легко понять, даже если вы не знаете Clojure.

    Вот видео: http://www.youtube.com/watch?v=nket0K1RXU4

    Вот источник, на который ссылается видео во 2-й половине: https://github.com/Cicayda/yolk-examples/blob/master/src/yolk_examples/client/autocomplete.cljs

    Эта статья Андре Стальца - лучшее и ясное объяснение, которое я до сих пор видел.

    Некоторые цитаты из статьи:

      

    Реактивное программирование - это программирование с асинхронными потоками данных.

         

    Кроме того, вам предоставляется удивительный набор функций для объединения, создания и фильтрации любого из этих потоков.

    Вот пример фантастических диаграмм, которые являются частью статьи:

     Диаграмма потока событий клика

    Речь идет о математических преобразованиях данных во времени (или игнорировании времени).

    В коде это означает функциональную чистоту и декларативное программирование.

    Государственные ошибки - огромная проблема в стандартной императивной парадигме. Различные биты кода могут изменять некоторые общие состояния в разные & Времена &. в исполнении программ. С этим трудно справиться.

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

    Это значительно снижает сложность и время отладки.

    Подумайте о разнице между A = B + C в математике и A = B + C в программе. В математике вы описываете отношения, которые никогда не изменятся. В программе написано, что & Quot; Прямо сейчас & Quot; А это В + С. Но следующая команда может быть B ++, в этом случае A не равен B + C. В математическом или декларативном программировании A всегда будет равно B + C, независимо от того, в какой момент времени вы спрашиваете.

    Таким образом, устраняя сложности общего состояния и меняя значения с течением времени. Ваша программа гораздо проще рассуждать.

    EventStream - это EventStream + некоторая функция преобразования.

    Поведение - это EventStream + некоторое значение в памяти.

    При возникновении события значение обновляется с помощью функции преобразования. Это значение сохраняется в памяти поведений.

    Поведения могут быть составлены для создания новых поведений, которые трансформируют N других видов поведения. Это составленное значение будет пересчитано как срабатывание входных событий (поведения).

    & "Поскольку наблюдатели не имеют состояния, нам часто требуется несколько из них для имитации конечного автомата, как в примере перетаскивания. Мы должны сохранить состояние, в котором он доступен для всех вовлеченных наблюдателей, например, в пути переменной выше. & Quot;

    Цитата из - Устаревшая модель наблюдателя http://infoscience.epfl.ch/record/148043/files/DeprecatingObserversTR2010. PDF

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

      

    [модуль / компонент / объект] реагирует означает, что он полностью ответственен   для управления собственным состоянием, реагируя на внешние события.

         

    В чем выгода этого подхода? Это Инверсия контроля ,   главным образом потому, что [модуль / Компонент / объект] отвечает за себя, улучшая инкапсуляцию с помощью частных методов по сравнению с открытыми.

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

    Проверьте Rx, Реактивные расширения для .NET. Они указывают, что с IEnumerable вы в основном «вытягиваете» из потока. Запросы Linq по IQueryable / IEnumerable представляют собой операции над множествами, которые «высасывают» результаты из набора. Но с теми же операторами над IObservable вы можете писать запросы Linq, которые «реагируют».

    Например, вы можете написать запрос Linq как (из m в MyObservableSetOfMouseMovements где m.X < 100 и m.Y < 100 выберите новую точку (m.X, m.Y)).

    и с расширениями Rx вот и все: у вас есть код пользовательского интерфейса, который реагирует на входящий поток движений мыши и рисует всякий раз, когда вы находитесь в поле 100 100 ...

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

    Начните с публикации Андреа Штальца о реактивном программировании.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top