Closure的R实现与其他函数语言不同,这使得它的行为类似于C#等命令式语言?

时间:2013-04-29 14:08:07

标签: c# r f# functional-programming closures

R是一种函数式语言,但在下列情况下它的行为类似于C#而不是F#。

在R

f <- function() x
x <- 15
f() // prints 15
x <- 20 // shadowing
f() // prints 20

在C#中

int j = 15;
Action<string> funs = x => Console.WriteLine(j);
funs("foo"); // prints 15
j = 20; // mutate
funs("foo"); // prints 20
在F#中

let x = 15
let f y = x
f() // prints 15
let x = 20 // shadowing, to mimic R (purely functional)
f() // prints 15, not 20

在R中,该示例违反了我对“闭包关闭变量,无论是按值还是按引用”的理解。在C#中,闭包通过引用关闭变量。在F#中,因为变量是不可变的并不重要。但是在R中,似乎闭包只关闭了符号名称(某些不是因为它确实发生变化;不是通过引用,因为变量是不可变的,它不是变异的,而是阴影的。)

那么,有三种方法可以关闭变量,按值,按引用和按名称

在这种情况下,还有其他功能语言的行为吗?

在这里,hadley book中定义的动态查找似乎可以解释一下,但我找不到任何其他资源都有“动态查找”这个词。

2 个答案:

答案 0 :(得分:1)

我不确定我是否完全理解你的问题,但也许这些例子有助于说明一个值如何定义(但这些可能不是很好的例子!)但我强烈建议你阅读{{ 3}} R语言定义的部分(实际上我应该再去读一遍):

# Define default value for x in function definition
f <- function( x = 15 ) x
f()
#[1] 15

# Assign value to x in .GlobalEnv
x <- 20

# But x is found in the environment of the function call because we already defined it there, so value we assigned inside the function is returned
f()
#[1] 15

# Now we pass an object, x to the function which causes it to search up the calling stack for an 'object' called x
f(x)
#[1] 20

# In this example we use 'get' to search for the object. In the help page it states:
# The default is to search from the current environment of the call to 'get'
f <- function() get( "x" )
f()
[1] 20

# But we can specify an environment to search in
# In this case we specify an environment where x was not defined
# and it is not found
f<- function() { pos <- sys.nframe()+1 ; get("x" ,  envir = as.environment(pos) ) }
f()
#Error in get("x", envir = as.environment(2)) : object 'x' not found

答案 1 :(得分:0)

来自Scheme,我没有看到混乱。

,例如,使用chibi-scheme(R7RS):

$ chibi-scheme
> (define f (lambda () x))
WARNING: reference to undefined variable: x
> (define x 15)
> (f)
15
> (define x 20)
> (f)
20

对于任何合规的Scheme版本应该是相同的(至少在Guile和MIT / GNU Scheme中有效)。 REPL可能与编译器不同,但即使您编写了上述内容并编译,它也会使用符号表并在解析文件后解析引用。它仍然有效。

f引用变量x指定的内存位置的值。执行f <- 15f <- 20后,您需要更新,而不是参考或位置。

我可能错了(或使用技术术语不正确),但我仍然觉得这并不奇怪。