PlanetJava
Custom Search

java-vm-languages
[Top] [All Lists]

Re: new milestone build for Renjin - R for the JVM

Subject: Re: new milestone build for Renjin - R for the JVM
Date: Tue, 17 May 2011 06:15:53 -0700 (PDT)
Great question!
FYI, this is renjin's implementation of a Thunk or "Promise" as it's
called in R. The only difference
is that the context needs to be provided to access the variables that
were in scope when the thunk was created.
http://code.google.com/p/renjin/source/browse/trunk/core/src/main/java/r/lang/Promise.java
My question for the JVM-niks out there is how feasable is it create a
new jvm class for each thunk or function value?
When you write a function in scala or clojure, does this get compiled
into a new, separate class?
I know invokedynamic will solve a lot of these problems, but in
targeting java 6, is it worth economizing on the number of class,
using for example reflection to dispatch a function call to a static
method?
Alex
On May 17, 12:29 am, James Iry 
<[email protected]> wrote:
> /*
>  * Along those lines I'm interested in the best way to implement
> call-by-need
>  * thunks on the JVM. A too-simplistic Java base class might look like
>  */
> abstract class Thunk1<T> {
> private T memo = null;
> private boolean evaluated = false;
>
> public final T compute() {
> if (!evaluated) {
> memo = compute();
> evaluated = true;
>
> }
> return memo;
> }
>
> abstract T innerCompute();
>
> }
>
> /*
>  * A thunk that lazily computes sqrt(1000) would look like
>  *
>  * new Thunk<Float> {
>  *
>  * @override public Float innerCompute() { return sqrt(1000); } }
>  *
>  * If you don't need nulls then you can get rid of the boolean and use memo
>  * == null to indicate that it hasn't been computed.
>  *
>  * The problem with that simplistic approach is that the compute method will
>  * hold on to a lot of structure that is no longer needed once the thunk has
>  * been evaluated. A better approach looks more like
>  */
> public interface Thunk2<T> {
> T compute();
>
> }
>
> public static <T> Thunk2<T> memoize2(final Thunk2<T> unmemoized) {
> return new Thunk2<T>() {
> private T memo = null;
> private Thunk2<T> inner = unmemoized;
>
> @Override
> public T compute() {
> if (inner != null) {
> memo = inner.compute();
> inner = null;
>
> }
> return memo;
> }
> };
> }
>
> /*
>  * To create a call-by-need thunk that computes sqrt(1000)
>  *
>  * memoize1(new Thunk<Float>() {
>  *
>  * @override public Float compute() { return sqrt(1000); } }
>  *
>  * That approach would need to be extended a bit if you want it to handle
>  * exceptions - e.g. instead of just a memo field, add an exception field as
>  * well and wrap the inner evaluation with a try/catch.
>  *
>  * An alternative memoizer uses a self-replacing thunk (that's what GHC
>  * uses). It replaces the conditional with an extra level of indirection.
>  * I've never benchmarked to know if self-replacing thunks work well on the
>  * JVM. In Java it might look like
>  */
> public class MemoizedThunk<T> implements Thunk2<T> {
> private T memo;
>
> public MemoizedThunk(T memo) {
> this.memo = memo;
>
> }
>
> @Override
> public T compute() {
> return memo;
>
> }
> }
>
> public static <T> Thunk2<T> memoize3(final Thunk2<T> unmemoized) {
> return new Thunk2<T>() {
> Thunk2<T> inner = new Thunk2<T>() {
> @Override
> public T compute() {
> final T memo = unmemoized.compute();
> inner = new MemoizedThunk<T>(memo);
> return memo;
>
> }
> };
>
> @Override
> public T compute() {
> return inner.compute();
>
> }
> };
> }
>
> /*
>  * Again, exceptions might need to be added if they are part of your
> language.
>  *
>  * One wrinkle with all of these options is that they don't play well with
>  * Thunks that move between threads. For that you may need to add some
>  * concurrency protection.
>  *
>  * Has anybody played with these or other alternatives here?
>  */
>
> On Fri, May 13, 2011 at 8:46 AM, Alexander Bertram 
> <[email protected]>wrote:
>
>
>
>
>
>
>
>
>
> > Hi Rémi,
>
> > Thanks for taking a look!
>
> > I see now that you're right about the example with runif(). To be
> > honest, I have more questions about compilation then running code at
> > this point. I'm reading Modern Compiler Implementation by Appel and
> > have started building the IRFactory, but R's lazy-non-pure-call-by-
> > need-semantics-with-higher -order-functions are a bit dizzying for a
> > compiler-novice like myself.
-- 
You received this message because you are subscribed to the Google Groups "JVM 
Languages" group.
To post to this group, send email to 
jvm-languages-/JYPxA39Uh5TLH3MbocFF+G/[email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/jvm-languages?hl=en.
msgmiddle
<Prev in Thread] Current Thread [Next in Thread>
Current Sitemap | © 2012 planetjava | Contact | Privacy Policy