2

We are trying to use hylang as DSL for some financial business flow. We were trying to use business rules as JSON, but switched to DSL using hy language. Now we need to persist s-expression items into postgreSQL as like previous JSON-B items. Is there a standard way to do this or we have to use text fields instead?

Previous:

  "conditions": {
    "all": [
        {
            "name": "order_create_date",
            "value": 1620675000,
            "operator": "greater_than_or_equal_to"
        },
        {
            "name": "order_create_date",
            "value": 1624217400,
            "operator": "less_than_or_equal_to"
        }
  }

Current:

(defn check_condition [params] (
                            and (> params.order_create_date "2021/06/22") (< params.order_create_date "2021/07/22"))

)

Kamyar
  • 2,494
  • 2
  • 22
  • 33

2 Answers2

3

There is indeed no standard way to do this; nothing special has been implemented on the side of Hy or of Postgres. Unless you have a truly massive number of these, or they're very large, or you want to do some kind of fancy search or indexing of them, storing them as text should do fine. In fact, I would prefer flat files for this over a database.

Another option would be to take advantage of Postgres's JSON support and design your own little method for converting between Hy model trees and JSON. For example, Hy expressions could be represented as JSON arrays. Python's json library could help with this with e.g. the default argument of JSONEncoder.

Kodiologist
  • 2,984
  • 18
  • 33
  • 1
    The second option is what I've done in equivalent cases, albeit with CL not Hy: turn the JSON into an S-expression, compile & evaluate that on the fly. It works well and means you can pretend to everyone else that you're a good JSON citizen. –  May 18 '21 at 17:54
1

There are 2 solutions:

  1. Using libraries like 'sexpdata' for parsing and unparsing S-Expresisons to/from Python list, and then using JSON plus some custom enc/dec.

  2. Using pyparsing for parsing S-Expression into Python list and then using json.

    import pyparsing as pp
    import json
    
    LP = pp.Literal("(").suppress()
    RP = pp.Literal(")").suppress()
    String = pp.Word(pp.alphanums + '_,.#@<>=+=/*%[]')
    SingleQuoteString = pp.QuotedString(quoteChar="'", unquoteResults=False)
    DoubleQuoteString = pp.QuotedString(quoteChar='"', unquoteResults=False)
    QuotedString = SingleQuoteString | DoubleQuoteString
    Atom = String | QuotedString
    SExpr = pp.Forward()
    SExprList = pp.Group(pp.ZeroOrMore(SExpr | Atom))
    SExpr << (LP + SExprList + RP)
    
    
    def to_json(expr: str) -> str:
        return json.dumps(SExpr.parseString(expr).asList())
    
    
    def from_json(val: str) -> str:
        if isinstance(val, list):
            return f"({' '.join(from_json(e) for e in val)})"
        else:
            return str(val)
    
Kamyar
  • 2,494
  • 2
  • 22
  • 33