Chas Emerick wrote:
> In those rare circumstances where you need to write mutually-recursive  
> functions without consuming stack, clojure provides a trampoline  
> implementation (introduced last November here: 
> http://groups.google.com/group/clojure/browse_frm/thread/6257cbc4454bcb85) 
> .  There's obviously a performance penalty associated with their use,  
> but it's nice to have that escape hatch.
> 

I was thinking about this.  For any given tail recursive function, it can be 
turned into a 
non-stack-building loop.  The transformation I'm thinking of looks like this:

public int foo(int bar, String baz) {
   /* Some logic for foo, including an escape */
   int newBar = ...;
   String newBaz = ...;
   return foo(newBar, newBaz);
}

becomes

public int foo(int bar, String baz) {
   label :top;

   /* Some logic for foo, including an escape */

   bar = newBar;
   baz = newBaz;
   jump :top;
}


Now consider two mutually recursive functions, 'foo' and 'bar'.

public int foo(int fooInt, String fooString) {
   /* Some logic for foo, possibly including an escape */
   int newBarInt = ...;
   String newBarString = ...;
   return bar(newBarInt, newBarString);
}

public int bar(int barInt, String barString) {
   /* Some logic for bar, possibly including an escape */
   int newFooInt = ...;
   String newFooString = ...;
   return foo(newFooInt, newFooString);
}

Given those two functions, what's to keep us from creating a structure like 
this?

private static class FooArgs {
   public int fooInt;
   public String fooString;
   public FooArgs(int fooInt, String fooString) {
     this.fooInt = fooInt;
     this.fooString = fooString;
   }
}

private static class BarArgs {
   public int barInt;
   public String barString;
   public BarArgs(int barInt, String barString) {
     this.barInt = barInt;
     this.barString = barString;
   }
}

public int foo(int fooInt, String fooString) {
   return foobar(new FooArgs(fooInt, fooString), null, true);
}

public int bar(int barInt, String barString) {
   return foobar(null, new BarArgs(barInt, barString), false);
}

private int foobar(FooArgs fooArgs, BarArgs, barArgs, boolean doFoo) {
   String fooString, barString;
   int fooInt, barInt;

   if(doFoo) {
     fooInt = fooArgs.fooInt;
     fooString = fooArgs.fooString;
     fooArgs = null;
     jump :foo
   } else {
     barInt = barArgs.barInt;
     barString = barArgs.barString;
     barArgs = null;
     jump :bar
   }
   label :foo

   /* Some logic for foo, including an escape */

   barInt = ...
   barString = ...
   fooString = null;
   jump :bar;
   label :bar;

   /* Some logic for bar, including an escape */

   fooInt = ...
   fooString = ...
   barString = null;
   jump :foo;
}

I know there are method size limits, but assuming we stay under them, this 
should work for solving 
at least the common case of two, small, mutually recursive functions.  And it 
could be generalized up.

~~ Robert Fischer.
Grails Training        http://GroovyMag.com/training
Smokejumper Consulting http://SmokejumperIT.com
Enfranchised Mind Blog http://EnfranchisedMind.com/blog

Check out my book, "Grails Persistence with GORM and GSQL"!
http://www.smokejumperit.com/redirect.html

--~--~---------~--~----~------------~-------~--~----~
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@googlegroups.com
To unsubscribe from this group, send email to 
jvm-languages+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/jvm-languages?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to