<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Random Hacks: Tag Macros</title>
    <link>http://www.randomhacks.net/articles/tag/Macros?tag=Macros</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Technology and Other Fun Stuff</description>
    <item>
      <title>Ruby-style metaprogramming in JavaScript (plus a port of RSpec)</title>
      <description>&lt;p&gt;Programming in Ruby makes me happy.  It&amp;#8217;s a lovable language, with a
pleasantly quirky syntax and lots of expressive power.&lt;/p&gt;

&lt;p&gt;Programming in JavaScript, on the other hand, frustrates me to no end.
JavaScript &lt;i&gt;could&lt;/i&gt; be a reasonable language, but it has all sorts of
ugly corner cases, and it forces me to roll everything from scratch.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve been trying to make JavaScript a bit more like Ruby.  In particular, I
want to support Ruby-style metaprogramming in JavaScript.  This would make it possible to port over many advanced Ruby libraries.&lt;/p&gt;

&lt;p&gt;You can
check out the &lt;a href="http://www.randomhacks.net/svn/planetary/tags/0.1.0/spec_checker.html"&gt;interactive specification&lt;/a&gt;, or look at some examples
below.  If the &lt;a href="http://www.randomhacks.net/svn/planetary/tags/0.1.0/spec_checker.html"&gt;specification&lt;/a&gt; gives you any errors, please post them in the comment
thread, and let me know what browser you&amp;#8217;re running!&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2007/07/01/ruby-metaprogramming-javascript-rspec-bdd"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sun, 01 Jul 2007 19:00:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:421e0747-a145-4fc3-b0f1-8a5323eaea01</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/07/01/ruby-metaprogramming-javascript-rspec-bdd</link>
      <category>Ruby</category>
      <category>JavaScript</category>
      <category>Macros</category>
      <category>Planetary</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/472</trackback:ping>
    </item>
    <item>
      <title>How to make Data.Set a monad</title>
      <description>&lt;p&gt;&lt;b&gt;&amp;#8230;and how to fake Lisp macros with Template Haskell&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;(I wrote this article in response to &lt;a href="http://www.randomhacks.net/articles/2007/03/05/three-things-i-dont-understand-about-monads#comment-329"&gt;a comment&lt;/a&gt; by
&lt;a href="http://sigfpe.blogspot.com/"&gt;sigfpe&lt;/a&gt;.  You may find it pretty dry reading, unless you want to
build &lt;a href="http://en.wikipedia.org/wiki/Domain-specific_programming_language"&gt;domain-specific languages&lt;/a&gt; in Haskell.  Proceed at your own
risk.)&lt;/p&gt;

&lt;p&gt;Haskell&amp;#8217;s built-in &lt;code&gt;Monad&lt;/code&gt; type has some serious limitations.  We can fix those limitations using a number of advanced Haskell techniques, including &lt;a href="http://www.haskell.org/th/"&gt;Template Haskell&lt;/a&gt;, Haskell&amp;#8217;s closest equivalent to Lisp macros.&lt;/p&gt;

&lt;p&gt;We can illustrate the limitations of &lt;code&gt;Monad&lt;/code&gt; with an example from math. In &lt;a href="http://en.wikipedia.org/wiki/Set_theory"&gt;set theory&lt;/a&gt;, we can define a set by specifying how to compute each
element:&lt;/p&gt;

&lt;blockquote&gt;
{ &lt;i&gt;xy&lt;/i&gt; : &lt;i&gt;x&lt;/i&gt; &amp;isin; {1,2,4}, &lt;i&gt;y&lt;/i&gt; &amp;isin; {1,2,4} }
&lt;/blockquote&gt;

&lt;p&gt;We can read this as, &amp;#8220;the set of all &lt;i&gt;xy&lt;/i&gt;, where &lt;i&gt;x&lt;/i&gt;
is one of {1,2,4}, and &lt;i&gt;y&lt;/i&gt; is one of {1,2,4}.&amp;#8221;  To calculate the
answer, we first multiply together all the possible combinations:&lt;/p&gt;

&lt;blockquote&gt;
1&amp;times;1=1, 1&amp;times;2=2, 1&amp;times;4=4, 2&amp;times;1=2, 2&amp;times;2=4, 2&amp;times;4=8, 4&amp;times;1=4, 4&amp;times;2=8, 4&amp;times;4=16
&lt;/blockquote&gt;

&lt;p&gt;We then collect up the answers, and&amp;#8212;because we&amp;#8217;re working with sets&amp;#8211;we
throw away the duplicates:&lt;/p&gt;

&lt;blockquote&gt;
{1,2,4,8,16}
&lt;/blockquote&gt;

&lt;p&gt;Can we do the same thing in Haskell?  Well, using Haskell&amp;#8217;s &lt;a href="http://www.randomhacks.net/articles/2007/03/12/monads-in-15-minutes"&gt;list
monad&lt;/a&gt;, we can write:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;listExample&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
  &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='varop'&gt;*&lt;/span&gt;&lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But when we run this, Haskell gives us lots of duplicate values:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;listExample&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;16&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Our problem: We&amp;#8217;re using lists (which can contain duplicate
values) to represent sets (which can&amp;#8217;t).  Can we fix this by switching to
Haskell&amp;#8217;s &lt;code&gt;Data.Set&lt;/code&gt;?&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='varid'&gt;qualified&lt;/span&gt; &lt;span class='conid'&gt;Data&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Set&lt;/span&gt; &lt;span class='keyword'&gt;as&lt;/span&gt; &lt;span class='conid'&gt;S&lt;/span&gt;

&lt;span class='comment'&gt;-- This doesn't work.&lt;/span&gt;
&lt;span class='varid'&gt;setExample&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
  &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='conid'&gt;S&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;fromList&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='conid'&gt;S&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;fromList&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='varop'&gt;*&lt;/span&gt;&lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Unfortunately, this code fails spectacularly.  A Haskell monad is required
to work for &lt;i&gt;any&lt;/i&gt; types &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;class&lt;/span&gt; &lt;span class='conid'&gt;Monad&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='keyword'&gt;where&lt;/span&gt;
  &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;
  &lt;span class='varid'&gt;fail&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;
  &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;b&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But &lt;code&gt;Data.Set&lt;/code&gt; only works for some types.  Specifically, it
requires that values of type &lt;code&gt;a&lt;/code&gt; can be ordered:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;data&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Ord&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;Set&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varop'&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As it turns out, we can make &lt;code&gt;Data.Set&lt;/code&gt; into a monad.  But be
warned: The solution involves some pretty ugly Haskell abuse.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 15 Mar 2007 22:29:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:93c1c7e1-2355-408f-bf5e-488ce3ea0913</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros</link>
      <category>Haskell</category>
      <category>Monads</category>
      <category>Macros</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/367</trackback:ping>
    </item>
    <item>
      <title>Why Ruby is an acceptable LISP</title>
      <description>&lt;p&gt;Years ago, I looked at Ruby and decided to ignore it. Ruby wasn&amp;#8217;t as
popular as Python, and it wasn&amp;#8217;t as powerful as LISP. So why should I
bother?&lt;/p&gt;

&lt;p&gt;Of course, we could turn those criteria around.  What if Ruby were more
popular than &lt;em&gt;LISP&lt;/em&gt;, and more powerful than &lt;em&gt;Python&lt;/em&gt;?  Would that be enough
to make Ruby interesting?&lt;/p&gt;

&lt;p&gt;Before answering this question, we should decide what makes LISP so
powerful.  Paul Graham has &lt;a href="http://www.paulgraham.com/icad.html" title="Revenge of the Nerds"&gt;written eloquently&lt;/a&gt; about LISP&amp;#8217;s virtues.  But, for the sake of argument, I&amp;#8217;d like to boil them down to two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;LISP is a dense functional language.  &lt;/li&gt;
&lt;li&gt;LISP has programmatic macros.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As it turns out, Ruby compares well as a functional language, and it fakes
macros better than I&amp;#8217;d thought.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2005/12/03/why-ruby-is-an-acceptable-lisp"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sat, 03 Dec 2005 11:30:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:080ade06-c978-4e36-8847-44c22d1bc9b9</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2005/12/03/why-ruby-is-an-acceptable-lisp</link>
      <category>Ruby</category>
      <category>LISP</category>
      <category>Macros</category>
      <category>Recommended</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/77</trackback:ping>
    </item>
    <item>
      <title>Why Hygienic Macros Rock</title>
      <description>    &lt;p&gt;I've recently been reading a lot of &lt;a href='http://www.paulgraham.com/articles.html'&gt;excellent essays on
    programming language design&lt;/a&gt; by Paul Graham.  Paul and I agree about
    a number of things: (1) LISP is beautiful and powerful family of
    languages, even by modern standards, (2) all existing dialects of LISP
    are lacking a certain something, and (3) programmatic macros are a Good
    Idea.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2002/09/13/hygienic-macros"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Fri, 13 Sep 2002 00:00:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:213d6f83-48bd-4661-a3eb-98fb3784f7da</guid>
      <author>Eric</author>
      <link>http://www.randomhacks.net/articles/2002/09/13/hygienic-macros</link>
      <category>Macros</category>
      <category>LISP</category>
      <category>Hacks</category>
      <category>Recommended</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/24</trackback:ping>
    </item>
  </channel>
</rss>
