0% found this document useful (0 votes)
48 views

Lisp - Tears of Joy Part 6

The document discusses closures in Lisp programming. It explains that closures allow functions to have private, internal state in the form of closed variables that are only accessible to that function. This is done by taking a snapshot of a function that includes its free symbols, like variables, as closed variables unique to that function closure. The closure retains its state between calls by updating the values of its closed variables. The document provides an example of creating closures of a function that generates successive even numbers to demonstrate how each closure maintains its own isolated state.

Uploaded by

ksenthil77
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
48 views

Lisp - Tears of Joy Part 6

The document discusses closures in Lisp programming. It explains that closures allow functions to have private, internal state in the form of closed variables that are only accessible to that function. This is done by taking a snapshot of a function that includes its free symbols, like variables, as closed variables unique to that function closure. The closure retains its state between calls by updating the values of its closed variables. The document provides an example of creating closures of a function that generates successive even numbers to demonstrate how each closure maintains its own isolated state.

Uploaded by

ksenthil77
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

Write For Us

Submit Tips

Subscribe to Print Edition

Search

HOME

REVIEWS

HOW-TOS

CODING

INTERVIEWS

FEATURES

OVERVIEW

BLOGS

SERIES

IT ADMIN

Lisp: Tears of Joy, Part 6


By Vivek Shangari on November 1, 2011 in Coding, Developers 0 Comments

Search for:

Search

Get Connected

Lisp has been hailed as the worlds most powerful programming language but only the top percentile of programmers use it, because of its cryptic syntax and academic reputation. This is rather unfortunate, since Lisp isnt that hard to grasp. If you want to be among the crme de la crme, this series is for you. This is the sixth article in the series than began in the June 2011.

RSS Feed

Twitter

Closures
Suppose you want to write a function that saves some value it can examine the next time it runs. For example, functions that generate random numbers often use the previously generated random number to help generate the next. To do this, you need to lay aside a value such that a function can get at it next time. Its a risky proposition if you use a global variable or a property list to store such a value. If you get careless, and write another function that uses the same global variable or property, the two functions may interact in a way you never intended. It is even more problematic if you wish to have several incarnations of the same function around, each remembering what it computed previously, but not interfering with one another. Using a single, global object does not accommodate this. For example, suppose you want a function that will give you the next even number each time it is called. You could write this as a function that uses the global variable *evenum* to remember the last value it computed:
>( d e f u ng e n e r a t e e v e n ( ) ( s e t q* e v e n u m *( +* e v e n u m *2 ) ) ) G E N E R A T E E V E N >( s e t q* e v e n u m *0 ) 0 >( g e n e r a t e e v e n ) 2 >( g e n e r a t e e v e n ) 4 >( g e n e r a t e e v e n ) 6

LINUX For You on

Follow

+2,497

This works fine, but some other function could come along and clobber e v e n u min between calls. And we could not use g e n e r a t e e v e nto generate two sequences of even numbers simultaneously, independent of the other. The solution to this problem is to make a version of a function that has variables only it can

access. This is done by taking a function that contains some free symbols, and producing a new function in which all those free symbols are given their own, unique variables (free symbols are symbols used to designate variables within a function, but which are not formal parameters of that function). This is as if we replaced each free symbol with a new symbol, one we were certain no other function could ever use. When this new function is run, then, its free symbols will reference variables that no other function can reference. If the values of some of these variables are changed, their new values will be retained until the next time the function is run. However, changes to these variables will not have any effect outside of this function; moreover, the values of these variables cannot be accessed or altered outside of this function. In this example, we would like to produce a version of g e n e r a t e e v e nthat has its own private copy of the free variable * e v e n u m * . When we create this version of g e n e r a t e e v e n , we would like its version of * e v e n u m *to be initialised at whatever value * e v e n u m *currently has. No matter what happens subsequently to the original version, this will not affect the new version. When we run this new version, it would update its private copy of * e v e n u m * . This would not affect the version of * e v e n u m *known to the original function, but the new, updated copy of * e v e n u m *would be available to the new function the next time it is run. In other words, we take a sort of snapshot of a function, with respect to the current status of its free symbols. We can then manipulate this picture, rather than the function itself. The picture has about the same logical structure as the original, but if we change something in the picture, the original does not change. In fact, we should be able to take any number of such snapshots, and manipulate each one a bit differently. The alterations to each snapshot would serve to record its current state of affairs. Each snapshot could be looked at and altered quite independently of the others. When we take such a snapshot of a function, it is called a closure of that function. The name is derived from the idea that variables denoted by the free symbols of that function, normally open to the world outside that function, are now closed to the outside world. In Common Lisp, closures of functions are created by supplying the function function with a lambda expression as argument. If the free symbols of that lambda expression happen to be parameters of the function within which the lambda expression is embedded, function will return a snapshot of the function denoted by the lambda expression. This snapshot will contain its own variables corresponding to each of the lambda expressions free symbols. For example, we can use function to write a version of g e n e r a t e e v e nthat will produce a closure that includes the free symbol * e v e n u m *in the picture:
>( d e f u ng e n e r a t e e v e n( * e v e n u m * ) ( f u n c t i o n ( l a m b d a ( ) ( s e t q* e v e n u m *( +* e v e n u m *2 ) ) ) ) ) G E N E R A T E E V E N >( s e t qg e n e v e n 1( g e n e r a t e e v e n0 ) ) # < F U N C T I O N: L A M B D AN I L( S E T Q* E V E N U M *( +* E V E N U M *2 ) ) > >( f u n c a l lg e n e v e n 1 ) 2 >( f u n c a l lg e n e v e n 1 ) 4 >( f u n c a l lg e n e v e n 1 ) 6

Popular

Comments

Tag cloud

August 13, 2013 13 Comments Diksha P Gupta

India has immense under-utilised talent in the cloud security space


May 6, 2013 6 Comments Priyanka Sarkar

PHP Development: A Smart Career Move


June 20, 2013 3 Comments sophie-samuel

New and amazing features of Linux


June 20, 2013 3 Comments Priyanka Sarkar

What it Takes to be an Open Source Expert


May 6, 2013 1 Comments Deepti Sharma

A Simple guide to building your own Linux Kernel

When g e n e r a t e e v e nis called, Lisp creates a new variable corresponding to * e v e n u m * , as Lisp always produces new variables corresponding to the formal parameters of a function. Then the f u n c t i o nfunction returns a closure of the specified lambda expression. Since a new variable corresponding to * e v e n u m *exists at this time, the closure gets this version of * e v e n u m * as its own. When we exit this call to g e n e r a t e e v e n , no code can reference this variable that is closed off to the outside world. We save this closure by assigning it to the variable g e n e v e n 1 . Next, let us use f u n c a l lto invoke this function (f u n c a l lis like a p p l y , but expects the arguments right after the function name. In this case, there are none, as the lambda expression of g e n e r a t e e v e n , and hence, the closure produced from it, is a function of no arguments). Lisp prints out the closure as # < F U N C T I O N: L A M B D AN I L( S E T Q* E V E N U M *( +* E V E N U M * 2 ) ) > . Remember that the notation used to print closures is not a part of the Common Lisp standard. This is because it is not really meaningful to talk about printing a closure. Therefore, other

implementations of Common Lisp may use a different notation. We run this closure a couple of times, and each time it produces a new value. We can create as many independent closures of the same function as we like. For example, if we make another closure of g e n e r a t e e v e nright now
>( s e t qg e n e v e n 2( g e n e r a t e e v e n0 ) ) # < F U N C T I O N: L A M B D AN I L( S E T Q* E V E N U M *( +* E V E N U M *2 ) ) > >( f u n c a l lg e n e v e n 2 ) 2 >( f u n c a l lg e n e v e n 2 ) 4 >( f u n c a l lg e n e v e n 1 ) 8 >( f u n c a l lg e n e v e n 1 ) 1 0 >( f u n c a l lg e n e v e n 2 ) 6

This closure starts off with its version of * e v e n u m *at the value 0. Each closure has its own independent variable corresponding to the symbol * e v e n u m * . Therefore, a call to one function has no effect on the value of * e v e n u m *in the other.

Close that function!


When we close off the free symbols of a function, a new problem presents itself. The closed variables are inaccessible outside of the closure, so it would be difficult to write a set of functions that shared the same closed variable. For example, suppose we want to write a pair of functions where one returns the next even number, and the other the next odd number. However, we want them to work in tandem, so that a call to one advances the other. For example, if we call the even number generator three times in a row, it should return 2, 4, and 6. Then a call to the odd number generator should return 7. If we call it again, it should return 9. The next time we call the even number generator, it should return 10. It is easy to write a single pair of such functions. For example, we could do the following:
>( d e f u ng e n e r a t e e v e n ( ) ( s e t q* s e e d *( c o n d( ( e v e n p* s e e d * )( +* s e e d *2 ) ) ( t( 1 +* s e e d * ) ) ) ) ) G E N E R A T E E V E N >( d e f u ng e n e r a t e o d d ( ) ( s e t q* s e e d *( c o n d( ( o d d p* s e e d * )( +* s e e d *2 ) ) ( t( 1 +* s e e d * ) ) ) ) ) G E N E R A T E O D D >( s e t q* s e e d *0 ) 0 >( g e n e r a t e e v e n ) 2 >( g e n e r a t e o d d ) 3 >( g e n e r a t e e v e n ) 4 >( g e n e r a t e e v e n ) 6 >( g e n e r a t e o d d ) 7

However, if we want to make closures of these functions, we are in trouble. If we use closure to produce a closure of each function, each closure would get its own version of * s e e d * . The closure of g e n e r a t e e v e ncould not influence the closure of g e n e r a t e o d d , and the converse would also be true. But this is not what we want. The solution to this problem is to create closures of a number of functions in the same context. The functions closed together would share their variables with one another, but not with anyone else. For example, here is a function that creates a list of two closures, one of which generates even numbers and the other, odd:
>( d e f u ng e n e r a t e e v e n o d d( * s e e d * ) ( l i s t ( f u n c t i o n ( l a m b d a ( ) ( s e t q* s e e d *( c o n d( ( e v e n p* s e e d * )( +* s e e d *2 ) ) ( t( 1 +* s e e d * ) ) ) ) ) ) ( f u n c t i o n ( l a m b d a ( ) ( s e t q* s e e d *( c o n d( ( o d d p* s e e d * )( +* s e e d *2 ) ) ( t( 1 +* s e e d * ) ) ) ) ) ) ) ) G E N E R A T E E V E N O D D >( s e t qf n s( g e n e r a t e e v e n o d d0 ) ) ( # F U N C T I O N: L A M B D AN I L( S E T Q* S E E D *( C O N D( ( E V E N P* S E E D * )( +* S E E D *2 ) )( T( 1 +* S E E D * ) ) ) ) > ( # F U N C T I O N: L A M B D AN I L( S E T Q* S E E D *( C O N D( ( O D D P* S E E D * )( +* S E E D *2 ) )( T( 1 +* S E E D * ) ) ) ) > ) >( f u n c a l l( c a rf n s ) ) 2 >( f u n c a l l( c a rf n s ) ) 4 >( f u n c a l l( c a d rf n s ) )

5 >( f u n c a l l( c a d rf n s ) ) 7 >( f u n c a l l( c a rf n s ) ) 8

Some readers who arent actively using Lisp may have forgotten some of what we covered earlier in this series, so here is a brief explanation of the keywords used in the code above.
( c o n d( ( t e s te x p r e s s i o n * ) * ) ) Evaluates test expressions until one returns true. If that

test has no corresponding expressions, returns the value of the test. Otherwise, evaluates the expressions in order, returning the value(s) of the last. If no test returns true, returns nil.
c a r The primitive functions for extracting the elements of lists are c a rand c d r . The c a rof

a list is the first element, and the c d ris everything after the first element:
>( c a r` ( abc ) ) A >( c d r` ( abc ) ) ( BC )

c a d d r Common Lisp defines functions like c a d d r , which is an abbreviation for c a rof c d r

of c d r . All the functions of the form c _ x _ r , where _ x _is a string of up to four a sor d s , are defined in Common Lisp. With the possible exception of c a d r , which refers to the second element, it is not a good idea to use them in code that anyone else is going to read.
( e v e n pi ) Returns true if iis even; (o d d pi ) returns true if i is odd.

The call to g e n e r a t e e v e n o d dproduces a pair of closures, one for each call to function. This pair shares access to an otherwise private copy of the variable * s e e d * . Subsequent calls to
g e n e r a t e e v e n o d dwould create additional pairs of such closures, each pair sharing a

variable all its own.

Related Posts:
Lisp: Tears of Joy, Part 5 Lisp: Tears of Joy, Part 3 Joy of Programming: Scope, Lifetime and Visibility in C Lisp: Tears of Joy, Part 7 Loading Library Files in C++
Tags: Common Lisp, even numbers, free symbols, lambda expression, LFY November 2011, Lisp, Lisp: Tears of Joy series, Programming Language, random numbers, sequences, syntax, variables

Article written by:


Vivek Shangari
The author is a hard-core hacker, if there ever was one. He always thinks programs, and holds a piece of code in his head all the time. His favourite past-time is to stop random strangers on the street and start talking about the benefits of open source over proprietary software, till they agree to switch sides, or threaten to jump off the nearest building. Connect with him: Website

Previous Post

Next Post

Device Drivers, Part 12: USB Drivers in Linux Continued

GDB: Logging Function Parameters, Part 1

Reviews

How-Tos

Coding

Interviews

Features

Overview

Blogs

Search
Popular tags
Linux , ubuntu, Java, MySQL, Google, python, Fedora, Android, PHP, C, html, w eb applications , India, Microsoft, unix , Window s , Red Hat, Oracle, Security , Apache, xml, LFY April 2012, FOSS, GNOME, http, JavaScript, LFY June 2011, open source, RAM, operating systems

For You & Me Developers Sysadmins Open Gurus CXOs Columns

All published articles are released under Creative Commons Attribution-NonCommercial 3.0 Unported License, unless otherw ise noted.

LINUX For You is pow ered by WordPress, w hich gladly sits on top of a CentOS-based LEMP stack. .

You might also like