
$vau: the ultimate abstraction (2010) [pdf] - drnewman
https://web.wpi.edu/Pubs/ETD/Available/etd-090110-124904/unrestricted/jshutt.pdf
======
gjm11
There's a bit of subtext in the title that may be worth drawing attention to.
(I dunno, maybe it's all obvious to everyone interested enough in this stuff
to be reading the dissertation. But perhaps not, so here goes.)

In the 1970s, after their paper introducing Scheme, Sussman and Steele
published a series of papers showing how to implement a bunch of things "on
top of" a functional-programming substrate, many of them having titles or
subtitles of the form "Lambda: the ultimate X". (The first one was "Lambda:
the ultimate imperative", the second "Lambda: the ultimate declarative",
others "Lambda: the ultimate GOTO" and "Lambda: the ultimate opcode".)

The idea of these papers wasn't merely "look, you can implement X in Lisp",
but something more like "You might be inclined to think of X as simple and
primitive and cheap, and Lisp as sophisticated and complicated and expensive
-- but that's mostly prejudice, an accident of the particular hardware we
happen to have built first, and using something like Lisp as your lower level
and implementing these things on top is _better_ than doing it the other way
around".

So writing something -- especially something about a Lisp implementation --
with a subtitle of the form "X: the ultimate Y" where X is _not_ lambda -- is
pointedly one-upping that.

Especially as the thing that $vau is allegedly providing the new best way to
do is ... function abstraction, which is exactly what lambda is for.

------
jhallenworld
I've implemented something like this in a non-LISP syntax language. See:

[https://github.com/jhallen/joes-
sandbox/tree/master/lang/ivy](https://github.com/jhallen/joes-
sandbox/tree/master/lang/ivy)

The idea is that in a function call, the arguments are normally evaluated
before the call as usual. But if a formal argument in the function's
declaration is prefixed with ampersand then during a function call, that
argument is not evaluated, but is instead packaged up as a zero-argument
lambda function. The argument can be called later using the normal function
call syntax, but also there is semantic sugar: the * operator calls a zero-
argument function.

Further, when a variable is evaluated, you get both its value and a reference
to it. This allows variables to be evaluated before being assigned to in
assignments. This sounds weird, but it works with the above. You can make a
"set" function which does the same thing as assignment:

    
    
        # Define set function
        fn set(&left, right) {
            *left = right
        }
    
        # Set x to 10
        set x 10
    

Here is how you could define switch using primitives (if the last argument is
prefixed with ampersand, then any extra arguments are treated the same, but
can only be accessed via argv):

    
    
        fn switch(&val) {
                var rtn, x, v = *val
                x = 1
                while x < len(argv) - 1 {
                        if *argv(x) == v {
                                return *argv(x + 1)
                        }
                        x += 2
                }
                if x < len(argv) {
                        return *argv(x)
                }
                return void
        }
    

Example use (8 arguments passed to switch- each set of braces is an argument):

    
    
        switch 2 1 {
            print "one"
        } 2 {
            print "two"
        } 3 {
            print "three"
        } {
            print "default"
        }
    

"two" is printed in this case.

Right now the delayed arguments are evaluated in the closure of the function
call (so they are lexically scoped). The wrap/unwrap concept from this paper
gives me ideas on how to make this more versatile...

~~~
amelius
Perhaps a stupid question, but why not introduce an explicit "evaluate"
operator, and keep the rest of the language lazy?

That would prevent treating function calls as special.

~~~
jhallenworld
Well the language is not LISP, meaning that the source is immediately compiled
(to byte code in this case), and provides no access to an AST that can be
manipulated.

It's interesting to see how far you can get without eval.

------
ASipos
I would like to see a mature language using fexprs. They are what I first
thought about when I heard the word homoiconicity. Macros seem inelegant in
comparison (since there is a separate layer of code that operates on code, and
also you don't get self-modifying code, just compile-time transformations).

~~~
9214
Rebol family of languages (including Red) uses near equivalents of fexprs.

Here's a self-modifying function ;^)

    
    
      >> foo: has [x][append body-of context? 'x [+ 1] 1]
      == func [/local x][append body-of context? 'x [+ 1] 1]
      >> loop 3 [probe foo]
      1
      2
      3
      == 3
      >> ?? foo
      foo: func [/local x][append body-of context? 'x [+ 1] 1 + 1 + 1 + 1]

------
geocar
There's a partial list of Kernel implementations (the lisp described in the
paper) that I'm aware of:

[https://axisofeval.blogspot.com/2011/09/kernel-
underground.h...](https://axisofeval.blogspot.com/2011/09/kernel-
underground.html)

------
openfuture
I read maybe a dozen pages, might read more but I'm curious if someone can
tell me the type of $vau?

~~~
shawn
According to Racket, the type is 'ultimate-abstraction':

    
    
      $ racket -I swindle
      Welcome to Racket v6.12.
      > (class-of 42)
      #<primitive-class:exact-integer>
      > (class-of $vau)
      #<primitive-class:ultimate-abstraction>
    

I guess the paper wasn't lying.

~~~
chaoticmass
dchaney@sagan:/~$ racket -I swindle

Welcome to Racket v6.7.

> (class-of 42)

#<primitive-class:exact-integer>

> (class-of $vau)

; $vau: undefined;

; cannot reference undefined identifier

; [,bt for context]

>

What did I do wrong? Or did the joke go over my head?

~~~
shawn
$vau was introduced in Racket v6.11. You'll need to upgrade.

~~~
leoh
What? No it wasn't.

------
pronoiac
Alt title: "Fexprs as the basis of Lisp function application"

------
leoh
What are interesting uses of this?

------
shawn
If anyone wants to implement this, I believe you can do so in Lumen Lisp:
[https://docs.ycombinator.lol/](https://docs.ycombinator.lol/)

In particular, macros like
[https://imgur.com/C4NL0OB](https://imgur.com/C4NL0OB) are pretty effortless
to write.

