Basic unit type:
λ> replTy "()"
() :: ()
Basic functions:
λ> replTy "(fn x x)"
(fn x x) :: b -> b
λ> replTy "((fn x ()) (fn x x))"
((fn x ()) (fn x x)) :: ()
λ> repl "((fn x x) (fn x x))"
((fn x x) (fn x x)) :: c -> c
(fn x x)
Statically typed:
λ> repl "(() (fn x x))"
-- *** Exception: Couldn't match expected type: ()
-- against type: (b -> b) -> e
Standard quotation:
λ> replTy "'()"
'() :: 'Symbol
λ> repl "'(foo bar)"
'(foo bar) :: 'Symbol
(foo bar)
Statically typed quotation:
λ> replTy "~()"
~() :: '()
All quotes have type 'a
. Normal symbolic Lisp style is 'Symbol
,
quoting anything else, e.g. for unit, is '()
. Also things have to be
in scope:
λ> repl "~a"
-- *** Exception: Not in scope: `a'
Quoted function:
λ> replTy "'(fn x x)"
'(fn x x) :: 'Symbol
Quoted function:
λ> replTy "~(fn x x)"
~(fn x x) :: '(b -> b)
Notice the type is '(b -> b)
.
There's an eval
function:
λ> replTy "eval"
eval :: 'a -> a
It accepts a quoted a
and returns the a
that it represents. It
won't accept anything not quoted:
λ> replTy "(eval ())"
-- *** Exception: Couldn't match expected type: 'a
-- against type: ()
If given a symbolic quoted expression, it will just return it as-is:
λ> repl "(eval '())"
(eval '()) :: Symbol
()
λ> repl "(eval '((fn x x) '()))"
(eval '((fn x x) '())) :: Symbol
((fn x x) ())
Given a well-typed quoted expression it will run the code:
λ> repl "(eval ~((fn x x) '()))"
(eval ~((fn x x) '())) :: 'Symbol
()
λ> repl "(eval ~((fn x x) ()))"
(eval ~((fn x x) ())) :: ()
()
What is the distinction between typed quotation and lazy lambdas? I've been wondering how to describe exactly what macros provide relative to lazy lambdas (just syntactic flexibility, or something more?). This seems bring them closer.
Neat!