锡兰的递归别名

时间:2015-02-18 17:25:42

标签: ceylon

我是Ceylon的新手,目前正在探索如何将用TypeScript(基本上是JavaScript)编写的现有软件移植到Ceylon,以便它可以在JavaScript引擎和JVM上运行。

有人知道如何在Ceylon中编写相应的Java内容:

public class Engine { ... } // Some given class definition

public interface Cont extends Callable1<Cont,Engine> {}

其中Callable1<Y,X>是Ceylon的Callable<Y,[X]>的Java等价物。

我们的想法是,Cont的实例(比如名为c)将会返回另一个Contnull

在Java中,使用它的代码如下所示:

// Somewhere
public static void exec(Cont c, Engine e) {
  while (c != null) c = c.call(e);
}

(这实际上是一个蹦床,每个被调用的函数返回连续,或者在计算完成时返回null。)

此外,在Ceylon中,我想将函数作为Cont。

的实例传递

阅读完回复后,我提出了以下解决方案:使用正确的结果输入(Cont?代替Anything)和null - 测试(性能) ):

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);
    }
}

这适合我,但每次都要创建一个额外的小对象,并通过wrap传递函数。

2 个答案:

答案 0 :(得分:3)

Callable的自定义实施已discussed,但目前还不可行。但是,你并不需要那样。

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());

由于Continuation没有(不能)满足Callable,因此您无法传递函数。但是在即将发布的版本(1.2,现在通过GitHub提供)中,您至少可以使用inline object expressions

请注意,这不是惯用的Ceylon,只是来自Java的直接翻译。

答案 1 :(得分:1)

这似乎是编译,但它看起来非常可怕:

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);
}