I saw this interesting post Reversing the technical interview by Kyle Kingsbury. For fun, I wrote the equivalent code in R, which looks like the following.
cons <- function(h, t) function(cond) if (cond) h else t
prn_list <- function(l) {
cat("(")
while (TRUE) {
cat(l(TRUE))
if (is.null(l(FALSE))) {
cat(")\n")
break
}
else {
cat(", ")
l <- l(FALSE)
}
}
}
reverse <- function(l) {
r <- NULL
while (TRUE) {
if (is.null(l)) {
return(r)
}
else {
r <- cons(l(TRUE), r)
l <- l(FALSE)
}
}
}
Looks fine when printing the constructed list.
l <- cons(1L, cons(2L, cons(3L, NULL)))
prn_list(l)
# (1, 2, 3)
However, when trying to print the reversed list, it will print (1, 1, 1, ...
infinitely.
prn_list(reverse(l))
# (1, 1, 1, ...
Do you see what’s going wrong? I looked at my code for quite a while, then tried to redefine cons
.
cons <- function(h, t) {
force(h)
force(t)
function(cond) if (cond) h else t
}
prn_list(reverse(l))
# (3, 2, 1)
It worked!
To simplify the problem, consider the following code.
a <- 42
genf <- function(a) {
function() a
}
f1 <- genf(a)
f2 <- genf(a)
f1()
# [1] 42
a <- 43
f1()
# [1] 42
f2()
# [1] 43
The f1()
and f2()
return different values since f1
has already captured the original value,
while f2
still holds the promise of a
.