I had a problem with the cool auto-generated Runnable, and thought I’d
ask
whether this is an operator error or not. I’ll cut to the chase.
Here’s a
little Java class:
public class AutoRunnableFixture {
public static void runit(Runnable r) {r.run();}
}
Here’s a little ruby test class:
require ‘java’
require ‘test/unit’
class AutoRunnableTest < Test::Unit::TestCase
def get_autorunnable_return_val(val)
Java::AutoRunnableFixture.runit {
return val
}
end
def test_return_val
assert_equal(‘hi’, get_autorunnable_return_val(‘hi’))
end
end
The issue is that if I provide a code block to a Java method that
accepts a
Runnable, it’s very cool that a Runnable get auto-generated behind the
scenes for me. Thanks. That is a joy, though it makes my brain hurt.
However, on the Ruby side, it’s possible that the code block returns a
value. It fails to return the value for the automatically generated
Runnable.
I realize that this is at the nasty edges between two languages, and
that
the answer may be, “Don’t do that.” Still, just looking locally at the
Ruby code all seems proper and legal. However, it doesn’t work as it
seems
it should.
I’d be glad to tell the tale of how I ended up doing this. This is the
key
aspect of my problem, though. I agree that it’s an uncommon use of
Runnable, which you mostly hand off to Thread, in my experience.
The newly inserted line does, in fact run.
Am I deluded in my belief that it should not?
The return in the block becomes the return for the runnable. Here’s the
equivalent Java; maybe it will make it more clear:
// not tested
class AutoRunnableTest extends TestCase {
public void getAutoRunnableReturnVal(final Object val) {
AutoRunnableFixture.runit(new Runnable() {
public void run() {
return; // can’t return val in java because Runnable#run returns
void
}
})
System.out.println “Hey!! I should never run! WTF?!?”
}
// etc.
}
A runnable can’t cause its calling context to return. If you want to do
something like that, you’ll have to throw an exception.
Ya, I understand these things about a Runnable, and that I’m in a weird
area between Ruby and Java. However, just looking on the Ruby side, the
code seems clear and correct, yet it doesn’t behave as expected. I
discovered this while moving methods down from Ruby into Java. The Ruby
implementation worked fine, and the Java one was borked.
I suppose I was hoping for a more elaborate implementation of the
internal auto-runnable that dealt with this. After all, as I’m
imaginging
it, the JRuby guys already have their hooks into both sides of the
operation here, and they could lob the return value and return context
across the Java run() method to accomplish this. That is, they’re
already
providing the implementation for run(), which has to call back to Ruby.
The result of that operation must have things like the return value and
the
context into which it tried to “return”, even though the run() method
itself is void.
At any rate, I’ve adopted the “Don’t Do That” strategy, (which you’re
suggesting) so it’s not urgent. Just wondering if anyone else thought
it
was a bug. If it becomes a problem, I’ll just write my own Runnable and
use that.
I’m not able to validate this at the moment, but I believe the block
parameter can also be auto-translated to a java.util.concurrent.Callable
implementation.