Enhancing expressions with mutability?

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Mon Mar 23 14:31:00 UTC 2020


Hey Bernard,
cool stuff. Your patch seems to be missing the Term class, which is kind 
of important to look at to see how it interoperates with javac.

That said, while the ideas you explore are interesting, I do not seem 
them being applicable 'as is' to Java. That said, one direction which 
overlaps a lot to what you describe here, especially in your derivative 
example is support for the so called expression trees feature - C# for 
example has it [1].

Expression trees gives the language a new super power, in that it allows 
the static compiler to create a richer intermediate form for the 
compiled expression (e.g. other than bytecode), which is then amenable 
to further processing at runtime - e.g. we could take this IR and 
compile it down to:

* regular bytecode - e.g. to generate a method handle
* assembly - very useful for native interop (a la Panama)
* GPU kernel - very useful for offloading computation to GPU or other 
resources

At the same time, if the IR is expressive enough, you can do things like 
differentiating functions and the likes, which are use cases very 
important in machine learning.

So, my feeling is that, at some point, we'll start seeing some more 
concrete experiments in that direction - stay tuned :-)

Maurizio

[1] - 
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/

On 10/03/2020 21:03, B. Blaser wrote:
> Hi,
>
> 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
> language.
>
> Any feedback about this experiment would be welcome!
>
> Thanks,
> Bernard
>
> [1] http://www-formal.stanford.edu/jmc/recursive.html
> [2] quote.patch


More information about the discuss mailing list