> the difficult thing I’ve found over the years is that Lisp is sort of unexplainable
I've found that getting rid of the parentheses helps.
f(x)
(f x)
["f", "x"]
(print (< 10 20))
["print", ["<", 10, 20]]
Lisp code is just normal Python lists which get evaluated by an interpreter function. Like this: code = ["print", ["<", 10, 20]]
def eval(code):
# magic
eval(code)
True
Filling out that eval function is a great way to learn lisp.These articles are very good and accessible:
What's the quintessential "now I get it" experience, in your mind?
If I could explain the moment, I would. But I really can’t. That said, one aha moment for me was reading McCarthy’s original Lisp paper and realizing the whole core of the language was a single page (17).
https://www.informatik.uni-bremen.de/agbkb/lehre/pi3/folien/...
Learning that https://calva.io/paredit/ exists and moving your cursor along the AST or moving expressions around with nice hotkeys. Then making simple macros for infix notation and SQL and so on, which operate on the AST too. Realizing that there is no "architecture" because any repeated code or pattern can be easily abstracted away with a macro. Realizing that you can just describe your problem on paper, making up the perfect notation, then implement that notation in a few hours.
Not anymore. I started with Racket and went through the Little Schemer. I did Clojure for a while. I even used Babashka to write all my scripts, then later rewrote them in other languages.
I gave it a good try. Maybe it wasn't enough to properly "get it"?
What did you end up rewriting your bb scripts in?
Let's write some very silly code to turn an integer into a list of digits in Common Lisp:
(deftype Digit ()
"A non-negative integer smaller than 10."
'(Mod 10))
(defun integer->digits (integer)
"Turns a given INTEGER into a list of digits."
(declare (type Integer integer))
(labels ((digit-loop (integer digits)
(declare (type Integer integer)
(type List digits))
(if (< integer 10)
(list* integer digits)
(multiple-value-bind (quotient remainder)
(truncate integer 10)
(declare (type Integer quotient)
(type Digit remainder))
(digit-loop quotient
(list* remainder digits))))))
(declare (ftype (Function (Integer List) List) digit-loop))
(digit-loop (abs integer)
nil)))
(digit-loop 2026) ; => (2 0 2 6)
(digit-loop "2026")
; The value
; "2026"
; is not of type
; INTEGER
; when binding INTEGER
;
; Type HELP for debugger help, or (SB-EXIT:EXIT) to exit from SBCL.
;
; Restarts:
; 0: [ABORT] Exit debugger, returning to top level.I "get" Lisp just fine, have made my own hobby Lisp interpreters, have written programs in Lisp, am an emacs user, etc. etc.
And yet if you handed me a terminal and an editor and asked me to write a program, I would never reach for Lisp to do it. My eyes don't like it. (Also I like static types).