Lisp - Tears of Joy Part 7
Lisp - Tears of Joy Part 7
Submit Tips
Search
HOME
REVIEWS
HOW-TOS
CODING
INTERVIEWS
FEATURES
OVERVIEW
BLOGS
SERIES
IT ADMIN
Search for:
Search
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.
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
Popular
Comments
Tag cloud
; ;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 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
Previous Post
Next Post
What's this?
India has immense under-utilised talent in the cloud 16 comments Code Sport
1 comment
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
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
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.