DarkMatter in Cyberspace
  • Home
  • Categories
  • Tags
  • Archives

Closure in Different Languages


The following code snippets compare closures in several languages.

First is closure in javascript. Here I use nvm to run javascript code.

$ cat closure.js
function extent() {
    var n = 0;
    return function() {
        n++;
        console.log("n=" + n);
    }
}

extent()();
extent()();
f = extent();
console.log("-----");
//console.log(extent.uniqueId());
f();
f();

$ nvm alias default 0.10
$ nvm run closure.js
Running node v0.10.30
n=1
n=1
-----
n=1
n=2

In above example, the closure is function() { n++; console.log... }. It's bound to variable "f". The local variable "n" is "closed" into closure. Its lifetime is the same with "f". So after the first execution of f, its inner state is saved.

For Python, nested function can only access variables in outer scope, but can't reassign (modify) them. So I use list as a workaround. In Python 3, there is a new keyword "nonlocal" to remove this restriction.

$ cat closure.py2.py
def extent():
    n = [0]
    def afun():
        n[0] += 1
        print('n=' + str(n[0]))
    return afun

extent()()
extent()()
print('-----')
f = extent()
f()
f()
print("type of f is %s, its id is %d" % (type(f), id(f)))

$ python closure.py2.py 
n=1
n=1
-----
n=1
n=2
type of f is <type 'function'>, its id is 140403684898408

$ cat closure.py3.py
def extent():
    n = 0
    def afun():
        nonlocal n
        n += 1
        print('n=' + str(n))
    return afun

extent()()
extent()()
f = extent()
print('----')
f()
f()
print("type of f is %s, its id is %d" % (type(f), id(f)))

[0] python3 closure.py3.py
n=1
n=1
----
n=1
n=2
type of f is <class 'function'>, its id is 139914425096528

The Ruby environment used here is RVM. Ruby version is 2.1.2.

$ rvm use 2.1.2 --default
$ cat closure.rb
def extent
    n = 0
    lambda {
        n += 1
        printf "n=%d\n", n
    }
end

extent().call()
extent().call()
f = extent()
puts '------'
f.call()
f.call()
puts "class of f is #{f.class.name}, its id is #{f.object_id}"

$ ruby closure.rb
n=1
n=1
------
n=1
n=2
class of f is Proc, its id is 6724520

Two versions of Scala, define functions via "def" and "val" give different results:

$ diff *.scala
1c1
< def extent = {
---
> val extent = {

$ cat closure-def.scala
def extent = {
    var n = 0
    () => {
        n += 1
        println("n=" + n)
    }
}

extent()
extent()
val f = extent
println("------")
f()
f()
println(s"Class of f is ${f.getClass}, its id is ${f.hashCode}")

$ scala closure-def.scala
n=1
n=1
------
n=1
n=2
Class of f is class Main$$anon$1$$anonfun$extent$1, its id is 8970973

$ cat closure-val.scala 
val extent = {
    var n = 0
    () => {
        n += 1
        println("n=" + n)
    }
}

extent()
extent()
val f = extent
println("------")
f()
f()
println(s"Class of f is ${f.getClass}, its id is ${f.hashCode}")
$ scala closure-val.scala 
n=1
n=2
------
$ scala closure-val.scala 
n=1
n=2
------
n=3
n=4
Class of f is class Main$$anon$1$$anonfun$1, its id is 8970973


Published

Aug 20, 2014

Last Updated

Aug 20, 2014

Category

Tech

Tags

  • closure 3
  • javascript 11
  • python 136
  • ruby 9
  • scala 20

Contact

  • Powered by Pelican. Theme: Elegant by Talha Mansoor