CSC/ECE 517 Fall 2010/ch1 1b YL

From Expertiza_Wiki
Jump to navigation Jump to search

Closures in Ruby vs. closures in other languages

Closures

Before discussing semantic and implementation differences of closure implementation in different languages, closures should be discussed first.

A closure is a first-class function with free variables that are bound in the lexical environment. Closures:Wikipedia

Such a function is said to be "closed over" its free variables. In this definition first-class function is the function which is treated as first-class objects. Specifically, this means that the language supports constructing new functions during the execution of a program, storing them in data structures, passing them as arguments to other functions, and returning them as the values of other functions. [1]

So closure can be explained as nothing but the behavior or in programming language function which can be passed around like any other argument and still remembering the original context where these functions are declared first. This way it breaks out of the standard function concept where the variables inside functions can be referenced within the scope of the function. However, in closures these variables can be referred out of the scope of the local functions. This ability of accessing original context makes closure different from normal objects.

Closure concept can be illustrated with the example in JavaScript.

// Return a list of all employees with at least 'threshold' salary.

function highlyPaidEmployees(threshold) 

{

return empList.filter( function (emp) { return emp.salary >= threshold; } );

}


In above javascript function highlyPaidEmployees, another anonymous function is defined. This function is passed to the Array.filter method with free variable threshold. This free variable is assigned the value that is passed during the function call of highlyPaidEmployees. Thus the anonymous function defined inside is called repeatedly by filter method with free variable threshold having assigned the value passed to the highlyPaidEmployees. This follows both the properties defined in the closure definition. One is that the function is passed as an argument and function is able to access free variable out of its context.

Closure is supported by many languages. Ruby is famous for extensive use of closure. In next few sections comparison of closure implementation is different languages is done.

Basis of differences in implementations of closure

Even though many languages support closure concepts there are significant differences in closure implementation in different languages. Some languages support closure concepts partially. Considering all these following are the point on the basis of which closures in different languages can be differed.

  • First-class function - Whether language supports passing function as an argument
  • Out of context reference - Whether language supports refering variable out of scope of its context
  • Copy of variable or reference to a variable location - If language supports Out of context reference of variable then how is it implemented. Whether variable value is copied or same copy of variable is referred.
  • Function currying - It is the technique by which function with multiple arguments can be called as a function with chain of functions each with single argument. Function Currying Some languages support it and some not.
  • Control structure using closure - Whether language supports closure for control structure or not.
  • less lines of code - If language supports control structure using closure then it reduces lines of code considerably.

Closures in other languages

Closures in Ruby

Closures in Lisp

Closures in ML

Closures in C

The C language provides function pointers, which allow you to pass functions as arguments to other functions. However, functions in C cannot have free variables; all variables must be known at compile time, which reduces the expressiveness of function pointers as an abstractive mechanism.

The C language does not support closures directly, but it has some extensions which add closures like functionality. Nested functions are similar to closures.

A nested function is a function defined inside another function. It's scope is limited to the enclosing function. The nested function can access all the variables of the containing function that are visible at the point of its definition. This is called lexical scoping.

    int arrayProcess (int *array, int offset, int size)
    {
      int arrayAccess (int *array, int index)
        { return array[index + offset]; }
      int i;
      /* ... */
      for (i = 0; i < size; i++)
        /* ... */ access (array, i) /* ... */
    }

Here the inner function arrayAccess can refer to outer function's variable 'offset'.

Nested function definitions are permitted within functions in the places where variable definitions are allowed; that is, in any block, mixed with the other declarations and statements in the block.

It is possible to call the nested function from outside the scope of its name by storing its address or passing the address to another function:

    hack (int *array, int size)
    {
      void store (int index, int value)
        { array[index] = value; }
    
      intermediate (store, size);
    }

Here, the function intermediate receives the address of store as an argument. If intermediate calls store, the arguments given to store are used to store into array. But this technique works only so long as the containing function (hack, in this example) does not exit.

If you try to call the nested function through its address after the containing function has exited, all hell will break loose. If you try to call it after a containing scope level has exited, and if it refers to some of the variables that are no longer in scope, you may be lucky, but it's not wise to take the risk. If, however, the nested function does not refer to anything that has gone out of scope, you should be safe.

Closures in C++

Closures in Java

Closures in Javascript

Comparison

Conclusion