Enhancing expressions with mutability?

B. Blaser bsrbnd at gmail.com
Tue Mar 10 21:03:40 UTC 2020


Taking back the essential idea of the original publication on Lisp
[1], I did the attached syntactic experiment [2] trying to bring some
kind of mutability to expressions and thus giving more flexibility to
the language. I hope this subject hasn't been covered too many times,
otherwise I'd apologize for any disturbance.

To build such mutable expressions, I've specified a new unary operator
` along with its resulting class 'java.lang.Term'. The quotation
operator creates a 'Term' from any reference which can then be linked
to other terms to finally be evaluated to the result of a function
call for lambdas or the reference itself otherwise.

Let's take some examples from the attached patch:

+    interface Get {
+        int op();
+    }
+    interface Sum {
+        int op(int i, int j);
+    }

+    int a = 0, b = 0;
+    Sum s = (x, y) -> x + y;

+    public void run() {
+        Get a = () -> this.a;
+        Get b = () -> this.b;
+        Term e1 = (`s).link(`a, `b);
+        this.a = 1; this.b = 2;

The above lines create a mutable expression e1 from the sum lambda s
of the getter a and b which can then be evaluated to:

    (Integer)e1.value() == 3

or visualized as:

    e1.toString().equals("Sum( Get( ) Get( ) )")

An interesting application similar to §3.g from [1] is the computation
of the partial derivative of a sum involving the mutation of the
initial expression to produce a new resulting one:

+    // Derivative of sum e with respect to r
+    Term derivative(Term e, Term r) {
+        if (e.terms.isEmpty()) {
+            return `Integer.valueOf(e.that == r.that ? 1 : 0);
+        }
+        else if(e.that == (`s).that) {
+            return (`s).link(derivative(e.terms.get(0), r),
derivative(e.terms.get(1), r));
+        }
+        else throw new AssertionError();
+    }

Invoking the above method like this:

+        Term e2 = derivative(e1, `a);

creates the resulting derivative expression e2 which can then be evaluated to:

    (Integer)e2.value() == 1

or visualized as:

    e2.toString().equals("Sum( `1 `0 )")

Finally, we note that any term may be quoted to prevent its
evaluation, for example:

+    Derivative d = this::derivative;

+        Term e3 = (`d).link(`e1, ``a);

can be evaluated to:

    (Integer)((Term)e3.value()).value() == 1

or visualized as:

    e3.toString().equals("Derivative( `Sum( Get( ) Get( ) ) `Get( ) )")

Of course, one of our main concern is how much do we need this and a
reasonable answer would probably be as much as we need Lisp's
S-expressions but with similar or maybe better performance than
external interpreters and a more homogeneous integration to the

Any feedback about this experiment would be welcome!


[1] http://www-formal.stanford.edu/jmc/recursive.html
[2] quote.patch
-------------- next part --------------
A non-text attachment was scrubbed...
Name: quote.patch
Type: text/x-patch
Size: 18205 bytes
Desc: not available
URL: <https://mail.openjdk.java.net/pipermail/discuss/attachments/20200310/54c5274c/quote-0001.patch>

More information about the discuss mailing list