PlanetJava
Custom Search

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

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

Subject: Re: Re: new milestone build for Renjin - R for the JVM
Date: Mon, 16 May 2011 15:29:03 -0700
/*
 * 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