0% found this document useful (0 votes)
91 views4 pages

Lisp - Tears of Joy Part 7

This document summarizes an article about macros in the Lisp programming language. It discusses how macros allow generating Lisp code and are expanded during compilation. It provides an example of a lookup-sin macro that generates a sin lookup table at compile-time to improve runtime performance for trigonometric functions. It also discusses macros that define other macros and defines a defsynonym macro to create synonyms for functions and special forms.

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)
91 views4 pages

Lisp - Tears of Joy Part 7

This document summarizes an article about macros in the Lisp programming language. It discusses how macros allow generating Lisp code and are expanded during compilation. It provides an example of a lookup-sin macro that generates a sin lookup table at compile-time to improve runtime performance for trigonometric functions. It also discusses macros that define other macros and defines a defsynonym macro to create synonyms for functions and special forms.

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/ 4

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 7


By Vivek Shangari on December 30, 2011 in Coding, Developers 1 Comment

Search for:

Search

Get Connected RSS Feed Twitter

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 seventh article in the series, which began in June 2011.

Macros cant get enough of them!


You already know from my previous articles that macros are Lisp programs that generate other Lisp programs. The generated Lisp code has fully parenthesised notation, and so does the macro that generates the code. In the simplest case, a macro substitutes forms within a template, clearly establishing a visual correspondence between the generating code and the generated code. Complex macros can use the full power of the Lisp language to generate code according to the macro parameters; often, a template form is wrapped in code that constructs appropriate subforms, but even this approach is just a typical pattern of use, and not a requirement (or restriction) of the Lisp macro facility. To refresh our memories, lets examine the mechanism by which the Lisp system translates code generated by a macro. You define a macro with a d e f m a c r oform; d e f m a c r ois like d e f u n , but instead of returning values, the body of the d e f m a c r oreturns a Lisp form. Your program calls a macro the same way it calls a function, but the behaviour is quite different. First, none of the macros parameters are evaluated ever. Macro parameters are bound literally to the corresponding arguments in the macro definition. If you pass ( *7( +32 ) )to a macro, the argument in the body of the macro definition is bound to the literal list ( *7( +32 ) )and not the value 35. Next, the macro expander is invoked, receiving all of the actual parameters bound to their corresponding arguments as named by the d e f m a c r oform. The macro expander is merely the

LINUX For You on

Follow

+2,501

body of the d e f m a c r oform, which is just Lisp code; the only catch is that the Lisp system expects the macro expander to return a Lisp form. The Lisp system then evaluates whatever form the macro expander returns. A Lisp implementation may expand macros at different times. A macro could be expanded just once, when your program is compiled. Or it could be expanded on first use as your program runs, and the expansion could be cached for subsequent reuse. A properly written macro will behave the same under all of these implementations. Lets explore a real-world example of using a macro to extend Lisp into the problem domain. In addition to providing a macro expander, our new macro will automatically generate an environment that will be referenced by the expander. Our example will show how to move computations from run-time to compile-time, and how to share information computed at compiletime. Lets say youre working on an interactive game that makes heavy use of the trigonometric function sin r in computing player motion and interaction. Youve already determined that calling the Lisp function sin is too time-consuming; you also know that your program will work just fine with approximate results for the computation of sin r. Youd like to define a lookup-sin macro to do the table lookup at runtime and also hide the details of table generation, which would just clutter your programs source code. Your macro will be invoked as (lookup-sin radians divisions), where radians is always in the range of zero to one-half pi, and divisions is the number of discrete values available as the result of lookup-sin. At runtime, the macro expander will just compute the index into a lookup table, and return the value from the table. The table will be generated at compile-time (on most Lisp systems). Furthermore, only one table will ever be generated for a given value of divisions in the macro call.

Find us on Facebook

Open Source For You


Like 252,987 people like Open Source For You.

F acebook social plugin

Popular

Comments

Tag cloud

August 13, 2013 16 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 ; ;T h i si sw h e r ew ec a c h ea l lo ft h es i n et a b l e sg e n e r a t e dd u r i n gc o m p i l a t i o n . ; ;T h et a b l e ss t a ya r o u n da tr u n t i m es ot h e yc a nb eu s e df o rl o o k u p s . ( d e f v a r* s i n t a b l e s *( m a k e h a s h t a b l e ) " Ah a st a b l eo ft a b l e so fs i n ev a l u e s .T h eh a s hi sk e y e db yt h en u m b e ro fe n t r i e si ne a c hs i n et a b l e . " )

; ;T h i si sah e l p e rf u n c t i o nf o rt h el o o k u p s i nm a c r o .I ti su s e do n l ya tc o m p i l e ; ;t i m e . ( d e f u ng e t s i n t a b l e a n d i n c r e m e n t( d i v i s i o n s ) " R e t u r n sas i n el o o k u pt a b l ea n dt h en u m b e ro fr a d i a n sq u a n t i s e db ye a c he n t r yi nt h et a b l e .T a b l e so fag i v e ns i z ea r er e u s e d .At a b l ec o v e ( l e t( ( t a b l e( g e t h a s hd i v i s i o n s* s i n t a b l e s *: n o n e ) ) ( i n c r e m e n t( /p i2d i v i s i o n s ) ) ) ( w h e n( e qt a b l e: n o n e ) ; ;U n c o m m e n tt h en e x tl i n et os e ew h e nat a b l eg e t sc r e a t e d . ; ;( p r i n t` | M a k i n gn e wt a b l e | ) ( s e t qt a b l e ( s e t f( g e t h a s hd i v i s i o n s* s i n t a b l e s * ) ( m a k e a r r a y ( 1 +d i v i s i o n s ) : i n i t i a l e l e m e n t1 . 0 ) ) ) ( d o t i m e s( id i v i s i o n s ) ( s e t f( a r e ft a b l ei ) ( s i n( *i n c r e m e n ti ) ) ) ) ) ( v a l u e st a b l ei n c r e m e n t ) ) ) ; ;M a c r oc a l l st h eh e l p e ra tc o m p i l et i m e ,a n dr e t u r n sa nA R E Ff o r mt od ot h e ; ;l o o k u pa tr u n t i m e . ( d e f m a c r ol o o k u p s i n( r a d i a n sd i v i s i o n s ) " R e t u r nas i n ev a l u ev i at a b l el o o k u p . " ( m u l t i p l e v a l u e b i n d( t a b l ei n c r e m e n t ) ( g e t s i n t a b l e a n d i n c r e m e n td i v i s i o n s ) ` ( a r e f ,t a b l e( r o u n d ,r a d i a n s ,i n c r e m e n t ) ) ) )

Let us examine what is happening here. When this program runs, it executes just a r e f (and associated round) to look up the sin r value.
>( p p r i n t( m a c r o e x p a n d 1` ( l o o k u p s i n( /p i4 )5 0 ) ) )

( A R E F# ( 0 . 0 D 00 . 0 3 1 4 1 0 7 5 9 0 7 8 1 2 8 2 9 D 00 . 0 6 2 7 9 0 5 1 9 5 2 9 3 1 3 3 8 D 00 . 0 9 4 1 0 8 3 1 3 3 1 8 5 1 4 3 3 D 00 . 1 2 5 3 3 3 2 3 3 5 6 4 3 0 4 2 6 D 00 . 1 5 6 4 3 4 4 6 5 0 4 0 2 3 0 8 7 D 00 . 1 8 7 3 8 1 3 1 4 5 8 5 7 2 4 6 3 D 0 . 3 0 9 0 1 6 9 9 4 3 7 4 9 4 7 4 D 00 . 3 3 8 7 3 7 9 2 0 2 4 5 2 9 1 4 D 00 . 3 6 8 1 2 4 5 5 2 6 8 4 6 7 8 D 00 . 3 9 7 1 4 7 8 9 0 6 3 4 7 8 0 6 D 00 . 4 2 5 7 7 9 2 9 1 5 6 5 0 7 2 7 D 00 . 4 5 3 9 9 0 4 9 9 7 3 9 5 4 6 8 D 00 . 4 8 1 7 5 3 6 7 4 0 . 5 8 7 7 8 5 2 5 2 2 9 2 4 7 3 1 D 00 . 6 1 2 9 0 7 0 5 3 6 5 2 9 7 6 5 D 00 . 6 3 7 4 2 3 9 8 9 7 4 8 6 8 9 8 D 00 . 6 6 1 3 1 1 8 6 5 3 2 3 6 5 1 8 D 00 . 6 8 4 5 4 7 1 0 5 9 2 8 6 8 8 7 D 00 . 7 0 7 1 0 6 7 8 1 1 8 6 5 4 7 6 D 00 . 7 2 8 9 6 8 6 2 0 . 8 0 9 0 1 6 9 9 4 3 7 4 9 4 7 5 D 00 . 8 2 7 0 8 0 5 7 4 2 7 4 5 6 1 8 D 00 . 8 4 4 3 2 7 9 2 5 5 0 2 0 1 5 1 D 00 . 8 6 0 7 4 2 0 2 7 0 0 3 9 4 3 6 D 00 . 8 7 6 3 0 6 6 8 0 0 4 3 8 6 3 7 D 00 . 8 9 1 0 0 6 5 2 4 1 8 8 3 6 7 8 D 00 . 9 0 4 8 2 7 0 5 . . . ) ( R O U N D( /P I4 )0 . 0 3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 4 D 0 ) )

Note that the macro call makes no mention of a lookup table. Tables are generated as needed by (and for) the compiler.
>( l o o k u p s i n( /p i4 )5 0 ) 0 . 7 0 7 1 0 6 7 8 1 1 8 6 5 4 7 6 D 0

In the macro expansion, the # ( . . . )is the printed representation of the lookup table for 50 divisions of the quarter circle. This table is stored in the * s i n t a b l e s *hash table, where it is shared by every macro call to ( l o o k u p s i na n g l e5 0 ) . We dont even have to do a hash lookup at runtime, because the macro expander has captured the free variable table from the multiple-value-bind form in l o o k u p s i n .

Macros that define macros


Macros that define macros are used infrequently, partly because its hard to think of a good use for this technique, and partly because its difficult to get right. The following macro, based on an example in Paul Grahams book On Lisp, can be used to define synonyms for the names of Lisp functions, macros, and special forms.
>( d e f m a c r od e f s y n o n y m( o l d n a m en e wn a m e ) " D e f i n eO L D N A M Et ob ee q u i v a l e n tt oN E W N A M Ew h e nu s e di nt h ef i r s tp o s i t i o no faL i s pf o r m . " ` ( d e f m a c r o ,n e w n a m e( & r e s ta r g s ) ` ( , ` , o l d n a m e ,@ a r g s ) ) ) D E F S Y N O N Y M >( d e f s y n o n y mm a k e p a i rc o n s ) M A K E P A I R >( m a k e p a i r` a` b ) ( A.B )

Macros are always a little bit dangerous because code containing a macro call does not automatically get updated if you change the definition of the macro. You can always establish your own convention to help you remember that you need to recompile certain code after you change a macro definition. But theres always the possibility that youll forget, or make a mistake. Ultimately, the likelihood that youll inadvertently end up with code that was compiled with an old version of a macro is directly proportional to how often youre likely to change the macro. A macro like d e f s y n o n y mpractically begs to be used again and again as you generate new code. If you change your mind about the old name to associate with a given new name, all of your previously compiled code will still refer to the old name that you had decided upon earlier. Ill leave you here to have fun with your macros. In the next article, well take a peek into Common Lisp Object System (CLOS) which allows you to build very sophisticated object-based systems. If you care to code with a strongly object-oriented mindset, you will probably find all the OOP language functionality you need in Common Lisp. CLOS has many advanced object-oriented features that you wont find in many other places. Because of this, CLOS has often been used as a research tool for studying OOP ideas.

Related Posts:
Lisp: Tears of Joy, Part 5 Lisp: Tears of Joy, Part 10 Lisp: Tears of Joy, Part 6 Lisp: Tears of Joy, Part 3 Lisp: Tears of Joy, Part 8
Tags: AREF, CLOS, Common Lisp, Languages, LFY December 2011, Lisp, lisp code, lisp programs, Lisp: Tears of Joy series, macro definition, Macros, object-based systems, Paul Graham, programming, syntax

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

CodeIgniter: Form APIs, Validations & Pagination Techniques

FOSS is __FUN__: FOSS Meets the MBA

ALSO ON LINUX FOR YOU

What's this?

India has immense under-utilised talent in the cloud 16 comments Code Sport
1 comment

Getting Your First Job

1 comment

File Systems A Semester Project-II, Part-19 6 comments The Semester Project-IV File Systems: Formatting a 3 comments Introducing Samba 4 Now, Even More Awesomeness 3 comments

Linux Professionals in High Demand


10 comments

Cyber Attacks Explained: The Botnet Army 1 comment

1 comment Leave a message...


Newest Community Linux For Y ou

Share
2 years ago

Bessem Rebai Kindly post unrelated comments separately -- that is open a new thread. While your announcement is great, we fail to understand how it's related to the article on Lisp that's shared here.
Reply Share

C o m m e n t fe e d

Su b s cri b e vi a e m a i l

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