Closures in R and Python

Posted on So 05 April 2015 in Blog

Seems like my "intermediate" Python knowledge benefits from (re-)learning R again with this Coursera-MOOC. Stumbling over closures from Wes McKinney's "Python for Data Analysis"-Book, here is a short comparison of closures in R and Python, respectively:

Closures in Python

In Python, closures are function that return function (dynamically), while preserving/accessing the namespace of the "caller"-function and having access to this "outer" function enviroment ("referencing enviroment")

1
2
3
4
5
6
7
8
9
def make_power(n):
    #Set 'n' as the power and create the n**power-function

    def power_by_n(b):
        #this function has access to the 'make_power'namespace and arguments --> n
        #Level the base by the power of 'n'
        return b**n
    #return the custom-power function
    return power_by_n

With this closure, one could use it as like this:

1
2
3
4
5
cubic = make_power(3)
square = make_power(2)

print cubic(10)  #-->1000
print square(10) #-->100

One could inspect the closure-functions, f.e. via it's attributes:

1
2
cubic.func_closure[0].cell_contents
>>>3

Closures in R

Similar to python (of course with more curly brackets), closures are quite simple in R.

1
2
3
4
5
6
7
8
9
make.power <- function(n) {
            pow <- function(x) {
                    x^n
                 }
            pow
            }

cube <- make.power(3)
square <- make.power(2)

Again, inspection is easy using the 'enviroment','ls' and 'get'-functions.

1
ls(environment(cube))

Although beeinf very similar, one should keep possible different scoping rules in R and Python in mind. As a first guess and because they are both using lexical scoping, they do not seem to differ that much (but I might be wrong!!):

In R, this would throw an 'undefined'-error (as well as in Python; the R code is used from the Coursera course mentioned above):

1
2
3
4
5
6
7
8
f <- function(x) {
            y <- 2
            y^2 + g(x)
                }
g <- function(x) {
            x*y
                }
f(3)

This lexical-scoping is used by python as well (maybe it's not pure lexical scoping, but others should argue wether Python is call-by-reference or whatever, has scoping xy and so on; this is a handy & short explanation of Python scoping rules; and that might be worth reading as well.