Hacker News new | ask | show | jobs
by sparkie 363 days ago
Kernel has first-class environments which aren't just lists, but can be constructed from lists. Environments are encapsulated, so we can't simply peek into them with car and cdr - we can only obtain the value associated with a given symbol by evaluating the symbol in that environment.

    ($define! foo
        ($bindings->environment
            (bar "Hello World")
            (baz 1234)
            (qux #f)))
            
    ($remote-eval bar foo)          ==> "Hello World"

    foo                             ==> #[environment]
We could perhaps make something a bit more friendly. Lets create an encapsulated `struct` type which could give us the contents as a plain list, or let us look up each field:

    ($provide! ($struct struct? destruct $get)
            
        ($define! (struct-intro struct? struct-elim) 
            (make-encapsulation-type))
                
        ($define! destruct
            ($lambda (struct)
                (cdr (struct-elim struct))))
    
        ($define! $get
            ($vau (struct member) e
                ($let ((record (car (struct-elim (eval struct e)))))
                    (eval member record))))
                    
        ($define! zip
            ($lambda (keys values)
                ($if ($and? (null? keys) (null? values))
                     ()
                     (cons (list (car keys) (car values)) (zip (cdr keys) (cdr values))))))
                    
        ($define! $struct
            ($vau kvpairs env
                ($let* ((keys (map car kvpairs))
                        (values (map ($lambda (pair) (eval (cadr pair) env)) kvpairs))
                        (record (apply (wrap $bindings->environment) (zip keys values))))
                    (struct-intro (cons record values))))))
Example usage:

    ($define! foo
        ($struct
            (bar "Hello World")
            (baz (+ 12 43))
            (qux #f)))              ==> #inert
            
    (struct? foo)                   ==> #t
    (pair? foo)                     ==> #f
    (environment? foo)              ==> #f
    
    (destruct foo)                  ==> ("Hello World" 55 #f)
    
    ($get foo bar)                  ==> "Hello World"
    ($get foo baz)                  ==> 55
    ($get foo qux)                  ==> #f
    ($get foo foo)                  ==> ERROR: Unbound symbol: foo

    foo                             ==> #[encapsulation]
Kernel: https://web.cs.wpi.edu/~jshutt/kernel.html

Klisp (essentially complete implementation of Kernel): https://github.com/dbohdan/klisp