2015-12-06 3 views
5

У меня есть общая функция, которая должна создать Tuple для вызова функции, аргументы которой я не знаю.Как превратить Ceylon Sequential или массив в общий Tuple с соответствующим типом?

Нечто подобное (кроме array в этом примере создается некоторый внешний код, так что я не могу просто применить функцию непосредственно):

Result apply<Result, Where>(
    Anything[] array, 
    Callable<Result, Where> fun) 
     given Where satisfies Anything[] => nothing; 

Есть ли тип-безопасный способ реализации этого метода и получить функцию, которая должна быть вызвана с данными аргументами?

+0

так у вас есть тип кортежа 'Where' и хотите обобщенно создать кортеж этого типа путем заполнения объектов из вашего массива (бросание исключения, когда он не поместиться)? –

+0

Точно :) и я верю, что в массиве есть элементы, которые успешно могут создать Tuple типа Where. – Renato

ответ

2

Это не может быть сделана полностью типа, благополучно ... но при условии, что массив действительно содержит элементы правильных типов, они должны появиться в Кортеже типа Where, следующая функция будет делать трюк:

Tuple<Anything, Anything, Anything> typedTuple({Anything+} array) { 
    if (exists second = array.rest.first) { 
     return Tuple(array.first, typedTuple({ second }.chain(array.rest.rest))); 
    } 
    else { 
     return Tuple(array.first, []); 
    } 
} 

и применять получает реализован как:

Result apply<Result, Where>(
    [Anything+] array, 
    Callable<Result, Where> fun) 
     given Where satisfies Anything[] { 
    value tuple = typedTuple(array); 
    assert(is Where tuple); 
    return fun(*tuple); 
} 
+0

Nice ... это действительно гарантируется спецификацией языка или просто происходит в текущей реализации? –

+0

Кстати, аналогичная вещь работает с конструктором последовательности: '[* array]' создаст 'ceylon.language :: ArraySequence ', где 'T' является объединением классов элементов в итерабельном. –

+1

Когда у вас есть метамодель функции (т. Е. Что-то реализующее 'ceylon.language.meta.model.Function'), у этого уже есть функция apply, которая принимает' Anything [] '. (Я уже использовал этот факт для некоторых задач codegolf при написании интерпретатора динамического языка). Тем не менее, это не работает для общего Callable. –

0

Ничего не связано с типом array с параметрами fun, так что подпись не может быть реализована безопасным способом. Вы вообще не ограничиваете тип array; он может содержать что угодно. Как в принципе, безопасная по типу реализация обрабатывает случай, когда fun ожидает [String, Integer], но array - [Boolean+]?

+0

Вы правы. Но мой вопрос предполагает, что тип массива правильный. Поскольку в моем коде я фактически создаю массив, используя метамодель, проверяя тип Where. – Renato

+0

, если вы уже * используете метамодель для построения массива, то почему бы просто не построить правильно набранный «Tuple»? Это может быть не самый эффективный код, но https://gist.github.com/jvasileff/9c5b079f6e1526deed2d делает что-то подобное. –

+0

Это полностью генерированный код генератора. Он проверяет, какие типы он должен генерировать, генерирует экземпляры, просматривая функции генератора для данных типов, собирает их как [Anything +], а затем должен преобразовать это в Tuple. – Renato