ホームページ >バックエンド開発 >Python チュートリアル >ルールエンジン DSL の再作成
数年前、私はもともと仕事のルールエンジン用に設計されたドメイン固有言語 (DSL) を再実装しました。おもちゃの再実装は Javascript (元々は Python) で書かれ、GitHub にリリースされました。これは公開すべきではない非常に特殊な使用例向けに特別に設計されていたため、あまり効果があるとは期待していませんでした。
bing副操縦士が吐いたちょっと可愛い写真
設計の主な目標は、簡単にシリアル化できるものにすることでした。チューリング完全性は次の 2 つのことだけを実行するだけで必要だったので、気にする必要はありませんでした。
私はまず Python で匿名関数を書くことから始めました。ただし、作業を一連のスレッド/プロセスに分散しようとすると、インタープリターはラムダがシリアル化できないと不平を言いました。当時、メイン コードの外側にロジックを配置する必要があったため、最終的にはその目的のために 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 中国語 Web サイトの他の関連記事を参照してください。