используя callCC с функциями высшего порядка в R

Я пытаюсь понять, как получить функцию callCC в R для кратковременного вычисления функции для работы с такими функциями, как lapply и Reduce.

Мотивация

Это сделало бы Reduce и lapply асимптотической эффективностью> O (n), что позволило бы вам выйти из вычисления раньше.

Например, если я ищу значение в списке, я могу сопоставить функцию 'finder' по всему списку, и после того, как она будет обнаружена, lapply перестает работать, и это значение будет возвращено (очень похоже на разрыв цикла или использование return заявление, чтобы вырваться раньше).

Проблема в том, что у меня проблемы с написанием функций, которые должны выполняться lapply и Reduce, используя стиль, который требуется callCC.

Пример

Скажем, я пытаюсь написать функцию, чтобы найти значение 100 в списке: что-то эквивалентное

imperativeVersion <- function (xs) {
    for (val in xs) if (val == 100) return (val)
}

Функция, которую нужно передать lapply, будет выглядеть так:

find100 <- function (val) { if (val == 100) SHORT_CIRCUIT(val)  }
functionalVersion <- function (xs) lapply(xs, find100)

Это (очевидно) дает сбой, поскольку функция короткого замыкания еще не определена.

callCC( function (SHORT_CIRCUIT) lapply(1:1000, find100) )

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

следующее работает, потому что SHORT_CIRCUIT определен во время создания функции, переданной lapply.

callCC(
    function (SHORT_CIRCUIT) {
        lapply(1:1000, function (val) {
             if (val == 100) SHORT_CIRCUIT(val)
        })
)

Как я могу определить SHORT_CIRCUIT в функции, переданной lapply, не определяя ее как встроенную, как указано выше?

Я знаю, что этот пример может быть достигнут с помощью циклов, уменьшения или любого другого количества способов. Я ищу решение проблемы использования callCC с lapply и Reduce в частности.

Если я был расплывчатым или необходимы какие-либо разъяснения, оставьте комментарий ниже. Надеюсь, кто-то сможет с этим помочь :)

Edit One: подход должен быть «производственно-качественным»; никаких функций депарсинга или подобной черной магии.


person Róisín Grannell    schedule 17.10.2013    source источник


Ответы (2)


Я нашел решение этой проблемы:

find100 <- function (val) {
    if (val == 100) SHORT_CIRCUIT(val)
}

short_map <- function (fn, coll) {


    callCC(function (SHORT_CIRCUIT) {

        clone_env <- new.env(parent = environment(fn))
        clone_env$SHORT_CIRCUIT <- SHORT_CIRCUIT

        environment(fn) <- clone_env
        lapply(coll, fn)

    })
}

short_map(find100, c(1,2,100,3))

Уловка, позволяющая заставить функции более высокого порядка работать с callCC, заключается в том, чтобы назначить функцию замыкания в среде входных функций перед продолжением остальной части программы. Я сделал клон среды, чтобы избежать нежелательных побочных эффектов.

person Róisín Grannell    schedule 29.10.2013

Не знаю, пригодится ли это, но:

    find100 <- "function (val) { if (val == 100) SHORT_CIRCUIT(val)  }"
    callCC( function (SHORT_CIRCUIT) lapply(1:1000, eval(parse(text = find100))) )
    #[1] 100
person alexis_laz    schedule 17.10.2013
comment
спасибо за ваш ответ, но evalparse слишком хакерский для моих целей. Разложение функции на строку не всегда возможно, и вся информация о окружающей среде, в которой функция была определена, теряется. (это нарушит многие функции). - person Róisín Grannell; 18.10.2013