You know PHP. Why learn a Lisp on the same runtime?
Honest answers below. If Phel doesn't fit, that's fine.
Do I need to know Lisp?#
No. One rule: the first element inside parentheses is the function, the rest are arguments — (map fn arr), (php/str_contains haystack needle). No operator precedence, no special cases. Phel in 5 Minutes walks through the syntax; practice exercises get you comfortable in an hour.
Why Lisp syntax specifically?#
- Homoiconicity. Code is data (lists, vectors, maps). Macros manipulate code with the same functions you use on data.
- Macros. Extend the language with built-in-looking syntax. See Macros.
- Regularity. One pattern:
(function arg1 arg2 ...). Read any Phel code once you internalize it.
Unfamiliar feeling fades within days of use.
Why not just modern PHP?#
Modern PHP is great. Some things aren't on its roadmap:
- Immutable data structures by default. Eliminates stale state, unexpected mutations, order-dependent side effects.
- Real macro system. Operates on code as data. PHP attributes and codegen are not the same.
- REPL-driven development. Evaluate expressions interactively, build incrementally. See REPL.
- Functional-first design. Pure functions, pipelines, data transformation. PHP allows FP but pushes OOP.
Phel and PHP optimize for different things on the same runtime.
Can I use existing PHP libraries?#
Yes. Any Composer package, class, trait, function, or constant is callable through the php/ prefix — e.g. (php/strlen "hello") or (php/-> (php/new DateTimeImmutable "2024-01-15") (format "Y-m-d")). The full escape hatch (methods, statics, constants, php/aget) is in PHP Interop.
Isn't a compilation step a hassle?#
No. vendor/bin/phel run or the REPL compiles transparently. No build pipeline, watcher, or output dir. Same idea as TypeScript or Sass. Deploys as plain PHP.
What about performance?#
Phel compiles to plain PHP, so the bulk of your code runs at PHP speed. The real overhead is the persistent (immutable) data structures: an "update" allocates a new structure with structural sharing (O(log32 n)) rather than mutating in place, so they are slower than a native PHP array write. For most web, CLI, and data-processing work that cost is negligible.
In a hot inner loop over millions of elements, reach for native PHP arrays through PHP interop (php/aset, php/aget, php/apush) and stay on the fast path, then hand the result back as a Phel value. Everywhere else, immutability buys correctness and clearer code for a price you will not notice.
What about debugging?#
Full PHP debugging ecosystem works:
- Phel helpers:
tap>,add-tap,pprint. - PHP native:
var_dump,print_r, Symfonydump(). Phel values are PHP objects. - XDebug: step-through, breakpoints, variable inspection. PhpStorm and VS Code.
See Debug helpers and XDebug setup.
What about IDE support?#
VS Code, PhpStorm, Emacs, Vim: syntax highlighting, REPL/nREPL, formatting. See Editor Support.
Is Phel production-ready?#
Core is stable and tested. Good fit for:
- Side projects, personal tools
- CLI applications
- Internal tools and scripts
- Learning FP on a runtime you know
- REPL-driven prototyping
Community small but active. Need LTS-grade enterprise stability? Not yet. Want expressive PHP and OK being an early adopter? Phel delivers.
See awesome-phel for libraries, tools, and projects.
Next steps#
- Getting Started: zero to a live REPL.
- PHP Interop: call any PHP function or class.
- Cheat Sheet: core syntax and functions in one page.