Остановите оценку функции, используя другую функцию в R

Я сделал тест с вложенным return функция в R, но без успеха. Я пришел из Mathematica, где этот код работает хорошо. Вот игрушечный код:

fstop <- function(x){
  if(x>0) return(return("Positive Number"))
}

f <- function(x){
  fstop(x)
  "Negative or Zero Number"
}

Если я оцениваю f(1), Я получил:

[1] "Negative or Zero Number"

Когда я ожидал всего лишь:

[1] "Positive Number"

Вопрос: есть некоторая нестандартная оценка, которую я могу сделать в fstopтак что я могу просто fstop результат, без изменений f функционировать?

PS: я знаю, что могу поставить if прямо внутри f, но в моем реальном случае структура не так проста, и эта структура сделает мой код проще.

2 ответа

Решение

Собираюсь высунуть мне шею и сказать...

Нет.

Возвращение функции не к вызывающей стороне, а к вызывающей ее вызывающей стороне будет означать изменение контекста выполнения. Вот как такие вещи, как return и другие вещи потока управления реализованы в источнике. Увидеть:

https://github.com/wch/r-source/blob/trunk/src/main/context.c

Я не думаю, что код уровня R имеет доступ к контекстам выполнения, подобным этому. Может быть, вы могли бы написать некоторый код уровня C, который мог бы это сделать, но это не ясно. Вы всегда можете написать do_return_return функция в стиле do_return в eval.c и создать собственную версию R... Это не стоит.

Таким образом, ответ, скорее всего, "нет".

Я думаю, что Spacedman прав, но если вы хотите оценить свои выражения в обертке, то это возможно, используя tryCatch механизм вырваться из стека оценки.

Во-первых, нам нужно определить специальный RETURN функция:

RETURN <- function(x) {
  cond <- simpleCondition("")  # dummy message required
  class(cond) <- c("specialReturn", class(cond))
  attr(cond, "value") <- x
  signalCondition(cond)
}

Затем мы переписываем ваши функции, чтобы использовать наши новые RETURN:

f <- function(x) {
  fstop(x)
  "Negative or Zero"
}
fstop <- function(x) if(x > 0) RETURN("Positive Number")  # Note `RETURN` not `return`

Наконец, нам нужна функция-обертка (здесь wsr означает "со специальным возвратом") для оценки наших выражений:

wsr <- function(x) {
  tryCatch(
    eval(substitute(x), envir=parent.frame()),
    specialReturn=function(e) attr(e, "value")
) }

Затем:

wsr(f(-5))
# [1] "Negative or Zero"
wsr(f(5))
# [1] "Positive Number"

Очевидно, это немного глупо, но повседневное использование не сильно отличается от оценки выражений в with или вызывающий код с source, Один недостаток в том, что он всегда вернется на тот уровень, который вы называете wsr от.

Другие вопросы по тегам