| title | Frequently Asked Questions (FAQ) |
|---|
No. Use tail-recursive functions instead:
(define (list-sum xs)
(list-sum-loop xs 0))
(define (list-sum-loop remaining result)
(match remaining
((nil) result)
((li head tail) (list-sum-loop tail (iadd result head)))))The compiler handles tail calls correctly — no stack growth.
(equal? a b) ;; structural equality
(same? a b) ;; reference equality, or same for atomic data(print x) ;; print a value
(println x) ;; print a value and newline
(write x) ;; print a string
(writeln x) ;; print a string and newline
(newline) ;; print a newline
(format x) ;; format a value as a stringmeta-lisp follows Scheme's minimalist syntax philosophy, but they are completely different languages.
meta-lisp has many syntax improvements over Scheme. It is not an implementation of the Scheme standard, nor a Scheme dialect.
The most important difference: meta-lisp is statically typed, while Scheme is dynamically typed.
meta-lisp has a Hindley-Milner type system similar to Haskell and ML.
A very simple type system:
- No subtyping.
- No row polymorphism.
- No union or intersection types.
- No typeclasses.
| Haskell | meta-lisp |
|---|---|
Int -> Int |
(-> int-t int-t) |
forall a. a -> a |
(polymorphic (A) (-> A A)) |
| Typeclasses | ❌ Not supported |
data Maybe a = Nothing | Just a |
(define-enum (maybe-t A) (just (value A)) (nothing)) |
| Algebraic data types | ✅ define-enum |
| Pattern matching | ✅ match |
| Lazy evaluation | ❌ Strict evaluation (call-by-value) |
| Purely functional (no side effects) | ❌ Side effects allowed (I/O, printing) |
| SML | meta-lisp |
|---|---|
int -> int |
(-> int-t int-t) |
'a -> 'a |
(polymorphic (A) (-> A A)) |
| Functors | ❌ Not supported |
datatype 'a option = NONE | SOME of 'a |
(define-enum (option-t A) (some (value A)) (none)) |
Pattern matching (case) |
✅ match |
| Strict evaluation | ✅ Strict evaluation (call-by-value) |
| Side effects allowed | ✅ Side effects allowed (I/O, printing) |
| OCaml | meta-lisp |
|---|---|
int -> int |
(-> int-t int-t) |
'a -> 'a |
(polymorphic (A) (-> A A)) |
| Module system (Module / Functor) | ❌ Not supported |
type 'a option = None | Some of 'a |
(define-enum (option-t A) (some (value A)) (none)) |
Pattern matching (match) |
✅ match |
| Strict evaluation | ✅ Strict evaluation (call-by-value) |
| Side effects allowed | ✅ Side effects allowed (I/O, printing) |
| Clojure | meta-lisp |
|---|---|
(defn f [x] ...) |
(define (f x) ...) |
int -> int |
(-> int-t int-t) |
| Dynamic typing | ✅ Static typing (Hindley-Milner) |
| Immutable data by default | Mutable data by default |
| Running on JVM / CLR / JS | Standalone compiler (bootstrap + self-hosting) |
| STM for concurrency | ❌ Not supported |
| Lazy sequences | ❌ Strict evaluation (call-by-value) |
| Common Lisp | meta-lisp |
|---|---|
(defun f (x) ...) |
(define (f x) ...) |
(function (int) int) |
(-> int-t int-t) |
| Dynamic typing | ✅ Static typing (Hindley-Milner) |
| CLOS (Common Lisp Object System) | ❌ Not supported (use define-struct / define-enum) |
| Multiple return values | ❌ Not supported |
| Restart / condition system | ❌ Not supported |
| Strict evaluation | ✅ Strict evaluation (call-by-value) |
| TypeScript | meta-lisp |
|---|---|
| Union types | ❌ Not supported |
| Intersection types | ❌ Not supported |
| Subtyping (interface extends) | ❌ Not supported |
Generics <T> |
✅ (polymorphic (A) ...) |
any / unknown |
❌ Not supported |
| Structural typing | ❌ Nominal typing only |
(define-struct) generates the constructor name as make-<base-name>:
(define-struct point-t
(x int-t)
(y int-t))Use (define-struct*) to specify a custom constructor name:
(define-struct* point-t
(cons-point
(x int-t)
(y int-t)))This is a naming convention.
(define-struct) uses the type name <base-name>-t to generate the constructor name make-<base-name>.
For example, point-t → make-point.
If you don't want this convention,
use the more explicit (define-struct*) or (define-record-type).