創建反應式程式語言的方法
在創建反應式程式語言時採用了幾種流行的方法。特定於各種域約束的專用語言的規範。這些約束通常以實時,嵌入式計算或硬體描述為特徵。另一種方法涉及通用語言的規範,其包括對反應性的支持。其他方法在定義中使用,並且使用編程庫或嵌入式域特定語言,這些語言能夠在程式語言的旁邊或之上實現反應。規範和這些不同方法的使用導致語言能力權衡。通常,語言越受限制,其關聯的編譯器和分析工具能夠通知開發者越多(例如,在執行分析程式是否能夠實際實時執行時)。特異性的功能性交易可能導致語言普遍適用性的惡化。
編程模型和語義
各種模型和語義決定了反應式編程的範疇。 我們可以沿著以下維度鬆散地拆分它們:
Synchrony:是時間同步與異步的基礎模型嗎?
決定論:評估過程和結果中的確定性與非確定性。
更新過程:回調與數據流與參與者。
實施技術和挑戰
實施的本質
反應式程式語言運行時由圖表表示,該圖示識所涉及的反應值之間的依賴性。在這樣的圖中,節點表示計算和邊緣模型依賴關係的行為。這樣的運行時使用所述圖形來幫助它跟蹤各種計算,一旦所涉及的輸入改變值,這些計算必須重新執行。
改變傳播算法
各種抽象實現方法使得能夠規範反應式編程。使用這樣的圖表明確地描述了數據流。最常見的算法是:拉、推、混合推拉式。
什麼推
在實施層面,事件反應包括跨圖表信息的傳播,該信息表征變化的存在。因此,受此類更改影響的計算將變得過時,並且必須標記為重新執行。然後,這種計算通常以其相關源的變化的傳遞閉包為特徵。然後,更改傳播可能會導致圖形接收器值的更新。
圖傳播信息可以包括節點的完整狀態,即所涉及節點的計算結果。在這種情況下,將忽略節點的先前輸出。另一種方法涉及增量傳播,即增量變化傳播。在這種情況下,信息沿著圖形邊緣激增,圖形邊緣僅包括描述前一個節點如何變化的增量。當節點保存大量狀態數據時,這種方法尤為重要,否則從頭開始重新計算會很昂貴。
Delta傳播本質上是一種最佳化,已經通過增量計算學科進行了廣泛的研究,增量計算的方法需要運行時滿意度,包括視圖更新問題。這個問題的臭名昭著是使用資料庫實體,它們負責維護不斷變化的數據視圖。
另一個常見的最佳化是採用一元變化積累和批量傳播。這種解決方案可以更快,因為它減少了涉及的節點之間的通信。然後可以採用最佳化策略來推斷其中包含的變化的性質,並相應地進行改變。例如批處理中的兩個更改可以相互抵消,因此,只需忽略。另一種可用的方法被描述為無效通知傳播。此方法導致具有無效輸入的節點拉取更新,從而導致更新其自己的輸出。
構建依賴關係圖有兩種主要方法:
依賴關係圖在事件循環中隱式維護。註冊顯式回調,然後導致創建隱式依賴。因此,通過回調引起的控制反轉因此留在原地。然而,使回調起作用(即返回狀態值而不是單位值)需要這樣的回調變為組合。
依賴關係圖是程式特定的,由程式設計師生成。這有助於以兩種方式定址回調的控制反轉:顯式指定圖形(通常使用可嵌入的特定於域的語言(DSL)),或者使用有效的表達和生成隱式定義圖形,原型語言。
途徑
運行
可以將反應式編程與普通的命令式編程融合在一起。在這樣的範例中,命令式程式在反應式數據結構上運行。這種設定類似於約束命令式編程; 然而,當約束命令式編程管理雙向約束時,反應式命令式編程管理單向數據流約束。
面向對象
面向對象的反應式編程(OORP)是面向對象編程和反應式編程的組合。 也許進行這種組合的最自然的方法如下:對象不是方法和領域,而是當他們所依賴的其他反應被修改時,對象會自動重新評估。
下面是使用JavaScript和jQuery的A = X + Y介紹示例的說明:
X: <input type="text" id="X" /> <br /> Y: <input type="text" id="Y" /> <br /> A: <span id="A"></span>
function setA() { // A=X+Y as integers var A = parseInt($('#X').val()) + parseInt($('#Y').val()); $('#A').text(A);}setA(); // for initial value of A$('#X,#Y').css('cursor', 'pointer').click(function () { // by reaction to a click at X or at Y... var obj = $(this); obj.val(parseInt(obj.val()) + 1); // updates X or Y setA(); // updates A});
如果OORP程式語言保持其命令性方法,那么它也屬於命令式反應式編程的範疇。