Рекурсивные псевдонимы на Цейлоне
Я новичок в 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);
}