<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2737806069624177704</id><updated>2012-02-16T16:50:02.596-08:00</updated><category term='lisp'/><category term='macros'/><title type='text'>(make-instance 'common-lisp-blog)</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://makeinstance.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2737806069624177704/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://makeinstance.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jimmy</name><uri>http://www.blogger.com/profile/12920882839335295872</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>1</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2737806069624177704.post-2472942059757390114</id><published>2008-03-23T07:08:00.000-07:00</published><updated>2008-03-23T11:53:51.230-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='macros'/><title type='text'>Macro Magic</title><content type='html'>This is a neat trick that I discovered the other day while mucking around in Lisp Land, and I figured I'd share it with my fellow Common Lisp programmers:&lt;br /&gt;&lt;br /&gt;Now, we all know how macros can allow us to seamlessly extend Lisp so that our own code looks the same as the language primitives.  However, not everyone knows just how seamless these extensions can get.&lt;br /&gt;&lt;br /&gt;We're going to develop a series of macros that allow us to determine how many arguments a function takes.  Our goal is to be able to run the following code:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defun test (a b)&lt;br /&gt;  (+ a b))&lt;br /&gt;&lt;br /&gt;(num-args test)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And have &lt;tt&gt;num-args&lt;/tt&gt; correctly report &lt;tt&gt;2&lt;/tt&gt; as the number of arguments for &lt;tt&gt;test&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;Obviously, our first step should be to get the definition of &lt;tt&gt;defun&lt;/tt&gt; from the &lt;tt&gt;common-lisp&lt;/tt&gt; package out of our way so we can create our own.  This is done by creating a new package:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defpackage :test&lt;br /&gt;  (:use :common-lisp)&lt;br /&gt;  (:shadow :defun))&lt;br /&gt;&lt;br /&gt;(in-package :test)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The only thing special about this package definition is that it shadows the &lt;tt&gt;defun&lt;/tt&gt; symbol, so it is undefined in our &lt;tt&gt;test&lt;/tt&gt; package.  Fortunately, we'll still be able to access the symbol in the &lt;tt&gt;common-lisp&lt;/tt&gt; package when we need it.&lt;br /&gt;&lt;br /&gt;We're going to need a place to store the argument list for each function that is defined in our new package.  We'll be using a hash table for this purpose:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defvar *arg-lists* (make-hash-table))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now we get to the main event:  the actual &lt;tt&gt;defun&lt;/tt&gt; macro:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defmacro defun (name varlist &amp;rest body)&lt;br /&gt;  `(progn&lt;br /&gt;     (common-lisp:defun ,name ,varlist ,@body)&lt;br /&gt;     (setf (gethash ',name *arg-lists*) ',varlist)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Despite being a short macro, it manages to get a lot of work done.  Not only does it define a function just like a normal &lt;tt&gt;defun&lt;/tt&gt; would, but it also stores the function's argument list in our hash table.  The trick is in calling the &lt;tt&gt;common-lisp&lt;/tt&gt; package's version of &lt;tt&gt;defun&lt;/tt&gt; while simultaneously defining our own.&lt;br /&gt;&lt;br /&gt;Now all that's left to do is provide a way of retrieving a function's argument list and finding its length.  We'll do this with another macro:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defmacro num-args (name)&lt;br /&gt;  `(length (gethash ',name *arg-lists*)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Finally, you can evaluate the code at the beginning at get the correct response of &lt;tt&gt;2&lt;/tt&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defun test (a b)&lt;br /&gt;  (+ a b))&lt;br /&gt;&lt;br /&gt;(num-args test)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So there you have it.  A normally complex bit of introspection added to Common Lisp in 11 lines of code, thanks to our trusty macros.  I'll leave it as an exercise to the reader to extend this program:  it can't determine how many arguments a macro takes, and it counts special words in the argument list like &lt;tt&gt;&amp;rest&lt;/tt&gt; as arguments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2737806069624177704-2472942059757390114?l=makeinstance.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://makeinstance.blogspot.com/feeds/2472942059757390114/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2737806069624177704&amp;postID=2472942059757390114' title='37 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2737806069624177704/posts/default/2472942059757390114'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2737806069624177704/posts/default/2472942059757390114'/><link rel='alternate' type='text/html' href='http://makeinstance.blogspot.com/2008/03/macro-magic.html' title='Macro Magic'/><author><name>Jimmy</name><uri>http://www.blogger.com/profile/12920882839335295872</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>37</thr:total></entry></feed>
