<?xml version="1.0" encoding="utf-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Lisp Macro Example</title>
	<atom:link href="http://www.nonperiodic.net/blog/2005/06/12/lisp-macro-example/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.nonperiodic.net/blog/2005/06/12/lisp-macro-example/</link>
	<description>Nonperiodic Central Trajectory</description>
	<lastBuildDate>Wed, 10 Jun 2009 09:47:09 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: amjad</title>
		<link>http://www.nonperiodic.net/blog/2005/06/12/lisp-macro-example/comment-page-1/#comment-70233</link>
		<dc:creator>amjad</dc:creator>
		<pubDate>Mon, 05 Mar 2007 12:11:07 +0000</pubDate>
		<guid isPermaLink="false">/?p=160#comment-70233</guid>
		<description>dear
iam looking for how to write a lisp to raed a data from text file (.prn)for example . please i f you can help me .email me</description>
		<content:encoded><![CDATA[<p>dear<br />
iam looking for how to write a lisp to raed a data from text file (.prn)for example . please i f you can help me .email me</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Emre Sevinc</title>
		<link>http://www.nonperiodic.net/blog/2005/06/12/lisp-macro-example/comment-page-1/#comment-3786</link>
		<dc:creator>Emre Sevinc</dc:creator>
		<pubDate>Tue, 26 Jul 2005 20:33:54 +0000</pubDate>
		<guid isPermaLink="false">/?p=160#comment-3786</guid>
		<description>Also there is an error in your dofile macro, you forgot to use a comma which must take place just before filename in `(with-open-file (stream filename) ...

If you macroexpand-1 it:

CL-USER&gt; (macroexpand-1 &#039;(dofile (line &quot;foo.txt&quot;) (princ line)))

(WITH-OPEN-FILE (STREAM FILENAME)
  (DO ((LINE (READ-LINE STREAM NIL NIL) (READ-LINE STREAM NIL NIL)))
      ((NULL LINE))
    (PRINC LINE)))
T

As you may notice in the above expansion, there&#039;s no &quot;foo.txt&quot;. However if you put the comma before the filename: (with-open-file (stream ,filename) ...

Then you have:

CL-USER&gt; (macroexpand-1 &#039;(dofile (line &quot;foo.txt&quot;) (princ line)))
(WITH-OPEN-FILE (STREAM &quot;foo.txt&quot;)
  (DO ((LINE (READ-LINE STREAM NIL NIL) (READ-LINE STREAM NIL NIL)))
      ((NULL LINE))
    (PRINC LINE)))
T

Another point is that, you don&#039;t need the third NIL in function read-line unless you want to be very explicit. The eof-value defaults to NIL according to ANSI Common Lisp standard: http://www.lisp.org/HyperSpec/Body/fun_read-line.html

Also the with-gensyms (and looping) version is included somewhere in http://paste.lisp.org/display/10220#4

BTW, no I&#039;m not a Lisp guru just pointing to the wisdom of #lisp :)</description>
		<content:encoded><![CDATA[<p>Also there is an error in your dofile macro, you forgot to use a comma which must take place just before filename in `(with-open-file (stream filename) &#8230;</p>
<p>If you macroexpand-1 it:</p>
<p>CL-USER&gt; (macroexpand-1 &#8216;(dofile (line &#8220;foo.txt&#8221;) (princ line)))</p>
<p>(WITH-OPEN-FILE (STREAM FILENAME)<br />
  (DO ((LINE (READ-LINE STREAM NIL NIL) (READ-LINE STREAM NIL NIL)))<br />
      ((NULL LINE))<br />
    (PRINC LINE)))<br />
T</p>
<p>As you may notice in the above expansion, there&#8217;s no &#8220;foo.txt&#8221;. However if you put the comma before the filename: (with-open-file (stream ,filename) &#8230;</p>
<p>Then you have:</p>
<p>CL-USER&gt; (macroexpand-1 &#8216;(dofile (line &#8220;foo.txt&#8221;) (princ line)))<br />
(WITH-OPEN-FILE (STREAM &#8220;foo.txt&#8221;)<br />
  (DO ((LINE (READ-LINE STREAM NIL NIL) (READ-LINE STREAM NIL NIL)))<br />
      ((NULL LINE))<br />
    (PRINC LINE)))<br />
T</p>
<p>Another point is that, you don&#8217;t need the third NIL in function read-line unless you want to be very explicit. The eof-value defaults to NIL according to ANSI Common Lisp standard: <a href="http://www.lisp.org/HyperSpec/Body/fun_read-line.html" rel="nofollow">http://www.lisp.org/HyperSpec/Body/fun_read-line.html</a></p>
<p>Also the with-gensyms (and looping) version is included somewhere in <a href="http://paste.lisp.org/display/10220#4" rel="nofollow">http://paste.lisp.org/display/10220#4</a></p>
<p>BTW, no I&#8217;m not a Lisp guru just pointing to the wisdom of #lisp :)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: RM</title>
		<link>http://www.nonperiodic.net/blog/2005/06/12/lisp-macro-example/comment-page-1/#comment-3770</link>
		<dc:creator>RM</dc:creator>
		<pubDate>Tue, 26 Jul 2005 18:47:35 +0000</pubDate>
		<guid isPermaLink="false">/?p=160#comment-3770</guid>
		<description>It would probably be better not to use LOOP in a macro in this way, for the same reason it&#039;s better to use a gensym instead of the name &quot;stream&quot;.  The macro LOOP-FINISH has a meaning lexically within the body of a LOOP, so it&#039;s best to avoid making macros that emit LOOP as part of their expansions:
(loop for file in files
      do (dofile (line file)
           (when (string= line &quot;STOP PROCESSING HERE&quot;)
              (loop-finish)))) 
would have unexpected results.  So my &quot;dofile&quot; macro would be:
(defmacro dofile ((linevar filename &amp;rest open-options) &amp;body body)
  (let ((stream (gensym))) ; Or with-gensyms
    `(with-open-file (,stream ,filename ,@open-options)
       (block nil
         (let ((,linevar (read-line ,stream nil)))
           (unless ,linevar (return nil))
           ,@body)))))
This introduces a new NIL-block but lots of looping macros do that in CL, so it&#039;s not unexpected.  If you didn&#039;t want it, you could name the block with another gensym.</description>
		<content:encoded><![CDATA[<p>It would probably be better not to use LOOP in a macro in this way, for the same reason it&#8217;s better to use a gensym instead of the name &#8220;stream&#8221;.  The macro LOOP-FINISH has a meaning lexically within the body of a LOOP, so it&#8217;s best to avoid making macros that emit LOOP as part of their expansions:<br />
(loop for file in files<br />
      do (dofile (line file)<br />
           (when (string= line &#8220;STOP PROCESSING HERE&#8221;)<br />
              (loop-finish))))<br />
would have unexpected results.  So my &#8220;dofile&#8221; macro would be:<br />
(defmacro dofile ((linevar filename &amp;rest open-options) &amp;body body)<br />
  (let ((stream (gensym))) ; Or with-gensyms<br />
    `(with-open-file (,stream ,filename ,@open-options)<br />
       (block nil<br />
         (let ((,linevar (read-line ,stream nil)))<br />
           (unless ,linevar (return nil))<br />
           ,@body)))))<br />
This introduces a new NIL-block but lots of looping macros do that in CL, so it&#8217;s not unexpected.  If you didn&#8217;t want it, you could name the block with another gensym.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Emre Sevinc</title>
		<link>http://www.nonperiodic.net/blog/2005/06/12/lisp-macro-example/comment-page-1/#comment-3759</link>
		<dc:creator>Emre Sevinc</dc:creator>
		<pubDate>Tue, 26 Jul 2005 17:34:31 +0000</pubDate>
		<guid isPermaLink="false">/?p=160#comment-3759</guid>
		<description>Yes, I prefer loop (sometimes) and after reading PCL I automatically say with-gensyms when I see the gensym in some code.

Did you check the very useful with-gensyms macro from Practical Common Lisp by Peter Seibel?

http://www.gigamonkeys.com/book/macros-defining-your-own.html

The complete source code for the book is available at:

http://www.gigamonkeys.com/book/

Happy hacking,

Emre S.</description>
		<content:encoded><![CDATA[<p>Yes, I prefer loop (sometimes) and after reading PCL I automatically say with-gensyms when I see the gensym in some code.</p>
<p>Did you check the very useful with-gensyms macro from Practical Common Lisp by Peter Seibel?</p>
<p><a href="http://www.gigamonkeys.com/book/macros-defining-your-own.html" rel="nofollow">http://www.gigamonkeys.com/book/macros-defining-your-own.html</a></p>
<p>The complete source code for the book is available at:</p>
<p><a href="http://www.gigamonkeys.com/book/" rel="nofollow">http://www.gigamonkeys.com/book/</a></p>
<p>Happy hacking,</p>
<p>Emre S.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ralph Richard Cook</title>
		<link>http://www.nonperiodic.net/blog/2005/06/12/lisp-macro-example/comment-page-1/#comment-3252</link>
		<dc:creator>Ralph Richard Cook</dc:creator>
		<pubDate>Thu, 21 Jul 2005 18:06:41 +0000</pubDate>
		<guid isPermaLink="false">/?p=160#comment-3252</guid>
		<description>Congratulations; you have found a common abstraction, and used a macro to extend Lisp by implementing the abstraction. You have implemented dofile. You are on the path to enlightenment.

A couple of things; using the LOOP macro will improve readability. That&#039;s just style, though. A problem is the use of &#039;stream&#039; within the body of your macro. If dofile is used, for example, in the body of another with-open-file, say for outputting a file, then a user of your dofile would need to know about how it was implemented in order to avoid using &#039;stream&#039; as a variable name. This is solved in Common Lisp with the gensym method. More about this and macros in general can be learned from 
http://www.paulgraham.com/onlisptext.html

Here is my dofile:
(defmacro dofile ((line filename) &amp;body body)
  (let ((stream (gensym)))
    `(with-open-file (,stream ,filename)
      (loop for ,line = (read-line ,stream nil nil)
       while ,line do ,@body))))</description>
		<content:encoded><![CDATA[<p>Congratulations; you have found a common abstraction, and used a macro to extend Lisp by implementing the abstraction. You have implemented dofile. You are on the path to enlightenment.</p>
<p>A couple of things; using the LOOP macro will improve readability. That&#8217;s just style, though. A problem is the use of &#8217;stream&#8217; within the body of your macro. If dofile is used, for example, in the body of another with-open-file, say for outputting a file, then a user of your dofile would need to know about how it was implemented in order to avoid using &#8217;stream&#8217; as a variable name. This is solved in Common Lisp with the gensym method. More about this and macros in general can be learned from<br />
<a href="http://www.paulgraham.com/onlisptext.html" rel="nofollow">http://www.paulgraham.com/onlisptext.html</a></p>
<p>Here is my dofile:<br />
(defmacro dofile ((line filename) &amp;body body)<br />
  (let ((stream (gensym)))<br />
    `(with-open-file (,stream ,filename)<br />
      (loop for ,line = (read-line ,stream nil nil)<br />
       while ,line do ,@body))))</p>
]]></content:encoded>
	</item>
</channel>
</rss>
