Phel
Lisp dialect compiling to PHP. Persistent data structures. PHP interop via php/.
Verify before documenting
Any Phel snippet added to docs/blog/cookbook MUST be runtime-checked. Examples that "look right" silently rot. Two ways:
# Simple one-shot eval
./vendor/bin/phel run -e '(println (map inc [1 2 3]))'
# Reliable multi-line one-shot eval with heredoc
./vendor/bin/phel eval - <<'PHEL'
(ns app)
(println (+ 40 2))
PHEL
# REPL session for exploration
./vendor/bin/phel repl
Prefer the quoted heredoc because:
- No quoting issues: Everything between
<<'PHEL'andPHELis treated as literal input. - Consistent pattern: One approach works for all evaluations, from simple to complex.
- Multi-line friendly: Code keeps its natural, readable formatting.
- Easy to extend: Add more forms without changing the command syntax.
Write the snippet, run it, paste real output. If output differs from what you assumed, fix the doc - not the runtime.
Gotchas (project-specific)
defprotocolcannot be implemented inline indefstruct. Usedefinterfacefor inline;defprotocol+extend-typeper struct.extends?works only on primitive type keywords (:string,:int). Returnsfalsefor struct types. Usesatisfies?on instances instead.- CLI args:
argv(vector of user args, excludes program name);*program*for the script path. Not*argv*orphp/$argv. - Side effects:
doseq/foreach. Build sequences:for. Mixing causes wrong return shape. - String module:
phel\string(notphel\str). - Phel vectors print as
@[...]. Clojure prints[...]. Match the runtime output in docs.
Core syntax
(defn greet [name] (str "Hello, " name)) ; function
(defrecord Todo [id text done]) ; record (positional + map ctor)
(definterface Showable (show [this])) ; interface - inline-implementable
(defprotocol Renderable (render [this])) ; protocol - extend-type only
(extend-type Todo Renderable (render [t] ...)) ; protocol impl per type
(defmulti area :shape) ; multimethod
(defmethod area :circle [{:radius r}] (* 3.14 r r))
(into [] (comp (filter odd?) (map inc)) [1 2 3 4 5]) ; transducer
(re-find #"\d+" "abc123") ; regex literal
PHP interop
(DateTimeImmutable. "2026-01-01") ; constructor shorthand
(.format obj "Y-m-d") ; method shorthand
(.-prop obj) ; property shorthand
DateTimeImmutable/ATOM ; static constant
(DateTimeImmutable/createFromFormat ...) ; static method
(php/strlen "x") ; any PHP function
This repo
- Docs:
content/documentation/,content/blog/ - Phel scratch:
local/main.phel - Build artifacts:
build/phel-config.php,.phel/ - CLI:
./vendor/bin/phel <run|repl|test|build>
For full language reference: content/documentation/language/ and content/documentation/reference/.