锡兰的递归别名

Recursive aliases in Ceylon

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

有谁知道如何在锡兰编写与 Java 等同的代码:

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

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

其中 Callable1<Y,X> 相当于锡兰 Callable<Y,[X]>.

的 Java

想法是 Cont 的一个实例,比如命名为 c,将是一个返回另一个 Contnull 的函数。

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

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

(这本质上是一个蹦床,其中每个调用函数 returns 继续,或 null 计算完成时。)

此外,在锡兰,我想将函数作为 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 传递函数。

这似乎可以编译,但看起来很糟糕:

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

Callable have been 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.

请注意,这不是地道的锡兰语,只是对您的 Java 的直接翻译。