Рекурсивные псевдонимы на Цейлоне

Я новичок в Ceylon и в настоящее время изучаю, как перенести некоторые существующие программы, написанные на TypeScript (в основном, JavaScript), на Ceylon, чтобы он мог работать как на JavaScript-движках, так и на JVM.

Кто-нибудь знает, как кодировать эквивалент этого Java-материала на Цейлоне:

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

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

где Callable1<Y,X> является Java-эквивалентом Цейлона Callable<Y,[X]>,

Идея состоит в том, что экземпляр Contскажем по имени c, будет функция, либо возвращающая другую Contили null,

В Java код, использующий это, будет выглядеть так:

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

(Это по сути батут, где каждая вызванная функция возвращает продолжение, или 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,

2 ответа

Решение

Пользовательские реализации Callable были обсуждены, но это пока невозможно. Тебе это не нужно.

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) вы по крайней мере сможете использовать встроенные объектные выражения.

Обратите внимание, что это не идиоматичный Цейлон, это просто прямой перевод с вашей Java.

Это похоже на компиляцию, но выглядит довольно ужасно:

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);
}
Другие вопросы по тегам