These lisp guys really get excited over very abstract things. If you say this to an average person on the street they will probably try to run away.
It’s kind of like in treesitter style editing, where you can “swap these two arguments,” “select this function,” “wrap this in a try block” with a single keyboard command… but way more standardized and granular. Plus with the ability to execute anything you highlight
All that and then you realize you can store code as data (since it’s just a data structure) and run data as code.
I think most programmers don’t realize how arbitrary the difference is between code and data until they get used to using LISP.
Because industry lied to you, promising "simplicity and riches". The industry didn't just overcomplicate programming. It institutionalized the complication. Why? Because complexity is a moat.
Complex frameworks need certified experts. Certified experts charge more. Companies built around expertise need the complexity to persist. So the complexity gets marketed as sophistication.
They've promised: "Java/C# will get you hired anywhere", but you're hired to write xml (these days yaml). "OOP models the real world", they said. The real world doesn't have abstract factory visitors. "Design patterns make you senior", but you only learned workarounds for language deficiencies. "Learn the framework, get the job". Framework dies, you start over. "Specialization is valuable". you're now hostage to one ecosystem.
A programmer who understands fundamentals is dangerous to this system. The fundamentals:
- a function transforms input to output.
- composition builds complexity from simplicity.
- types describe what's possible.
- effects should be explicit.
And then you realize that Lisp is the skeleton key. All that above is Lisp, or came from Lisp. Every language is either: Lisp with different syntax, or C with different syntax, or arguing between the two.
If you learn Lisp, you don't learn a language. You learn what languages are. You're no longer a consumer of a programming language or two, or a few. You are native speaker in all of them.
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
Frankly, though, I think lispy community has benefited from being smaller. For example, even though the now ancient Design Patterns already warned programmers to prefer composition over inheritance, the OO programmers still created 15 levels deep hierarchies.