首頁 > 後端開發 > Python教學 > 重構規則引擎 DSL

重構規則引擎 DSL

Susan Sarandon
發布: 2024-12-01 09:36:10
原創
122 人瀏覽過

幾年前,我重新實現了一種最初為工作中的規則引擎設計的領域特定語言(DSL)。這個玩具重新實作是用 Javascript 編寫的(最初是用 Python 編寫的),並發佈到 GitHub。我沒想到它能做太多事情,因為它是專門為一個非常具體的用例而設計的,我不應該透露。

Remaking a rule-engine DSL
bing副駕駛吐的一張有點可愛的照片

設計的主要目標是可以輕鬆序列化。圖靈完備性不是問題,因為我只需要它做兩件事:

  1. 簡單的布林比較(如果 x == 到 y)
  2. 從字典/雜湊中的欄位取得值

我先開始用 Python 寫匿名函數。然而,當我嘗試將工作分散到一組線程/進程時,解釋器抱怨 lambda 不可序列化。當時,我需要主程式碼之外的邏輯,所以我最終為此目的創建了 DSL。

首先想到的是 lisp,因為我喜歡程式碼有點類似陣列/列表。相似性是一件好事,因為我已經將設定儲存在 YAML 中。因此,我不必擔心創建一種新的方式來表示邏輯。

將語言儲存為清單帶來了另一個優勢,我不需要從頭開始建立解析器,即不需要標記/執行詞法分析(詞法分析器)。換句話說,作者就是詞法分析者。我需要實現的就是獲取輸入列表,查找它是否是一個程式(我們稱之為規則),然後根據上下文執行它。

const schema = ["condition.Equal", ["basic.Field", "foo"], ["basic.Field", "bar"]];

// returns a function that checks if context.foo === context.bar
const rule = ruler.parse(rule)

const context = {foo: "meow", bar: "woof"};
rule(context) // returns false
登入後複製
登入後複製

一切順利,符合預期。然後幾天前我偶然發現了一篇用Python實作方案的文章。我之前可能讀過這篇文章,當時我花了很多時間學習 Clojure。然而,這一次,我決定再次使用 Python 重新實作該程式庫。

所以這次我需要標記化,並且自己執行詞法分析器。如果我只處理數字,一切都很簡單,但是當涉及到字串時,事情就會變得更加複雜。我遵循了另一個教程,並重新發現了 make-a-lisp 專案。最後我放棄了,使用了hy-lang提供的詞法分析器。

詞法分析器採用 s 表達式,並傳回類似抽象語法樹的結構。從那裡,我透過遍歷樹來建立我的解析器,將規則作為以字典作為上下文的閉包返回。

const schema = ["condition.Equal", ["basic.Field", "foo"], ["basic.Field", "bar"]];

// returns a function that checks if context.foo === context.bar
const rule = ruler.parse(rule)

const context = {foo: "meow", bar: "woof"};
rule(context) // returns false
登入後複製
登入後複製

新的實施並沒有真正的優勢,因為我已經離開這份工作幾年了。我留下的實現到目前為止可能仍然運行良好(最好是在經過多次迭代之後才實現)。然而,在整個旅程中我仍然學到了一兩件事。如果您覺得這很有趣,請隨意查看 Javascript(它需要陣列中的規則模式)或新的 Python 版本(s-表達式)。

以上是重構規則引擎 DSL的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板