9. LispE in a Nutshell - naver/lispe GitHub Wiki

Introducing LispE: A Lightweight, Extensible Lisp for Today’s Programmers

In a world where programming languages often feel like a compromise — too slow, too heavy, or too rigid — LispE steps up as a breath of fresh air. Developed by Naver, this modern Lisp dialect combines the elegance of its heritage with a lean, high-performance implementation that’s ready for anything from AI prototyping to web applications. Available on Windows, macOS, as a Docker container for Linux, and even as a WebAssembly module for browsers, LispE is as versatile as it is powerful. If you’re a developer craving a tool that’s fast, extensible, and doesn’t bog you down with unnecessary baggage, LispE might just be your next go-to.

What Makes LispE Special?

LispE is built from the ground up in C++ to prioritize speed and simplicity. Unlike traditional Lisps trudging along with linked lists, LispE uses vector-based lists for O(1) access and efficient operations (see 2.3 List Implementation). It skips the virtual machine entirely — every object has its own eval method — delivering performance that leaves Python in the dust. A Stochastic Gradient Descent benchmark clocks in at 9 ms versus Python’s 45 ms, a 5x win without leaning on external crutches like NumPy (see 2.5 LispE vs. Python).

Key features include:

  • Multithreading Made Nimble: LispE offers lightweight, GIL-free threading—no heavy artillery needed. Python users might raise an eyebrow here; its Global Interpreter Lock (GIL) can’t say the same.
  • Bit-level Efficiency: A custom binHash dictionary slashes lookup times to handle symbols, the gist of Lisp programming.
  • Lean Design: Object pools and specialized types keep memory use tight, making LispE a lightweight champ compared to garbage-collected heavyweights.

LispE is also a breeze to extend—add new methods in minutes, integrate custom C++ libraries, or embed it in C projects (see 3. Extensions). Creating a library is as simple as deriving from the Element class and overriding the eval method to define how your library’s methods are evaluated — a straightforward hook into LispE’s core. With support for sockets, cURL, SQLite, BLAS, and FLTK graphics, it’s packed with tools for the real world, all in a package that won’t weigh down your system.

jag: The Ultra-Light Editor with a Twist

LispE comes with jag, a terminal-based editor so light it could float. Launch the LispE interpreter from the command line, and at any moment, summon jag to edit your current code. Execute it, peek at variables in a clean debugging space, tweak as needed, and hop back to editing — all without leaving the interpreter. Need to step through your code? Set breakpoints and debug line-by-line. Jag’s not just an editor; it’s your trusty sidekick, keeping things simple and focused—no IDE bloat required.


LispE in Action: Familiar Power, Fresh Approach

LispE isn’t here to intimidate — it’s designed to feel approachable, especially for Python users, while delivering a lighter, faster alternative. With its rich feature set and intuitive design, it’s ready to tackle modern programming tasks with a wink and a nod.

Arithmetic Structure and Pattern Programming

LispE’s data construct and pattern matching unlock a declarative approach to programming that’s both powerful and intuitive, naturally paving the way for a first-order logic engine. With data, you define structured types:

(data (Circle integer_) (Rectangle integer_ integer_)) ; for a circle’s radius and a rectangle’s dimensions

;; Pattern matching lets you compute over them effortlessly. 

(defpat Surface ((Circle r)) (* _pi r r)) ; calculates a circle’s area
(defpat Surface ((Rectangle h w)) (* h w)) ; handles a rectangle’s Surface. 
(defpat Surface (true) 'wrong) ; catching mismatches. 

(Surface (Circle 10)) ; yields 314.16
(Surface (Rectangle 5 10)) ; gives 50

In this snippet, (Circle 10) defines a circle with radius 10, and (Rectangle 5 10) a rectangle with height 5 and width 10. The Surface pattern matches each case, computes the area, and falls back to 'wrong' for anything else—all with minimal fuss. It’s a small taste of how LispE turns data into actionable logic, no heavy lifting required.

This isn’t just about areas; pattern matching over data can encode rules and queries, turning LispE into a lightweight Prolog-like engine without extra overhead, perfect for structured reasoning with a Lisp twist.


; When the list is empty we return true and stop
(defpred teste ([]) 
  true
)

; This rule only applies if the current head value: a is less than 10
(defpred teste ([a $ b])
  (< a 10)
  (teste b)
)

; Else we stop
(defpred teste (l)
  (println "We stop" l)
)

(teste '(1 2 11 12 13)) ;returns (11 12 13)

The main difference here is that instead of relying only on the function signature to select the right function for our data, we also impose that each instruction in the body returns true, otherwise we skip to the next, in a very Prolog way.

Python-Friendly, Lisp-Powered

Python developers will feel right at home with LispE’s primitives: vectors, dictionaries, heaps, and seamless list creation. Build a list the Lisp way with (list 1 2 3 4), or get specific with (integers 1 2 3 4) or (strings "a" "b" "c"). Need a classic linked list? (llist 1 2 3) has you covered. Methods mimic Python’s object-oriented style — (push l 1) is just l.push(1) under the hood — unlike Common Lisp’s more arcane syntax.

List operations are a standout:

  • (+ (numbers 1 2 3) (numbers 4 5 6)) yields (5 7 9).
  • (+ 10 (numbers 1 2 3)) gives (11 12 13).
  • Convert strings to numbers in one go: (integers (strings "1" "2" "3")) becomes (1 2 3).
  • Shape lists with rho: (rho 2 3 (numbers 1 2 3 4 5 6)) splits into ((1 2 3) (4 5 6)), or skip parentheses with (rho 2 3 . numbers 1 2 3 4 5 6) à la Haskell.

Note: The C++ compiler automatically identifies when lists of values are computed one with the others to produce the most efficient code at this effect, thanks to an array implementation. Hence you can expect these operations to run fast.

Parse a file of numbers (numbers.txt) with ease:

1 2 3 4
5 6 7 8
9 1 2 4
5 2 1 8

(rho 4 4 . numbers . flatten . maplist (\(x) (split x " ")) (split (fread "mumbers.txt") "\n"))

; yields ((1 2 3 4) (5 6 7 8) (9 1 2 4) (5 2 1 8))

Note if the last argument of a function is also a function call, we can replace the () with a ..

One line, no fuss—LispE turns raw data into a usable list faster than you can say “csv module.”

The Index of Functions adds depth: tail-call optimization, Haskell-inspired fold, APL’s iota, plus cURL for web requests and BLAS for matrix math. Macros and pattern matching let you reshape the language itself — try that with Python’s GIL holding you back!

Who’s It For?

  • Developers: Fast enrichment of the language with any C or C++ code.
  • Systems Coders: GIL-free threads and C embedding make it a lightweight powerhouse (see 6.3 Threads).
  • Python Fans: Familiar primitives, no steep learning curve — LispE’s your speedy cousin.

Take It for a Spin

LispE, a Naver creation, is open-source and waiting at LispE. Grab it for your platform, launch lispe, and dive in — whether you’re crunching numbers, scraping the web, or debugging with a smirk. Fast, light, and extensible, LispE proves you don’t need a GIL to get ahead—just a little Lisp magic. Ready to code smarter?