问题
I am new to Ceylon, and am currently exploring how to port some existing software written in TypeScript (essentially JavaScript) to Ceylon, so that it can run both on JavaScript engines and JVM.
Does anybody know how to code an equivalent of this Java stuff in Ceylon:
public class Engine { ... } // Some given class definition
public interface Cont extends Callable1<Cont,Engine> {}
where Callable1<Y,X>
is a Java equivalent of Ceylon's Callable<Y,[X]>
.
The idea is that an instance of Cont
, say named c
, would be a function either returning another Cont
, or a null
.
In Java, the code using this would look like:
// Somewhere
public static void exec(Cont c, Engine e) {
while (c != null) c = c.call(e);
}
(This is essentially a trampoline, where each called function returns the continuation, or null
when the computation is done.)
Also, in Ceylon I would like to pass functions as instances of Cont.
After reading the replies, I've come up to the following solution which uses both the proper result typing (Cont?
instead of Anything
), and null
-testing (for performance):
shared interface Cont { shared formal Cont? call(Engine e); }
// A wrapper class for an actual continuation function
class ContWrap(Cont?(Engine) fun) satisfies Cont {
shared actual Cont? call(Engine e) => fun(e);
}
shared Cont wrap(Cont?(Engine) fun) {
return ContWrap(fun);
}
// Somewhere
shared void exec(variable Cont? cont) {
while (exists cc = cont) {
cont = cc.call(this);
}
}
This suits me, at the cost of creating an additional small object every time, and passing functions through wrap
.
回答1:
Custom implementations of Callable have been discussed, but it's not yet possible. You don't need that, though.
shared class Engine() {
// ...
}
shared interface Continuation {
shared formal Continuation? call(Engine engine);
}
shared void execute(variable Continuation? continuation, Engine engine) {
while ((continuation = continuation?.call(engine)) exists) {}
}
object continuation satisfies Continuation {
call(Engine engine) => null;
}
// usage
execute(continuation, Engine());
// usage in 1.2 with inline object expression
execute(object satisfies Continuation { call(Engine engine) => null; }, Engine());
Since Continuation
doesn't (can't) satisfy Callable
, you can't just pass in a function. But in the upcoming release (1.2, available now via GitHub), you'll at least be able to use inline object expressions.
Note that this isn't idiomatic Ceylon, just a fairly direct translation from your Java.
回答2:
This seems to compile, but it looks pretty horrible:
class Engine() {}
Anything(Engine) foo(Engine e) {
return foo;
}
// Somewhere
variable Anything(Engine)? f = foo;
while (is Anything(Engine)(Engine) f2=f) {
f = f2(e);
}
来源:https://stackoverflow.com/questions/28589895/recursive-aliases-in-ceylon