upvote
> can actually be extended in useful ways

I just made a library with [query syntax](https://codeberg.org/veqq/declarative-dsls) over various data structures a la sql:

    (import declarative-dsls/dataframes :as df)
    (def people (df/dataframe :name :age :job))
    (df/dataframe? people)

    (df/insert! {:name "Bob" :age 30 :job "Developer"} :into people)
    (df/insert! {:name "Alice" :age 27 :job "Sales"} :into people)
    (df/update! :set {:job "Engineer"}
             :where |(= ($ :job) "Developer")
             :from people)
    
    (df/save-csv people "people.csv" :sep "\\t")
    (def people2 (df/load-csv "people.csv" :sep "\\t"))
    
    (-> people2
       df/dataframe->rows
       df/rows->dataframe
       df/print-as-table)
Printing:

    job       age  name
    --------  ---  -----
    Engineer  30   Bob
    Sales     27   Alice
It also has datalog and minikanren (with s expr, sharing the same goals etc.) And it vectorizes like APL:

    (df/v + [1 2 3] 1 [1 2 3] 1) # returns: [4 6 8]
    (df/v + 1 {:column [1 2 3] :key [1 2 3]}) # returns: {:column @[2 3 4] :key @[2 3 4]}

    (df/v * [1 2 3] [[1 1 1]
                     [1 2 2]
                     [1 2 3]]) # returns: @[@[1 1 1] @[2 4 4] @[3 6 9]]
Or you can just use [J directly from Janet](https://git.sr.ht/~subsetpark/jnj):

    (jnj/j "3 4 $ i. 10") # returns: ((0 1 2 3) (4 5 6 7) (8 9 0 1))
    (jnj/j "$" [3 4] (range 10)) # returns: ((0 1 2 3) (4 5 6 7) (8 9 0 1))
The Joy Web Framework has a cool [db query dsl](https://github.com/joy-framework/joy/blob/master/docs/databa...) too: `(var account (db/find-by :account :where {:login (auth-result :login)}))`, used for a [web auth](https://codeberg.org/veqq/janetdocs/src/commit/848dcbd8e54ad...).

From my response, bigger than the article: https://lobste.rs/s/y0euno/why_janet_2023#c_lspe6n

reply
these little dsl's convey so much
reply