Recursive aliases in Ceylon

折月煮酒 提交于 2019-12-11 03:07:14

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!