Понимание ленивых вычислений в R

Я пытаюсь понять, как работает ленивое вычисление в R. Применяется ли это только к оценке аргументов функции? Потому что я понимаю, например

f <- function(x = x, y = x*2) {
  c(x, y)
}

f(2)
[1] 2 4

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

g <- function(x) {
  y <- sample(1:100000000)
  return(x)
}

g(4)

Но он четко оценивает вызов sample, даже если его результат не используется.

Может ли кто-нибудь точно объяснить, как это работает, или указать мне, где это подробно объясняется?

Похожие вопросы:

Вопрос с похожей формулировкой, но с другой проблемой


person user2987808    schedule 09.03.2017    source источник


Ответы (1)


Как вы уже выяснили, R не использует ленивое вычисление в общем смысле. Но R предоставляет эту функциональность, если она вам нужна, с помощью функции delayedAssign(), как показано ниже:

> system.time(y <- sample(1E8))
   user  system elapsed 
  7.636   0.128   7.766 
> system.time(length(y))
   user  system elapsed 
      0       0       0 
system.time(delayedAssign("x", sample(1E8)))
   user  system elapsed 
  0.000   0.000   0.001 
> system.time(length(x))
   user  system elapsed 
  7.680   0.096   7.777 

Как видите, y вычисляется немедленно, поэтому определение длины y совсем не занимает времени. x, с другой стороны, не оценивается при создании, delayedAssign() возвращает только обещание оценить x, и только когда нам действительно нужно значение x, в данном случае для определения его длины, оценивается x.

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

a.f <- function(z) { delayedAssign("x", sample(1E8)); return(z+1) }
system.time(a.f(0))
   user  system elapsed 
      0       0       0 
person Hans Ekbrand    schedule 09.03.2017
comment
Я имею в виду книгу Хэдли Уикхема, где он упоминает: По умолчанию аргументы функции R ленивы, они оцениваются только в том случае, если они действительно используются. Разве это не так с последними версиями? - person Sarang Manjrekar; 14.03.2017
comment
Обратите внимание, что вопрос включал эту фразу. Применимо ли это только к оценке аргументов функции? Мой ответ не противоречит утверждению Уикхема. - person Hans Ekbrand; 14.03.2017