<?xml version="1.0"?>
<rdf:RDF
	xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:foaf="http://xmlns.com/foaf/0.1/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns="http://purl.org/rss/1.0/"
>
<channel rdf:about="http://planet.trapexit.org">
	<title>Planet Trapexit - Erlang/OTP News</title>
	<link>http://planet.trapexit.org</link>
	<description>Planet Trapexit - Erlang/OTP News - http://planet.trapexit.org</description>

	<items>
		<rdf:Seq>
			<rdf:li rdf:resource="http://erlsoft.org/erlang-internet-framework/43/eif-on-aws-and-an-ami-for-erlang/" />
			<rdf:li rdf:resource="http://www.trapexit.org/forum/viewtopic.php?p=43965#43965" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-7435412383881764254.post-2790488996638110334" />
			<rdf:li rdf:resource="http://steve.vinoski.net/blog/?p=77" />
			<rdf:li rdf:resource="http://www.lshift.net/blog/2008/07/01/rabbitmq-xmpp-gateway-released" />
			<rdf:li rdf:resource="http://yarivsblog.com/?p=195" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-3729811.post-5037189212731578855" />
			<rdf:li rdf:resource="http://prog21.dadgum.com/30.html" />
			<rdf:li rdf:resource="http://yarivsblog.com/?p=194" />
			<rdf:li rdf:resource="http://namsisi.com/?p=20" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-855944390206940143.post-2891792412737653499" />
			<rdf:li rdf:resource="http://www.process-one.net/en/blogs/article/erlang_exchange_london_uk_june_27th/#When:14:44:00Z" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-5246027334551923738.post-7309515441611634378" />
			<rdf:li rdf:resource="http://weblog.hypotheticalabs.com/?p=275" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-6265608756663924839.post-6495775998059610457" />
			<rdf:li rdf:resource="http://weblog.hypotheticalabs.com/?p=274" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-855944390206940143.post-3592269825987137569" />
			<rdf:li rdf:resource="http://weblog.hypotheticalabs.com/?p=273" />
			<rdf:li rdf:resource="http://weblog.hypotheticalabs.com/?p=272" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-855944390206940143.post-4377781961682745041" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-7435412383881764254.post-8901001959287642946" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-6265608756663924839.post-1240176153328288267" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-3729811.post-8789859386655022416" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-6265608756663924839.post-6651319658700771609" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-855944390206940143.post-3589219738909897871" />
			<rdf:li rdf:resource="http://steve.vinoski.net/blog/?p=73" />
			<rdf:li rdf:resource="http://ulf.wiger.net/weblog/?p=25" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-6265608756663924839.post-7076198302203910448" />
			<rdf:li rdf:resource="http://blogtrader.net/page/dcaoyuan/entry/parsing_performance_of_scala_for" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-1893218858608219953.post-2042706619324991488" />
			<rdf:li rdf:resource="http://prog21.dadgum.com/29.html" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-3729811.post-8715084766226292593" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-3729811.post-7994656310753990125" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-7012030999962875668.post-2937248757794621509" />
			<rdf:li rdf:resource="http://weblog.hypotheticalabs.com/?p=271" />
			<rdf:li rdf:resource="http://www.trapexit.org/forum/viewtopic.php?p=43939#43939" />
			<rdf:li rdf:resource="tag:blog.socklabs.com,2008:entry-1532" />
			<rdf:li rdf:resource="tag:blog.socklabs.com,2008:entry-1531" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-3729811.post-3544563282243548671" />
			<rdf:li rdf:resource="tag:blog.socklabs.com,2008:entry-1530" />
			<rdf:li rdf:resource="http://prog21.dadgum.com/28.html" />
			<rdf:li rdf:resource="http://erlangdevelopers.splinder.com/post/17296208/Programming+Erlang%2C+Software+f" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-3729811.post-5721620365634283981" />
			<rdf:li rdf:resource="http://yarivsblog.com/?p=192" />
			<rdf:li rdf:resource="urn:uuid:e486a1c7-eb55-4bb4-9de2-3f9b6b133a2e" />
			<rdf:li rdf:resource="http://weblog.hypotheticalabs.com/?p=269" />
			<rdf:li rdf:resource="http://blogtrader.net/page/dcaoyuan/entry/bundled_latest_scala_runtime_to" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-5246027334551923738.post-2767538981043038705" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-3729811.post-213508279296531618" />
			<rdf:li rdf:resource="http://steve.vinoski.net/blog/?p=72" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-3729811.post-2495235679507358636" />
			<rdf:li rdf:resource="http://weblog.hypotheticalabs.com/?p=265" />
			<rdf:li rdf:resource="http://weblog.hypotheticalabs.com/?p=267" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-3729811.post-8133193519919898247" />
			<rdf:li rdf:resource="http://prog21.dadgum.com/27.html" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-3729811.post-5494438681968588568" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-3729811.post-1003767045144330062" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-3729811.post-6143162776029321920" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-7012030999962875668.post-41253636972880484" />
			<rdf:li rdf:resource="http://weblog.hypotheticalabs.com/?p=264" />
		</rdf:Seq>
	</items>
</channel>

<item rdf:about="http://erlsoft.org/erlang-internet-framework/43/eif-on-aws-and-an-ami-for-erlang/">
	<title>Erlang Software Framework: EIF on AWS and an AMI for Erlang</title>
	<link>http://erlsoft.org/erlang-internet-framework/43/eif-on-aws-and-an-ami-for-erlang/</link>
	<content:encoded>I got an email this morning that made me realize how long it had been since I had updated this site. I've been a little bit distracted since I got my book deal. Originally I submitted a proposal to write a book on Erlang, but through a series of events ...</content:encoded>
	<dc:date>2008-07-02T19:20:55+00:00</dc:date>
</item>
<item rdf:about="http://www.trapexit.org/forum/viewtopic.php?p=43965#43965">
	<title>Trapexit News Feed: Trapexit News :: New Cookbook Entry on Tracing!</title>
	<link>http://www.trapexit.org/forum/viewtopic.php?p=43965#43965</link>
	<content:encoded>Author: &lt;a href=&quot;http://www.trapexit.org/forum/profile.php?mode=viewprofile&amp;u=183&quot; target=&quot;_blank&quot;&gt;francesco&lt;/a&gt;&lt;br /&gt;
Subject: New Cookbook Entry on Tracing!&lt;br /&gt;
Posted: Wed Jul 02, 2008 11:40 am (GMT 0)&lt;br /&gt;
Topic Replies: 0&lt;br /&gt;&lt;br /&gt;
&lt;span class=&quot;postbody&quot;&gt;Marstein has kindly contrinuted a new page to the Erlang Cookbook on tracing processes. You can view his contribution &lt;a href=&quot;http://www.trapexit.org/Tracing_Processes&quot; target=&quot;_blank&quot; class=&quot;postlink&quot;&gt; here...&lt;/a&gt; Or you can add your own recepie in trapexit's wiki &lt;a href=&quot;http://www.trapexit.org/Category:CookBook&quot; target=&quot;_blank&quot; class=&quot;postlink&quot;&gt;based Erlang Cookbook&lt;/a&gt;.
&lt;br /&gt;_________________&lt;br /&gt;--
&lt;br /&gt;
&lt;a href=&quot;http://www.erlang-consulting.com&quot; target=&quot;_blank&quot;&gt;http://www.erlang-consulting.com&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;</content:encoded>
	<dc:date>2008-07-02T11:51:04+00:00</dc:date>
</item>
<item rdf:about="tag:blogger.com,1999:blog-7435412383881764254.post-2790488996638110334">
	<title>21st Century Code Works: Notes from Erlang Exchange</title>
	<link>http://21ccw.blogspot.com/2008/07/notes-from-erlang-exchange.html</link>
	<content:encoded>I was at the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang-exchange.com/&quot;&gt;Erlang Exchange&lt;/a&gt; in London last week, which I really enjoyed. It was really great to see &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/joe-armstrong&quot;&gt;Joe Armstrong&lt;/a&gt;, and to see the faces behind the projects, e.g. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/klacke-wikstrom&quot;&gt;Claes Wikström&lt;/a&gt; (Yaws, Bluetail, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.kreditor.se/&quot;&gt;Kreditor&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.tail-f.com/&quot;&gt;Tail-f&lt;/a&gt;), &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/steve-vinoski&quot;&gt;Steve Vinoski&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/eric-merrit-and-martin-logan&quot;&gt;Eric Merrit&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/eric-merrit-and-martin-logan&quot;&gt;Martin Logan&lt;/a&gt; (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlware.org/&quot;&gt;Erlware&lt;/a&gt;), &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/matthias-radestock-and-tony-garnock-jones&quot;&gt;Matthias Radestock&lt;/a&gt; (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.lshift.net/&quot;&gt;LShift &lt;/a&gt;&amp;amp; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rabbitmq.com/&quot;&gt;RabbitMQ&lt;/a&gt;), &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang-exchange.com/mickael-remond&quot;&gt;Mickaël Rémond&lt;/a&gt; (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ejabberd.im/&quot;&gt;ejabberd&lt;/a&gt;) etc. etc.&lt;br /&gt;&lt;br /&gt;Something that Joe said reminded me of a comment that &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://peripateticaxiom.blogspot.com/&quot;&gt;Keith&lt;/a&gt; made about 6 months ago. I think this is something that gets lost in the hype around Erlang and multicore computing:&lt;br /&gt;&lt;br /&gt;&lt;span&gt;Erlang was designed to program fault tolerant systems. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It was not designed to program multicore computers. It was designed 15-20 years ago when multicore-everywhere was not even on the horizon. As a side-effect, it is a good language for multicore systems, since the only way to actually &lt;span&gt;achieve&lt;/span&gt; fault tolerance is to have &lt;span&gt;independant&lt;/span&gt; processes (read &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://ml.osdir.com/lang.erlang.general/2003-04/msg00350.html&quot;&gt;here&lt;/a&gt; for some more on this).&lt;br /&gt;&lt;br /&gt;I think it's important for us as to remember to advocate this, and instead of marketing Erlang/OTP as &quot;the application system for multicore&quot;, we should be marketing it as &quot;the application system for fault tolerance&quot;. Oh, and by the way &quot;this is one of the few systems that will actually use those cores that are coming your way&quot;.&lt;br /&gt;&lt;br /&gt;The second point that I have been pondering, was brought on my &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang-exchange.com/gordon-guthrie&quot;&gt;Gordon Guthrie&lt;/a&gt;'s talk about Erlang/OTP vs Google Apps as an application engine. At this moment, there aren't many application systems to choose from, Erlang/OTP, Google Apps and Amazon EC2 come to mind. In the context of the talk, an Application System (A/S) would be something that takes care of a lot of the non-functional requirements of you system, e.g. reliability, scalability (+distribution) etc.&lt;br /&gt;&lt;br /&gt;For some businesses, using Google Apps or EC2 would be a good fit, but then you're tied into the value chain of that business, and in some instances you just cannot (for legal and other reasons) put your data on servers you don't own. If you go the OTP route you have full control over your application(s), but there's a lot of extra infrastructure that you will have to supply yourself.&lt;br /&gt;&lt;br /&gt;If you start thinking of Erlang/OTP in this way, you realise that the terms should be reversed and it should actually be OTP/Erlang. The platform is actually the important thing. The &lt;span&gt;platform&lt;/span&gt; is the thing that gives you the reliability, scalability, distribution and hot code swapping etc. that you require. Erlang becomes this awesome language that you use to build things on the &lt;span&gt;platform&lt;/span&gt;. Looking at things from a different perspective can lead to some interesting insights.&lt;br /&gt;&lt;br /&gt;If I'm standing at this vantage point, heated discussions like the recent meme-storm in the blogosphere of &quot;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sauria.com/blog/2008/05/22/the-scala-vs-erlang-whirlwind/&quot;&gt;Erlang&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sauria.com/blog/2008/05/22/the-scala-vs-erlang-whirlwind/&quot;&gt; vs &lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sauria.com/blog/2008/05/22/the-scala-vs-erlang-whirlwind/&quot;&gt;Scala&lt;/a&gt;&quot; become much less relevant. Is there a platform that gives you reliability, scalability, distribution, hot code replacement that uses Scala as a language? No? Oh. What a pity...</content:encoded>
	<dc:date>2008-07-02T04:09:00+00:00</dc:date>
</item>
<item rdf:about="http://steve.vinoski.net/blog/?p=77">
	<title>Trapexit's Erlang Blog Filter: Convenience Over Correctness</title>
	<link>http://steve.vinoski.net/blog/2008/07/01/convenience-over-correctness/</link>
	<content:encoded>&lt;p&gt;My latest &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://computer.org/internet&quot;&gt;Internet Computing&lt;/a&gt; column, &amp;#8220;&lt;a rel=&quot;nofollow&quot;&gt;Convenience Over Correctness&lt;/a&gt;,&amp;#8221; (PDF) is now available. It continues the exploration of problems with RPC-oriented distributed programming approaches that I&amp;#8217;ve been writing about in each of my &lt;a rel=&quot;nofollow&quot;&gt;three&lt;/a&gt; &lt;a rel=&quot;nofollow&quot;&gt;prior&lt;/a&gt; &lt;a rel=&quot;nofollow&quot;&gt;columns&lt;/a&gt; this year, as well as in &lt;a rel=&quot;nofollow&quot;&gt;columns from years gone by&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang.org/pipermail/erlang-questions/2008-May/035207.html&quot;&gt;in the erlang-questions mailing list&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For years we&amp;#8217;ve known RPC and its descendants to be fundamentally flawed, yet many still willingly use the approach. Why? I believe the reason is simply &lt;em&gt;convenience&lt;/em&gt;. Regardless of RPC&amp;#8217;s well-understood problems, many developers continue to go down the RPC-oriented path because it conveniently fits the abstractions of the popular general-purpose programming languages they limit themselves to using. Making a function or method call to a remote or distributed function, object, or service appear just like any other function or method call allows such developers to stay within the comfortable confines of their language. Those who choose this approach essentially decide that developer convenience and comfort is more important than dealing with hard distribution issues like latency, concurrency, reliability, scalability, and partial failure.&lt;/p&gt;
&lt;p&gt;Is this convenience for the developer the right thing to focus on? I really, really don&amp;#8217;t think it is. There are ways of developing robust distributed applications that don&amp;#8217;t require code-generation toolkits, piles of special code annotations, or brittle enterprisey frameworks. Perhaps the wonderful programming language renaissance we&amp;#8217;re currently experiencing will help us to finally see the light and put tired old broken abstractions like RPC permanently out to pasture.&lt;/p&gt;</content:encoded>
	<dc:date>2008-07-02T02:42:58+00:00</dc:date>
</item>
<item rdf:about="http://www.lshift.net/blog/2008/07/01/rabbitmq-xmpp-gateway-released">
	<title>LShift on Erlang: RabbitMQ XMPP gateway released</title>
	<link>http://www.lshift.net/blog/2008/07/01/rabbitmq-xmpp-gateway-released</link>
	<content:encoded>&lt;p&gt;I&amp;#8217;m pleased to announce that our XMPP gateway for exposing a RabbitMQ instance to the global XMPP network has been released (&lt;a href=&quot;http://hg.rabbitmq.com/rabbitmq-xmpp/raw-file/tip/doc/index.html&quot;&gt;documentation&lt;/a&gt;, &lt;a href=&quot;http://hg.rabbitmq.com/rabbitmq-xmpp/&quot;&gt;browse or check out code&lt;/a&gt;, &lt;a href=&quot;http://hg.rabbitmq.com/rabbitmq-xmpp/archive/tip.zip&quot;&gt;download snapshot&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; Because it depends on a newer release of RabbitMQ than 1.3.0, you will also need to check out the server and codegen code from our &lt;a href=&quot;http://hg.rabbitmq.com/&quot;&gt;public mercurial repositories&lt;/a&gt;, or download them as snapshots: &lt;a href=&quot;http://hg.rabbitmq.com/rabbitmq-server/archive/tip.zip&quot;&gt;server&lt;/a&gt;, &lt;a href=&quot;http://hg.rabbitmq.com/rabbitmq-codegen/archive/tip.zip&quot;&gt;codegen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img id=&quot;image314&quot; src=&quot;http://www.lshift.net/blog/wp-content/uploads/2008/07/whole-network-1.png&quot; alt=&quot;Gateway in relation to ejabberd and RabbitMQ&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;mod_rabbitmq&lt;/code&gt; module implements an &lt;a href=&quot;http://www.process-one.net/en/ejabberd/&quot;&gt;ejabberd&lt;/a&gt; extension module which gateways AMQP (as implemented by &lt;a href=&quot;http://www.rabbitmq.com/&quot;&gt;RabbitMQ&lt;/a&gt;) to XMPP.&lt;/p&gt;

&lt;p&gt;By bridging between the two systems, we benefit from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;XMPP&amp;#8217;s internet-scale addressing and federation&lt;/li&gt;
&lt;li&gt;XMPP&amp;#8217;s presence model&lt;/li&gt;
&lt;li&gt;AMQP&amp;#8217;s store-and-forward capability&lt;/li&gt;
&lt;li&gt;AMQP&amp;#8217;s routing and filtering (using &lt;i&gt;exchanges&lt;/i&gt; and &lt;i&gt;bindings&lt;/i&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current implementation is a very simple mapping between the two systems. Its simplicity keeps the code short, but only exposes a subset of AMQP features to the XMPP network, and vice versa.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://hg.rabbitmq.com/rabbitmq-xmpp/raw-file/tip/doc/index.html&quot;&gt;Read more here.&lt;/a&gt;&lt;/p&gt;</content:encoded>
	<dc:date>2008-07-01T11:31:37+00:00</dc:date>
</item>
<item rdf:about="http://yarivsblog.com/?p=195">
	<title>Yariv's Blog: Numenta, AI, and the Web</title>
	<link>http://feeds.feedburner.com/~r/YarivsBlog/~3/322970050/</link>
	<content:encoded>&lt;p&gt;Last week, I attended the &lt;a href=&quot;http://numenta.com&quot;&gt;Numenta&lt;/a&gt; workshop. I didn&amp;#8217;t know much about Numenta before I went. My friend&amp;#8217;s excitement about the technology Numenta is building piqued my curiosity, so I decided to check it out. It seemed that almost everyone else in the conference had read Jeff Hawkins&amp;#8217;s &lt;a href=&quot;http://www.onintelligence.org/&quot;&gt;On Intelligence&lt;/a&gt; and at least experimented with Numeta&amp;#8217;s tools, so I felt like a real n00b. I&amp;#8217;m happy I went, though, because I learned about some interesting ideas and technologies.&lt;/p&gt;
&lt;p&gt;Jeff Hawkins, Numenta&amp;#8217;s founder, has been fascinated with the workings of the brain throughout his career, but only two decades into it, after he founded Palm and Handspring, was he able to devote his efforts to artificial intelligence. In On Intelligence, Hawkins discusses his theories on the brain&amp;#8217;s functions in detail. Numenta, a company he founded with &lt;a href=&quot;http://www.stanford.edu/~dil/&quot;&gt;Dileep George&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/Donna_Dubinsky&quot;&gt;Donna Dubinsky&lt;/a&gt;, aims to put these ideas to work in commercial and research applications.&lt;/p&gt;
&lt;p&gt;Numenta is a platform company. The platform they develop is NuPIC (Numenta Platform for Intelligent Computing), a software toolkit essentially for building pattern classifiers. The fundamental concept behind NuPIC is called HTM (Hierarchical Temporal Memory). It postulates that the cortex learns to recognize patterns using a combination of two basic algorithms: hierarchical belief propagation, and the detection of invariants in a sequence of transformations in time. I won&amp;#8217;t get into what this all means because there&amp;#8217;s plenty of &lt;a href=&quot;http://www.numenta.com/for-developers/education/general-overview-htm.php&quot;&gt;documentation&lt;/a&gt; on the Numenta website. I recommend browsing it if you find this interesting.&lt;/p&gt;
&lt;p&gt;HTM is not just theory. Although NuPIC is in a very early stage, companies are applying NuPIC to a wide range of problems, including vision, voice recognition, finance, motion recognition (recognizing motion capture data to detect if a person is walking, running, sitting, etc) and games. This is just a small subset of its potential uses.&lt;/p&gt;
&lt;p&gt;Using Nupic in its current state isn&amp;#8217;t trivial. It provides the building blocks for HTM pattern classifiers, but application developers still have to do a good deal of work to tune the parameters of their HTM (How many nodes? How many levels in the hierarchy? How much training data to use? How many categories? What transformations to apply to the input over time to train the system?) to their problem domain. Also, some important features haven&amp;#8217;t been implemented yet. For example, although NuPIC can be pretty effective at classifying images that contain a single object against a plain background (with enough training), it isn&amp;#8217;t designed to recognize objects in images with noisy backgrounds or with multiple objects. (The problem of how to identify interesting objects in a scene is called the &amp;#8220;attention&amp;#8221; problem. To solve it you need to have a mechanism by which the top nodes could send feedback down to the bottom nodes. Hawkins said Numenta will tackle it in a future release.)&lt;/p&gt;
&lt;p&gt;One reason I find Numenta so interesting is that I believe that NuPIC, or something like it, will play a role in the evolution of the Web. The current generation of web applications (Web 2.0 apps, if you will) is effective at aggregating massive amounts of data in different verticals (pictures, videos, bookmarks, status messages, paintings), slicing and dicing it in different ways, searching it, and displaying it in an organized fashion. Mashups provide additional context for the data gathered in the different silos of the web (&lt;a href=&quot;http://kosmix.com&quot;&gt;Kosmix&lt;/a&gt; is a good example), but they don&amp;#8217;t add any real &amp;#8220;intelligence&amp;#8221; to the mix, i.e. they don&amp;#8217;t extract new knowledge from the data they aggregate. Numenta&amp;#8217;s technology could be used to implement a new layer of intelligence on top of existing services by training it to recognize spacial and temporal pattens in the data they&amp;#8217;ve collected. For example, imagine a Flickr API that let you submit an image and Flickr would tell you what the objects in the image are and where the picture was taken. Or a Facebook API for identifying the people in a picture. Or a Skype API for recognizing the speaker from a voice sample (creepy, I know). Or a HotOrNot API for automatically classifying the hotness of a person (ok, bad example :) ). Or a YouTube API for identifying the objects and events in a video clip. Or a &lt;a href=&quot;http://icanhascheezburger.com/&quot;&gt;icanhascheezburger&lt;/a&gt; API for automatically classifying the LOLness of a cat (well&amp;#8230; maybe not :) ).&lt;/p&gt;
&lt;p&gt;If this happens, maybe some day a mashup of these web services will be used to build something that resembles real AI. If (when?) someone manages to build a real-life WALL*E (great movie!), I think there&amp;#8217;s a good chance its HTMs will be trained on the vast amounts of data gathered on the web.&lt;/p&gt;
&lt;p&gt;Interesting times ahead. Stay tuned.&lt;/p&gt;
&lt;img src=&quot;http://feeds.feedburner.com/~r/YarivsBlog/~4/322970050&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content:encoded>
	<dc:date>2008-06-30T04:26:22+00:00</dc:date>
</item>
<item rdf:about="tag:blogger.com,1999:blog-3729811.post-5037189212731578855">
	<title>Web 2.0 and beyond: Erlang Exchange 2008</title>
	<link>http://www.rsaccon.com/2008/06/erlang-exchange-2008.html</link>
	<content:encoded>The last two days I have spent at the Erlang Exchange Conference. It was great to met other Erlang hackers in person I just knew from their blog, emails or mailing list. Below the slides from my talk:</content:encoded>
	<dc:date>2008-06-30T02:53:58+00:00</dc:date>
	<dc:creator>Roberto Saccon</dc:creator>
</item>
<item rdf:about="http://prog21.dadgum.com/30.html">
	<title>Programming in the 21st Century: Want to Write a Compiler?  Just Read These Two Papers.</title>
	<link>http://prog21.dadgum.com/30.html</link>
	<content:encoded>Imagine you don't know &lt;i&gt;anything&lt;/i&gt; about programming, and you want learn how to do it.  You take a look at Amazon.com, and there's a highly recommended set of books by Knute or something with a promising title, &lt;i&gt;The Art of Computer Programming&lt;/i&gt;, so you buy them.  Now imagine that it's more than just a poor choice, but that &lt;b&gt;all&lt;/b&gt; the books on programming are at written at that level.
&lt;br /&gt;&lt;br /&gt;That's the situation with books about writing compilers.
&lt;br /&gt;&lt;br /&gt;It's not that they're bad books, they're just too broadly scoped, and the authors present so much information that it's hard to know where to begin.  Some books are better than others, but there are still the thick chapters about converting regular expressions into executable state machines and different types of grammars and so on. After slogging through it all you will have undoubtedly expanded your knowledge, but you're no closer to actually writing a working compiler.
&lt;br /&gt;&lt;br /&gt;Not surprisingly, the opaqueness of these books has led to the myth that compilers are hard to write.
&lt;br /&gt;&lt;br /&gt;The best source for breaking this myth is Jack Crenshaw's series, &lt;a href=&quot;http://compilers.iecc.com/crenshaw/&quot;&gt;Let's Write a Compiler!&lt;/a&gt;, which started in 1988.  This is one of those gems of technical writing where what's assumed to be a complex topic ends up being suitable for a first year programming class.  He focuses on compilers of the Turbo Pascal class: single pass, parsing and code generation are intermingled, and only the most basic of optimizations are applied to the resulting code.  The original tutorials used Pascal as the implementation language, but there's a C version out there, too.  If you're truly adventurous, Marcel Hendrix has done a &lt;a href=&quot;http://home.iae.nl/users/mhx/crenshaw/tiny.html&quot;&gt;Forth translation&lt;/a&gt; (and as Forth is an interactive language, it's easier to experiment with and understand than the C or Pascal sources).
&lt;br /&gt;&lt;br /&gt;As good as it is, Crenshaw's series has two major omissions.  The first is that there's no internal representation of the program at all.  That is, no abstract syntax tree.  It is indeed possible to bypass this step if you're willing to give up flexibility, but the main reason it's not in the tutorials is because manipulating trees in Pascal is out of sync with the simplicity of the rest of the code he presents.  If you're working in a higher level language--Python, Ruby, Erlang, Haskell, Lisp--then this worry goes away.  It's trivially easy to create and manipulate tree-like representations of data.  Indeed, this is what Lisp, Erlang, and Haskell were designed for.
&lt;br /&gt;&lt;br /&gt;That brings me to &lt;a href=&quot;http://www.cs.indiana.edu/~dyb/pubs/nano-jfp.pdf&quot;&gt;A Nanopass Framework for Compiler Education&lt;/a&gt; [PDF] by Sarkar, Waddell, and Dybvig.  The details of this paper aren't quite as important as the general concept:  a compiler is nothing more than a series of transformations of the internal representation of a program.  The authors promote using &lt;b&gt;dozens or hundreds of compiler passes&lt;/b&gt;, each being as simple as possible.  Don't combine transformations; keep them separate.  The framework mentioned in the title is a way of specifying the inputs and outputs for each pass.  The code is in Scheme, which is dynamically typed, so data is validated at runtime.
&lt;br /&gt;&lt;br /&gt;After writing a compiler or two, then go ahead and plunk down the cash for the infamous &lt;a href=&quot;http://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools&quot;&gt;Dragon Book&lt;/a&gt; or one of the alternatives.  Maybe.  Or you might not need them at all.</content:encoded>
	<dc:date>2008-06-29T06:00:00+00:00</dc:date>
	<dc:creator>James Hague</dc:creator>
</item>
<item rdf:about="http://yarivsblog.com/?p=194">
	<title>Yariv's Blog: Twoorl Goes Multilingual</title>
	<link>http://feeds.feedburner.com/~r/YarivsBlog/~3/322365520/</link>
	<content:encoded>&lt;p&gt;Since its launch, Twoorl users have helped translate it to Spanish, German, French, Korean, Polish, Portuguese (Brazilian) and Russian. This is an awesome contribution from the Twoorl community. Big thanks to everyone who contributed a translation!&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re fluent in a language that Twoorl hasn&amp;#8217;t been translated into and you&amp;#8217;d like to contribute a translation for it, obtain the file &lt;a href=&quot;http://github.com/yariv/twoorl/tree/master/src/bundles/twoorl_eng.erl&quot;&gt;twoorl_eng.erl&lt;/a&gt;, translate the english strings, and email me the modified file. (Please make sure the file is encoded in UTF-8.) If you&amp;#8217;re familiar with Git, you can also clone the repository, make the changes, and send me a message through GitHub to pull your updates. Thanks in advance!&lt;/p&gt;
&lt;img src=&quot;http://feeds.feedburner.com/~r/YarivsBlog/~4/322365520&quot; height=&quot;1&quot; width=&quot;1&quot; /&gt;</content:encoded>
	<dc:date>2008-06-29T03:24:47+00:00</dc:date>
</item>
<item rdf:about="http://namsisi.com/?p=20">
	<title>Namsisi: The Erlang Exchange</title>
	<link>http://namsisi.com/archives/2008-06-26/the-erlang-exchange/</link>
	<content:encoded>&lt;p&gt;I&amp;#8217;m currently attending the &lt;a title=&quot;Erlang Exchange&quot; href=&quot;http://www.erlang-exchange.com&quot; target=&quot;_blank&quot;&gt;Erlang Exchange&lt;/a&gt; conference in London.&lt;/p&gt;
&lt;p&gt;So far I&amp;#8217;ve attended two presentations in the main track before lunch and two presentations in the Tools &amp;amp; Gadgets track. I&amp;#8217;m going to give a brief summary below. All the talks are being streamed on &lt;a href=&quot;http://yaika.com/channel/erlang-live&quot; target=&quot;_blank&quot;&gt;Yaika&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Main Track&lt;/h3&gt;
&lt;h4&gt;Joe Armstrong on Software: Erlang &amp;amp; SMP&lt;/h4&gt;
&lt;p&gt;This is the talk of Joe Armstrong which kind of aligns with his book. It is quite basic and more aimed at Erlang beginners that experts. It contains a few interesting bits however, mostly the stuff about Symmetric Multi-Processing (SMP) and multi core processors. Not specifically Erlang related but at least message passing oriented, or as Joe calls it, &lt;em&gt;Concurrency Oriented Programming&lt;/em&gt; (COP). All in all, &amp;#8220;old stuff&amp;#8221; (in a good sense) with some really interesting insights.&lt;/p&gt;
&lt;h4&gt;Introducing Erlang to Motorola: The Journey to Success&lt;/h4&gt;
&lt;p&gt;This talk was given by Nicholas Gunder and Torben Hoffman (which I enjoyed the OTP course together with) from Motorola (which interesting enough is now using Erlang, the language developed by their main competitor Ericsson). It was more of a manager talk than a technical talk, although they sometimes go all the way down to the hardware level, for example when talking about the &lt;a href=&quot;http://www.gumstix.com/&quot; target=&quot;_blank&quot;&gt;Gumstix&lt;/a&gt; computers they are using.&lt;/p&gt;
&lt;p&gt;This was a really nice talk, Nicholas and Torben are really funny guys. It gave a good insight into how they pushed Erlang from being a basically non-existant technology inside Motorola to a technology about which the managers ask &amp;#8220;is there&amp;#8217;s any other projects we could apply this to?&amp;#8221; Their main conclusion was, I think, &amp;#8220;have something finished to show.&amp;#8221; That means, whenever pushing Erlang to management, show them something working. This is among other things a terrific illustrator on how productive Erlang is, which also compared to C is one of the selling points.&lt;/p&gt;
&lt;h3&gt;Tools &amp;amp; Gadgets Track&lt;/h3&gt;
&lt;h4&gt;Erlang D-Trace&lt;/h4&gt;
&lt;p&gt;Given by Garry Bulmer, the talk was about intergrating Erlang with the OS X/Unix tracing facility &lt;a href=&quot;http://en.wikipedia.org/wiki/DTrace&quot; target=&quot;_blank&quot;&gt;DTrace&lt;/a&gt;. DTrace basically lets you trace on &amp;#8220;anything&amp;#8221; in the operating system and user space programs. You can trace on functions, accumulate data etc using your own DTrace scripts. Erlang already has an extremely powerful tracing and &lt;a href=&quot;http://erlang.org/doc/man/dbg.html&quot;&gt;debugging&lt;/a&gt; &lt;a href=&quot;http://www.erlang.org/doc/apps/debugger/&quot; target=&quot;_blank&quot;&gt;facility&lt;/a&gt;. This integration aims to give a bigger picture on how your Erlang application and the rest of the OS and other applications interact and perform. Unfortunately due to GPL issues, DTrace is not available on Linux, only on OS X and other Unix variants.&lt;/p&gt;
&lt;p&gt;What Bulmer and his team did, was to extend the Erlang VM with DTrace hooks so that tracing can be done on process creating and other Erlang primitives. The goal is to become a good complement to the internal Erlang tracing and debuggnig facilities.&lt;/p&gt;
&lt;h4&gt;Building Web Applications in Erlang&lt;/h4&gt;
&lt;p&gt;A talk about Erlang and web development given by Michal Slask and Xingdong Bian from &lt;a href=&quot;http://www.erlang-consulting.com&quot; target=&quot;_blank&quot;&gt;Erlang Training &amp;amp; Consulting&lt;/a&gt; (disclaimer: I work for ETC). It was about the new web development platform that ETC is releasing. It takes its template philosophy from JSP, so that with tags such as list and choose you can call backend Erlang modules expanding to dynamic HTML code. All in a Model View Controller (MVC) fashion.&lt;/p&gt;
&lt;p&gt;More about this soon so keep an eye on the Erlang Training &amp;amp; Consulting website and the Erlang mailing list!&lt;/p&gt;
&lt;h4&gt;Erlang &amp;amp; Ajax Web&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://rsaccon.com&quot; target=&quot;_blank&quot;&gt;Roberto Saccon&lt;/a&gt; gived a talk on integrating Ajax technologies with Erlang. The talk focused heavily on Coment and Roberts implementation in Erlang, &lt;a href=&quot;http://code.google.com/p/erlycomet/&quot; target=&quot;_blank&quot;&gt;ErlyComet&lt;/a&gt;. The talk is focusing on the implemantion and the results, both mistakes and successes. It is like a overview of both Ajax (for the Erlang community) and a collection of do&amp;#8217;s and don&amp;#8217;ts when using Ajax/Comet with Erlang. All in all, a web 2.0 presentation with an Erlang flavour.&lt;/p&gt;
&lt;h3&gt;The Rest of the Conference&lt;/h3&gt;
&lt;p&gt;This is it so far, maybe more posts will come later. Today it is just the &lt;a href=&quot;http://www.erlware.org/&quot;&gt;Faxien &amp;amp; Sinan&lt;/a&gt; presentation I&amp;#8217;m planning to attend.&lt;/p&gt;</content:encoded>
	<dc:date>2008-06-26T14:44:23+00:00</dc:date>
</item>
<item rdf:about="tag:blogger.com,1999:blog-855944390206940143.post-2891792412737653499">
	<title>EazyErl!: Parsing Binaries with erlang, lamers inside</title>
	<link>http://easyerl.blogspot.com/2008/06/parsing-binaries-with-erlang-lamers.html</link>
	<content:encoded>It's seems that there's a really high expectation  on &lt;a href=&quot;http://www.erlang.org/pipermail/erlang-questions/2008-June/036166.html&quot;&gt;&quot;parsing binaries&quot; with erlang&lt;/a&gt; and reach others languages performance. For me this is a complete nonsense.&lt;br /&gt;What's the meaning of &quot;parsing a binary&quot;, a binary is not a text, it's a binary, a sequence of bytes... &lt;br /&gt;A sequence must be defined by its length. You must know before reading anything, the size that'll be needed store what's coming.&lt;br /&gt;Every crap software you can find has always prefered to use strcpy instead of memcpy. Whatever the language you use, you MUST know the size of what you're working with, this is not an advice this is mandatory.&lt;br /&gt;&lt;br /&gt;From the post above, you can find that the only delimiter seems to be &quot;\r\n&quot;. So if someone sends you 4Gb of data not ending with &quot;\r\n&quot; you'll keep reading it... (and of course blow your memory because this was not supposed to be) &lt;br /&gt;&lt;br /&gt;While working at low level with C and flex scanners, I've always ask me this question: &quot;What's the max size of the element I can accept ?&quot;. This simple question helps me build software that don't break with a simple 'perl print Ax60000' trick...&lt;br /&gt;&lt;br /&gt;So is HTTP badly designed, because delimiters are &quot;\r\n&quot; and headers can spread on multiple lines ? The answer is absolutely YES.&lt;br /&gt;Was'it difficult to build something more secure, using prefixed elements with their size ? The answer is absolutely NO ! (take &lt;a href=&quot;http://easyerl.blogspot.com/2007/07/erlang-and-jboss-talking-ajp13-part-i.html&quot;&gt;ajp13 for example&lt;/a&gt;...)&lt;br /&gt;&lt;br /&gt;Now that erlang is becoming more and more popular, lamers are lurking in the erlang direction. This is life, but will the erlang mailling list suffer from this ? The answer is yes :/&lt;br /&gt;&lt;br /&gt;Someone with knowledge must not try to resolve someone's else problem, he must help him by asking the good question. (do you know the size a priori ?)&lt;br /&gt;&lt;br /&gt;Why parsing binaries in java is faster than erlang ? Who cares, since parsing binaries is of course stupid !&lt;br /&gt;Parsing real world protocol with erlang is lightning fast, both for writing and for executing. So teach lamers how to build real protocols and don't try help them with some trickery.&lt;br /&gt;&lt;br /&gt;That's my rant for today :)</content:encoded>
	<dc:date>2008-06-26T13:25:39+00:00</dc:date>
	<dc:creator>rolphin</dc:creator>
</item>
<item rdf:about="http://www.process-one.net/en/blogs/article/erlang_exchange_london_uk_june_27th/#When:14:44:00Z">
	<title>Process-one Blogs: Talk at Erlang Exchange Conference, London, UK on June 27th</title>
	<link>http://www.process-one.net/en/blogs/article/erlang_exchange_london_uk_june_27th/</link>
	<content:encoded>I will be talking in a London conference about ejabberd XMPP application server and Tsung benchmarking (HTTP and XMPP). &lt;p&gt;I will be at Erlang Exchange next friday (27th June, 2008), to talk about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;ejabberd for web 2.0 development&lt;/b&gt;: We have designed ejabberd as an XMPP application server that happens to be ideal to build web 2.0 applications and social networks. The talk will rely on two majors use cases: building a large scale community chat system (Major League of Baseball) and building a Twitter-like microblogging platform on top of ejabberd.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Tsung tutorial&lt;/b&gt;: This Tsung tutorial will present the fundamental concepts underlying Tsung architecture and will provide the required knowledge to write relevant benchmark scenarios. You will then learn how to create a scenario to benchmark an example web application and how to analyse the results of the benchmark.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I would be very glad to meet existing or future ejabberd and Tsung users next friday &lt;img class=&quot;inline&quot; src=&quot;http://www.process-one.net/images/smileys/smile.gif&quot; width=&quot;19&quot; height=&quot;19&quot; alt=&quot;smile&quot; /&gt;&lt;/p&gt;

&lt;p&gt;More details: &lt;a href=&quot;http://www.erlang-exchange.com/mickael-remond&quot;&gt;My talks&lt;/a&gt; and the &lt;a href=&quot;http://www.erlang-exchange.com/conference&quot;&gt;conference programme&lt;/a&gt;.&lt;/p&gt;</content:encoded>
	<dc:date>2008-06-25T13:44:00+00:00</dc:date>
</item>
<item rdf:about="tag:blogger.com,1999:blog-5246027334551923738.post-7309515441611634378">
	<title>Joe Armstrong: Invasion of Privacy</title>
	<link>http://armstrongonsoftware.blogspot.com/2008/06/invasion-of-privacy.html</link>
	<content:encoded>On 18 June the Swedish Parliament passed a law giving sweeping new powers to the FRA (Swedish Defense Radio Establishment) allowing them to wiretap people in Sweden through phone conversations, email, text messages and more.

All people in Sweden using electronic communication can have their communication monitored despite the fact that they are not suspected of committing any crime.

In my view</content:encoded>
	<dc:date>2008-06-24T13:53:06+00:00</dc:date>
	<dc:creator>Joe Armstrong</dc:creator>
</item>
<item rdf:about="http://weblog.hypotheticalabs.com/?p=275">
	<title>Hypothetical Labs: Oh Frabjous Day!</title>
	<link>http://weblog.hypotheticalabs.com/?p=275</link>
	<content:encoded>&lt;p&gt;(With humble apologies to Lewis Carroll, my favorite purveyor of kid-safe absurdity)&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve finally wrestled frabjous into a form approximating acceptable quality &amp;#8212; you can check it out on GitHub &lt;a href=&quot;http://github.com/kevsmith/hypotheticalabs/tree/master&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So, what is frabjous? It&amp;#8217;s a wrapper around Erlang&amp;#8217;s parse transforms with some of the sharp edges filed off. Frabjous insulates developers from the tedium of parse transforms in two ways. &lt;/p&gt;
&lt;p&gt;First, it interfaces directly with the compiler and handles all of the low-level details around iterating over the AST and other parse transform muck. Frabjous knows all about multi-pass transforms and provides a persistent state mechanism for parse transformers so they can remember where they&amp;#8217;ve been and what they&amp;#8217;re doing.&lt;/p&gt;
&lt;p&gt;Second, frabjous defines a new behavior, &lt;code&gt;ast_transformer&lt;/code&gt;, to use when you want to write a frabjous-based parse transformer. Why is this a good thing? Well, &lt;code&gt;ast_transformer&lt;/code&gt; defines a number of helpful functions like &lt;code&gt;start/1&lt;/code&gt; and &lt;code&gt;is_complete/1&lt;/code&gt; which model allow a transformer to track its state and implement multiple passes. &lt;code&gt;ast_transformer&lt;/code&gt; also defines a standardized calling convention for transforming AST nodes using the function &lt;code&gt;transform/3&lt;/code&gt;. No more inventing your own calling convention each time you write a parse transformer.&lt;/p&gt;
&lt;p&gt;Frabjous integrates into the Erlang compiler via a header file named &amp;#8220;&lt;code&gt;frabjous.hrl&lt;/code&gt;&amp;#8220;. Just use &lt;code&gt;include_lib&lt;/code&gt; to include the header and your code is now frabjous-enabled. Wiring up AST transformers is done using the &lt;code&gt;frabjous&lt;/code&gt; attribute.&lt;/p&gt;
&lt;p&gt;A picture is worth a thousand words so let&amp;#8217;s see what a source file which uses frabjous and its AST transformers looks like. This same is taken from frabjous/examples/src/pt_test.erl.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;br /&gt;
-module(pt_test).&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;-define(SERVER, ?MODULE).&lt;/p&gt;
&lt;p&gt;-include_lib(&quot;frabjous/include/frabjous.hrl&quot;).&lt;/p&gt;
&lt;p&gt;-frabjous([{remote_call, [{debug, true}]}]).&lt;/p&gt;
&lt;p&gt;-behaviour(gen_server).&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;The example includes &lt;code&gt;frabjous.hrl&lt;/code&gt; which &amp;#8220;turns on&amp;#8221; frabjous. It then goes on to configure a single frabjous AST transformer named &lt;code&gt;remote_call&lt;/code&gt; and runs it in debug mode. When frabjous AST transformers are run in debug mode they emit before and after snapshots of the AST. This is indispensable  when you&amp;#8217;re debugging a transformer, either on its own or when it&amp;#8217;s part of a chain of transformers. Yep, frabjous understands how to chain a series of transformers together.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;remote_call&lt;/code&gt; transformer takes attribute entries like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;br /&gt;
-call_gen_server([{server, ?SERVER},&lt;br /&gt;
                  {name, add},&lt;br /&gt;
                  {vars, [x,y]}]).&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;and turns them into functions like this, complete with matching &lt;code&gt;export&lt;/code&gt; statements:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;br /&gt;
add(X, Y) -&gt; gen_server:call(?SERVER, {add, X, Y}).&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Why? Because I got really, really, really tired of writing the same message sending wrapper function over and over each time I write a &lt;code&gt;gen_server&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;These are still early days for frabjous so the code is a bit rough. There are several things I want to improve soon including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unit tests (!!!)&lt;/li&gt;
&lt;li&gt;Teaching frabjous how to handle more than the first level of the AST nodes&lt;/li&gt;
&lt;li&gt;Adding more functions to &lt;code&gt;frabjous_helper&lt;/code&gt; to make AST node generation easier&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&amp;#8217;re interested in frabjous, please check it out and let me know what you think!&lt;/p&gt;</content:encoded>
	<dc:date>2008-06-24T10:16:09+00:00</dc:date>
	<dc:creator>kevin</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-6265608756663924839.post-6495775998059610457">
	<title>Dukes of Erl: Tokyocabinet and Mnesia</title>
	<link>http://dukesoferl.blogspot.com/2008/06/tokyocabinet-and-mnesia.html</link>
	<content:encoded>As &lt;a href=&quot;http://www.wagerlabs.com/blog/2008/06/mnesia-unlimited.html&quot;&gt;Daisy&lt;/a&gt; has already indicated, it is now possible to plug &lt;a href=&quot;http://code.google.com/p/mnesiaex&quot;&gt;arbitrary storage strategies into Mnesia&lt;/a&gt;.  For those who are familiar with mnesia_access, this is different; mnesia_access only covers reads and writes, not schema manipulations, and has &lt;a href=&quot;http://www.erlang.org/pipermail/erlang-questions/2008-April/034642.html&quot;&gt;other deficiencies&lt;/a&gt; that it render it useless for adding a new storage type in practice (what mnesia_access is great for is changing the semantics of mnesia operations, e.g., mnesia_frag).  This project lets you make tables that are essentially indistinguishable from the built-in mnesia table types (ram_copies, disc_copies, disc_only_copies).&lt;br /&gt;&lt;br /&gt;Anyway our goal was to get a good on-disk ordered_set table type, since we've found ordered_sets very useful for the kinds of problems we're solving but we're tired of being limited by memory.  After looking around for a while &lt;a href=&quot;http://tokyocabinet.sourceforge.net/&quot;&gt;Tokyocabinet&lt;/a&gt; emerged as our favorite for underlying implementation.  We considered BDB and libmysql, but Tokyocabinet seemed simple and faster, and had a more accommodating license.  So we ported Tokyocabinet to Erlang and then used the above storage API to connect to Mnesia.&lt;br /&gt;&lt;br /&gt;As a side benefit Tokyocabinet might also be preferred to dets even for set-type applications because of the lack of file size limit and high performance.  Tokyocabinet actually has a set-type storage strategy that we'd like to define an Erlang Term Store for, but as of this post, the set-type store doesn't support cursor positioning based upon a key, which makes the implementation of next tedious (although not impossible).  So I'm waiting on the author to add that call; if that happens, we could have a nicer on-disk set-type table as well.&lt;br /&gt;&lt;br /&gt;Everything is available on google code: &lt;a href=&quot;http://code.google.com/p/mnesiaex&quot;&gt;mnesiaex&lt;/a&gt; (storage API) and &lt;a href=&quot;http://code.google.com/p/tcerl&quot;&gt;tcerl&lt;/a&gt; (erlang port of Tokyocabinet).&lt;br /&gt;&lt;br /&gt;Also Daisy (aka Joel Reymont) is really nice to work with.</content:encoded>
	<dc:date>2008-06-23T22:25:59+00:00</dc:date>
	<dc:creator>Paul Mineiro</dc:creator>
</item>
<item rdf:about="http://weblog.hypotheticalabs.com/?p=274">
	<title>Hypothetical Labs: I Wrote What?</title>
	<link>http://weblog.hypotheticalabs.com/?p=274</link>
	<content:encoded>&lt;p&gt;Late last evening I was finally able to carve out some time to work on frabjous. Frabjous, for those who missed out on my only other post about it, is a parse transform framework for Erlang aimed at making writing parse transforms easier.&lt;/p&gt;
&lt;p&gt;But that&amp;#8217;s not important right now.&lt;/p&gt;
&lt;p&gt;The important part is I was ready to release it last night and decided against it. It&amp;#8217;s got unit tests, examples, and nice descriptive comments in all the public functions (and some of the private ones, too). But the code is, well, utter crap.&lt;/p&gt;
&lt;p&gt;I wrote the original core of frabjous the day I flew out to Engine Yard&amp;#8217;s offices. I figured with a day of air travel and my laptop I could get a lot of hacking done. I did. A lot of &lt;em&gt;hacking&lt;/em&gt; but not much designing. The up side is I understand parse transforms really well. The down side is the code is way less organized and efficient than it could be.&lt;/p&gt;
&lt;p&gt;Plain and simple, the code isn&amp;#8217;t pretty. I have a simple benchmark for code prettiness which works equally well for OOP and functional languages. If I have to stare at the code for more than a minute or two to understand a given function, method, or class, then the code isn&amp;#8217;t pretty. That&amp;#8217;s it. Think of it as inscrutability quotient. The cleaner the code, aka pretty, the less time I have to spend understanding it. The longer I have to stare before I understand it the less pretty the code becomes. I &lt;em&gt;wrote&lt;/em&gt; frabjous and I had several multi-minute &amp;#8220;WTF?!&amp;#8221; moments.&lt;/p&gt;
&lt;p&gt;So, frabjous may or may not be released today. But when it is released it&amp;#8217;ll be pretty even if i have to go medieval on it.&lt;/p&gt;</content:encoded>
	<dc:date>2008-06-22T12:59:47+00:00</dc:date>
	<dc:creator>kevin</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-855944390206940143.post-3592269825987137569">
	<title>EazyErl!: Quick Tip, list join</title>
	<link>http://easyerl.blogspot.com/2008/06/quick-tip-list-join.html</link>
	<content:encoded>Another &quot;lists:join&quot; :&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Join = fun([X|Rest], D) -&amp;gt; &lt;br /&gt;  [ X | [ [D,E] || E &amp;lt;- Rest ] ] &lt;br /&gt;  end.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Usage:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;io:format(&quot;~s~n&quot;, [Join([&quot;a&quot;, &quot;b&quot;, &quot;cde&quot;, &quot;h&quot;, &quot;k&quot;, &quot;lm&quot;], $,)]).&lt;br /&gt;a,b,cde,h,k,lm&lt;br /&gt;ok&lt;br /&gt;&lt;/pre&gt;</content:encoded>
	<dc:date>2008-06-20T10:20:00+00:00</dc:date>
	<dc:creator>rolphin</dc:creator>
</item>
<item rdf:about="http://weblog.hypotheticalabs.com/?p=273">
	<title>Hypothetical Labs: Episode 4 Errata</title>
	<link>http://weblog.hypotheticalabs.com/?p=273</link>
	<content:encoded>&lt;p&gt;See &lt;a href=&quot;http://forums.pragprog.com/forums/73/topics/564&quot;&gt;here&lt;/a&gt; for the gory details.&lt;/p&gt;
&lt;p&gt;*sigh*&lt;/p&gt;
&lt;p&gt;A hearty thanks to &lt;a href=&quot;http://organized-ignorance.net/&quot;&gt;Jon Gretar&lt;/a&gt; for finding it. I&amp;#8217;d much rather know about a bug and fix it than let it languish in public.&lt;/p&gt;
&lt;p&gt;Also, if you haven&amp;#8217;t told me what you&amp;#8217;d like to see in the next episodes, please drop a comment on &lt;a href=&quot;http://weblog.hypotheticalabs.com/?p=272&quot;&gt;here&lt;/a&gt;. Right now I&amp;#8217;m leaning towards doing a RESTian API via Yaws or Mochiweb (haven&amp;#8217;t decided which), followed by unit testing, and then OTP. But there&amp;#8217;s still time to make your case! Comment today!&lt;/p&gt;</content:encoded>
	<dc:date>2008-06-19T17:27:41+00:00</dc:date>
	<dc:creator>kevin</dc:creator>
</item>
<item rdf:about="http://weblog.hypotheticalabs.com/?p=272">
	<title>Hypothetical Labs: Erlang By Example: Episode 4</title>
	<link>http://weblog.hypotheticalabs.com/?p=272</link>
	<content:encoded>&lt;p&gt;Mike Clark and his merry band of busy hamsters have published episode 4 in my screencast series &lt;a href=&quot;http://www.pragprog.com/screencasts/v-kserl/erlang-by-example&quot;&gt;Erlang By Example&lt;/a&gt;. The episode is the longest so far, clocking in at an epic 39 minutes. I chose mnesia as the episode&amp;#8217;s focus and used it to implement store and forwarding for messages in the chat system. If you&amp;#8217;re interested in using mnesia, wondering how to write qlc queries, or just curious what a non-trivial Erlang application looks like, I recommend checking this episode out.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m also soliciting comments on what topic I should cover next in the series. The choices and their expected durations are, in no particular order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Using OTP (2-3 episodes)&lt;/li&gt;
&lt;li&gt;Adding a REST endpoint using either Mochiweb or Yaws (2 episodes)&lt;/li&gt;
&lt;li&gt;Writing chat clients in another language like Python or Ruby (2-3 episodes)&lt;br /&gt;
&lt;em&gt;Clarification: This is meant to illustrate how to interface other languages to Erlang via Erlang&amp;#8217;s ports or other libraries such as &lt;a href=&quot;http://code.google.com/p/erlectricity/&quot;&gt;erlectricity&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Unit testing and dialyzer (1 episode)&lt;/li&gt;
&lt;li&gt;Insert the burning topic I missed here&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Please comment on this post and let me know what you&amp;#8217;d like to see next!&lt;/p&gt;</content:encoded>
	<dc:date>2008-06-18T18:48:49+00:00</dc:date>
	<dc:creator>kevin</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-855944390206940143.post-4377781961682745041">
	<title>EazyErl!: Ubuntu and Ghostscript</title>
	<link>http://easyerl.blogspot.com/2008/06/ubuntu-and-ghostscript.html</link>
	<content:encoded>On my development box, I've recently upgraded my ubuntu. The ghostscript package was also upgraded, but my erlang webservice wasn't able anymore to draw any mobile tag...&lt;br /&gt;&lt;br /&gt;I've found that the new ghostscript binary 'gs' has new command line parameters that are incompatible with their previous version...&lt;br /&gt;&lt;br /&gt;I used to initialize gs like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; Cmd = &quot;gs -sDEVICE=pngalpha -q -dNOPLATFONTS -dNOPAUSE -dGraphicsAlphaBits=2 -sOutputFile=- -&quot;,&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But that no longer works since this flushing is done only when the process quits...&lt;br /&gt;&lt;br /&gt;The correct command line is then:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; Cmd = &quot;gs -sDEVICE=pngalpha -q -dGraphicsAlphaBits=2 -sOutputFile=%stdout -dNOPROMPT&quot;,&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Everything works fine now, but I've re-read the very long Ghostscript documentation, and the solution comes from &lt;a href=&quot;http://pages.cs.wisc.edu/%7Eghost/doc/cvs/Use.htm#Parameter_switches&quot;&gt;this page&lt;/a&gt;.</content:encoded>
	<dc:date>2008-06-18T14:38:51+00:00</dc:date>
	<dc:creator>rolphin</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-7435412383881764254.post-8901001959287642946">
	<title>21st Century Code Works: Migrating a native Erlang interface to RESTful Mochiweb (with a bit of TDD)</title>
	<link>http://21ccw.blogspot.com/2008/06/migrating-native-erlang-interface-to.html</link>
	<content:encoded>The title is a bit of a mouthful, but it does contain in essence what I will show you:&lt;br /&gt;&lt;br /&gt;1. I will convert an existing native erlang &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Create,_read,_update_and_delete&quot;&gt;CRUD&lt;/a&gt; interface (a simple client-server) to use a HTTP layer.&lt;br /&gt;2. The HTTP calls will be &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Representational_State_Transfer&quot;&gt;REST&lt;/a&gt;ful.&lt;br /&gt;3. I will be using &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://code.google.com/p/mochiweb/&quot;&gt;Mochiweb&lt;/a&gt;.&lt;br /&gt;4. I will show you how to do a bit of Test-Driven-Development (TDD) for this exercise using &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://support.process-one.net/doc/display/CONTRIBS/EUnit&quot;&gt;EUnit&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;As an introduction, I suggest you read &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://steve.vinoski.net/blog/&quot;&gt;Steve Vinoski&lt;/a&gt;'s &quot;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.infoq.com/articles/vinoski-erlang-rest&quot;&gt;RESTful Services with Erlang and Yaws&lt;/a&gt;&quot;, and &quot;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blog.socklabs.com/2008/04/a_restful_web_service_demo_in/&quot;&gt;A RESTful web service demo in yaws&lt;/a&gt;&quot; by &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blog.socklabs.com/&quot;&gt;Nick Gerakines.&lt;/a&gt; They are both excellent posts, and Nick's post has a lot of interesting details, including some OTP goodness. Also check out &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://darynholmes.wordpress.com/2008/03/15/beginners-tutorial-routing-in-rails-20-with-rest-part-1-of-n/&quot;&gt;Daryn&lt;/a&gt;'s posts for a Rails twist on this topic.&lt;br /&gt;&lt;br /&gt;I will NOT be showing much error handling, simply returning a 501 response if the REST Url has&lt;br /&gt;some mistake in it.&lt;br /&gt;&lt;br /&gt;This is the plan:&lt;br /&gt;1. We will start with a working set of tests for a native CRUD interface. I will &lt;span&gt;not&lt;/span&gt; show you the actual implementation, but it is simple enough to do yourself using a process dictionary.&lt;br /&gt;2. I will show a very simple REST interface with Mochiweb, that just returns the request method type as a plaintext string. This will be tested using Inets, the native Erlang OTP internet module.&lt;br /&gt;3. We will write a translators to and from plaintext and native erlang terms (again, unit tested).&lt;br /&gt;4. We will combine all these into the REST interface, tested using Inets again.&lt;br /&gt;&lt;br /&gt;Right, here is the unit tests for the CRUD interface:&lt;pre class=&quot;code&quot;&gt;crud_test_() -&amp;gt; &lt;br /&gt; {setup,&lt;br /&gt; fun() -&amp;gt; start() end,&lt;br /&gt; fun(_) -&amp;gt; stop() end,&lt;br /&gt; fun(_) -&amp;gt;&lt;br /&gt; [&lt;br /&gt; ?_assert(ok == create(#person{id = 1})),&lt;br /&gt; ?_assert(already_exists == create(#person{id=1})),&lt;br /&gt; ?_assert(#person{id=1} == retrieve(1)),&lt;br /&gt; ?_assert(ok == update(#person{id = 1, name=&quot;Ben&quot;})),&lt;br /&gt; ?_assert(#person{id=1, name=&quot;Ben&quot;} == retrieve(1)),&lt;br /&gt; ?_assert(ok == delete(1)),&lt;br /&gt; ?_assert(undefined == delete(2)),&lt;br /&gt; ?_assert(undefined == update(#person{id = 2}))&lt;br /&gt; ]&lt;br /&gt; end}.&lt;/pre&gt;The CRUD interface is container in a module &quot;crud&quot;, and start() and stop() are methods to start and stop the CRUD server. For EUnit, you can define a test with a setup, teardown and tests, and this is the form that I've used here. There are many forms of tests for EUnit, and I suggest you consult the EUnit documentation (contained in the EUnit distribution).&lt;br /&gt;&lt;br /&gt;EUnit automatically creates a test() function on the module when you include &quot;eunit.hrl&quot;, so let's run the crud tests:&lt;pre class=&quot;console&quot;&gt;&lt;br /&gt;75&amp;gt; crud:test().&lt;br /&gt;All 8 tests successful.&lt;br /&gt;ok&lt;br /&gt;&lt;/pre&gt;We know that are CRUD interface is working OK.&lt;br /&gt;&lt;br /&gt;Onto Step 2! If you're not familiar with Mochiweb, it's a lightweight web server developed by the guys at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mochimedia.com/&quot;&gt;Mochi Media&lt;/a&gt;. It's very easy to integrate into you application, and has very little configuration.&lt;br /&gt;&lt;br /&gt;Here are the tests for the simple Mochiweb demo:&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;-define(URL, &quot;http://127.0.0.1:8888&quot;).&lt;br /&gt;&lt;br /&gt;rest_server_test_() -&amp;gt;&lt;br /&gt; {setup,&lt;br /&gt; fun() -&amp;gt; inets:start(), start_simple() end,&lt;br /&gt; fun(_) -&amp;gt; inets:stop(), stop_simple() end,&lt;br /&gt; fun(_) -&amp;gt;&lt;br /&gt; [&lt;br /&gt; ?_assert(http_result('GET') =:= &quot;GET&quot;),&lt;br /&gt; ?_assert(http_result('PUT') =:= &quot;PUT&quot;),&lt;br /&gt; ?_assert(http_result('POST') =:= &quot;POST&quot;),&lt;br /&gt; ?_assert(http_result('DELETE') =:= &quot;DELETE&quot;)&lt;br /&gt; ]&lt;br /&gt; end}.&lt;br /&gt;&lt;br /&gt;parse_result(Result) -&amp;gt;&lt;br /&gt; {ok, {{_Version, 200, _ReasonPhrase}, _Headers, ResultBody}} = Result,&lt;br /&gt; ResultBody.&lt;br /&gt;&lt;br /&gt;rest_server_test_() -&amp;gt;&lt;br /&gt; {setup,&lt;br /&gt; fun() -&amp;gt; inets:start(), start_simple() end,&lt;br /&gt; fun(_) -&amp;gt; inets:stop(), stop_simple() end,&lt;br /&gt; fun(_) -&amp;gt;&lt;br /&gt; [&lt;br /&gt; ?_assert(http_result('GET') =:= &quot;GET&quot;),&lt;br /&gt; ?_assert(http_result('PUT') =:= &quot;PUT&quot;),&lt;br /&gt; ?_assert(http_result('POST') =:= &quot;POST&quot;),&lt;br /&gt; ?_assert(http_result('DELETE') =:= &quot;DELETE&quot;)&lt;br /&gt; ]&lt;br /&gt; end}.&lt;br /&gt;&lt;/pre&gt;start_simple() starts the simple version of the server and stop_simple() stops it. We're just using the base URL, and the server just returns a plain-text string of the request method. The http:request() functions are part of Inets (documentation &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang.org/doc/apps/inets/index.html&quot;&gt;here&lt;/a&gt;). You will notice that the put and post functions have extra parameters (which we will use later for the request body).&lt;br /&gt;&lt;br /&gt;Here's the solution:&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;start_simple() -&amp;gt;&lt;br /&gt; mochiweb_http:start(&lt;br /&gt; [{ip, &quot;127.0.0.1&quot;},&lt;br /&gt; {loop, {?MODULE, simple_response}}]).&lt;br /&gt;stop_simple() -&amp;gt;&lt;br /&gt; mochiweb_http:stop().&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;simple_response(Req, Method) -&amp;gt;&lt;br /&gt; Req:ok({&quot;text/plain&quot;, atom_to_list(Method)}).&lt;br /&gt;simple_response(Req) -&amp;gt;&lt;br /&gt; simple_response(Req, Req:get(method)).&lt;br /&gt;&lt;/pre&gt;We've started Mochiweb, and told it that the &quot;simple_response&quot; function in the current module should be used to handle requests. It takes one parameter, which contains the request data. The data can be queried with different methods to extract data from it, e.g. Req:get(method), gives you the method used.&lt;br /&gt;&lt;br /&gt;The Req:ok() function is used to respond to a request, and we simply return plain text (with the text/plain MIME type).&lt;br /&gt;&lt;br /&gt;And let's run the tests:&lt;pre class=&quot;console&quot;&gt;&lt;br /&gt;77&amp;gt; rest_server:test().&lt;br /&gt;...&lt;br /&gt;All 4 tests successful.&lt;br /&gt;ok&lt;br /&gt;&lt;/pre&gt;Nice. The next bit of code we need is to translate Erlang terms to and from plain text. We'll use Base64 encoding for this. Erlang also has very hand term to binary and binary to term functions that we can use to achieve the translation.&lt;br /&gt;&lt;br /&gt;The tests for the translation:&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;term_to_plaintext_test_() -&amp;gt;&lt;br /&gt; A = anatom,&lt;br /&gt; B = {a, 23, &quot;abc&quot;},&lt;br /&gt; C = {props, [{a,3},{b,4}]},&lt;br /&gt; [&lt;br /&gt; ?_assert(A == ptt(ttp(A))),&lt;br /&gt; ?_assert(B == ptt(ttp(B))),&lt;br /&gt; ?_assert(C == ptt(ttp(C)))&lt;br /&gt; ].&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Where &quot;ttp&quot; would be &quot;term_to_plaintext&quot; and &quot;ptt&quot; is&lt;br /&gt;&quot;plaintext_to_term&quot;. Here's the implementation:&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;ttp(Term) -&amp;gt;&lt;br /&gt; base64:encode_to_string(term_to_binary(Term)).&lt;br /&gt;&lt;br /&gt;ptt(PlainText) -&amp;gt;&lt;br /&gt; binary_to_term(base64:decode(PlainText)).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And the test result:&lt;pre class=&quot;console&quot;&gt;&lt;br /&gt;77&amp;gt; rest_server:test().&lt;br /&gt;...&lt;br /&gt;All 7 tests successful.&lt;br /&gt;ok&lt;br /&gt;&lt;/pre&gt;(7 tests, since we have the first 4 and now the extra 3). Now things are getting a bit more complicated. We now have to ensure that the response to the request is converted from the native Erlang terms to plaintext, this result is then returned, and we also need a function to convert the request result into the native form.&lt;br /&gt;&lt;br /&gt;Here we go:&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;result_to_terms(Result) -&amp;gt;&lt;br /&gt; {ok, {{_Version, 200, _ReasonPhrase}, _Headers, ResultBody}} = Result,&lt;br /&gt; ptt(ResultBody).&lt;br /&gt;&lt;br /&gt;rest_api('GET', Path) -&amp;gt;&lt;br /&gt; Result = http:request(get, {?URL ++ Path, []}, [], []),&lt;br /&gt; result_to_terms(Result);&lt;br /&gt;rest_api('DELETE', Path) -&amp;gt;&lt;br /&gt; Result = http:request(delete, {?URL ++ Path, []}, [], []),&lt;br /&gt; result_to_terms(Result).&lt;br /&gt;&lt;br /&gt;rest_api('POST', Path, Data) -&amp;gt;&lt;br /&gt; Result = http:request(post, {?URL ++ Path, [], [], ttp(Data)}, [], []),&lt;br /&gt; result_to_terms(Result);&lt;br /&gt;rest_api('PUT', Path, Data) -&amp;gt;&lt;br /&gt; Result = http:request(put, {?URL ++ Path, [], [], ttp(Data)}, [], []),&lt;br /&gt; result_to_terms(Result).&lt;br /&gt;&lt;br /&gt;crud_server_test_() -&amp;gt;&lt;br /&gt; {setup,&lt;br /&gt; fun() -&amp;gt; crud:start(), inets:start(), start() end,&lt;br /&gt; fun(_) -&amp;gt; stop(), inets:stop(), crud:stop() end,&lt;br /&gt; fun(_) -&amp;gt;&lt;br /&gt; [&lt;br /&gt; ?_assert(ok == rest_api('POST', &quot;/person&quot;, #person{id = 1})),&lt;br /&gt; ?_assert(already_exists == rest_api('POST', &quot;/person&quot;, #person{id = 1})),&lt;br /&gt; ?_assert(#person{id=1} == rest_api('GET', &quot;/person/1&quot;)),&lt;br /&gt; ?_assert(ok == rest_api('PUT', &quot;/person/1&quot;, #person{name=&quot;Ben&quot;})),&lt;br /&gt; ?_assert(#person{id=1, name=&quot;Ben&quot;} == rest_api('GET', &quot;/person/1&quot;)),&lt;br /&gt; ?_assert(ok == rest_api('DELETE', &quot;/person/1&quot;)),&lt;br /&gt; ?_assert(undefined == rest_api('DELETE', &quot;/person/1&quot;)),&lt;br /&gt; ?_assert(undefined == rest_api('PUT', &quot;/person/1&quot;, #person{id = 2}))&lt;br /&gt; ]&lt;br /&gt; end}.&lt;br /&gt;&lt;/pre&gt;There is a bit of duplication here, but for illustration I've kept the functions seperate. You will notice that the data is converted to plaintext for the PUT and POST requests. result_to_terms() converts the HTTP result from the plain text to the native Erlang terms.&lt;br /&gt;&lt;br /&gt;You can scroll back to the original CRUD tests, and notice that the tests do exactly the same thing as on the CRUD interface, but we would have to do a &quot;GET&quot; + &quot;/person/1&quot; to get person 1, instead of doing a crud:retrieve(1).&lt;br /&gt;&lt;br /&gt;The mapping between the CRUD and REST method are as follows:&lt;br /&gt;GET &amp;lt;=&amp;gt; RETRIEVE&lt;br /&gt;POST &amp;lt;=&amp;gt; CREATE&lt;br /&gt;PUT &amp;lt;=&amp;gt; UPDATE&lt;br /&gt;DELETE &amp;lt;=&amp;gt;DELETE&lt;br /&gt;&lt;br /&gt;Here's the final product:&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;br /&gt;start() -&amp;gt;&lt;br /&gt; mochiweb_http:start(&lt;br /&gt; [{ip, &quot;127.0.0.1&quot;},&lt;br /&gt; {loop, {?MODULE, crud_response}}]).&lt;br /&gt;stop() -&amp;gt;&lt;br /&gt; mochiweb_http:stop().&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;crud_response(Req, 'GET', &quot;/person/&quot; ++ IdString) -&amp;gt;&lt;br /&gt; Id = list_to_integer(IdString),&lt;br /&gt; Response = crud:retrieve(Id),&lt;br /&gt; Req:ok({&quot;text/plain&quot;, ttp(Response)});&lt;br /&gt;&lt;br /&gt;crud_response(Req, 'DELETE', &quot;/person/&quot; ++ IdString) -&amp;gt;&lt;br /&gt; Id = list_to_integer(IdString),&lt;br /&gt; Response = crud:delete(Id),&lt;br /&gt; Req:ok({&quot;text/plain&quot;, ttp(Response)});&lt;br /&gt;&lt;br /&gt;crud_response(Req, 'POST', &quot;/person&quot;) -&amp;gt;&lt;br /&gt; Body = Req:recv_body(),&lt;br /&gt; Person = ptt(Body),&lt;br /&gt; Response = crud:create(Person),&lt;br /&gt; Req:ok({&quot;text/plain&quot;, ttp(Response)});&lt;br /&gt;&lt;br /&gt;crud_response(Req, 'PUT', &quot;/person/&quot; ++ IdString) -&amp;gt;&lt;br /&gt; Id = list_to_integer(IdString),&lt;br /&gt; Body = Req:recv_body(),&lt;br /&gt; PersonWithNewValues = ptt(Body),&lt;br /&gt; UpdatedPerson = #person{id = Id, &lt;br /&gt; name = PersonWithNewValues#person.name, &lt;br /&gt; email_address = PersonWithNewValues#person.email_address},&lt;br /&gt; Response = crud:update(UpdatedPerson),&lt;br /&gt; Req:ok({&quot;text/plain&quot;, ttp(Response)});&lt;br /&gt; &lt;br /&gt;crud_response(Req, _Method, Path) -&amp;gt;&lt;br /&gt; Req:respond({501, [], Path}).&lt;br /&gt;&lt;br /&gt;crud_response(Req) -&amp;gt;&lt;br /&gt; crud_response(Req, Req:get(method), Req:get(path)).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Once again, there is some duplication, but it's easier to grasp when we split the functions. The GET and DELETE requests are simple to handle, since we just convert the Id string to an integer (which could throw an exception, you would have to handle that in some way), and call the CRUD interface.&lt;br /&gt;&lt;br /&gt;POST is not much more complicated, we just get the body of the request using Req:recv_body().&lt;br /&gt;&lt;br /&gt;The PUT function has a problem. There is duplication of the Id of the person, in both the URL &quot;/person/1&quot;, and the actual term, #person{id=1,...}. I'm not sure how to handle this, comments are welcome. Perhaps you can generate an error response if the Ids don't match. Or you can make sure the posted record does NOT contain an Id field, and return an error if it does.&lt;br /&gt;&lt;br /&gt;The solution as I've given it, uses the fields in the record, and ignores the Id of the record, using the Id in the URL instead.&lt;br /&gt;&lt;br /&gt;The last function generates an error if the request could not be matched.&lt;br /&gt;&lt;br /&gt;And the moment of truth:&lt;pre class=&quot;console&quot;&gt;81&amp;gt; rest_server:test().&lt;br /&gt;...&lt;br /&gt;All 15 tests successful.&lt;br /&gt;ok&lt;/pre&gt;Looks so simple now, but I can asure you that it took some effort to get all the tests to pass!&lt;br /&gt;&lt;br /&gt;Well I hope I've shown you something that you didn't know before, or even encouraged you to learn some Erlang. &lt;br /&gt;&lt;br /&gt;Comments and criticisms are most welcome :)</content:encoded>
	<dc:date>2008-06-17T06:07:00+00:00</dc:date>
</item>
<item rdf:about="tag:blogger.com,1999:blog-6265608756663924839.post-1240176153328288267">
	<title>Dukes of Erl: generating app files</title>
	<link>http://dukesoferl.blogspot.com/2008/06/generating-app-files.html</link>
	<content:encoded>We automatically generate our .app files around here from analysis of the source code.  However this trick is buried inside &lt;a href=&quot;http://code.google.com/p/fwtemplates/wiki/FwTemplateErlangWalkthrough&quot;&gt;fw-template-erlang&lt;/a&gt; which most (all?) people outside our group do not use.  I thought I'd highlight how it works.&lt;br /&gt;&lt;br /&gt;A typical &lt;a href=&quot;http://www.erlang.org/doc/design_principles/applications.html#appl_res_file&quot;&gt;OTP application specification&lt;/a&gt; file looks like:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;{ application, walkenfs,&lt;br /&gt;[&lt;br /&gt;  { description, &quot;Distributed filesystem.&quot; },&lt;br /&gt;  { vsn, &quot;0.1.7&quot; },&lt;br /&gt;  { modules, [ walkenfssup, walkenfsfragmentsrv, walkenfs, walkenfssrv ] },&lt;br /&gt;  { registered, [ walkenfsfragmentsrv ] },&lt;br /&gt;  { applications, [ kernel, stdlib   ] },&lt;br /&gt;  { mod, { walkenfs, [] } },&lt;br /&gt;  { env, [ { linked_in, false }, { mount_opts, &quot;&quot; }, { mount_point, &quot;/walken&quot; }, { prefix, walken }, { read_data_context, async_dirty }, { write_data_context, sync_dirty }, { read_meta_context, transaction }, { write_meta_context, sync_transaction }, { attr_timeout_ms, 0 }, { entry_timeout_ms, 0 }, { reuse_node, true }, { start_timeout, infinity }, { stop_timeout, 1800000 }, { init_fragments, 7 }, { init_copies, 3 }, { copy_type, n_disc_only_copies }, { buggy_ets, auto_detect }, { port_exit_stop, true } ] }&lt;br /&gt;&lt;br /&gt;]&lt;br /&gt;}.&lt;br /&gt;&lt;/pre&gt;There are alot of bits here that can filled in automatically.  It helps to think in terms of the template:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;{ application, @FW_PACKAGE_NAME@,&lt;br /&gt;[&lt;br /&gt;  { description, &quot;@FW_PACKAGE_SHORT_DESCRIPTION@&quot; },&lt;br /&gt;  { vsn, &quot;@FW_PACKAGE_VERSION@&quot; },&lt;br /&gt;  { modules, [ @FW_ERL_APP_MODULES@ ] },&lt;br /&gt;  { registered, [ @FW_ERL_APP_REGISTERED@ ] },&lt;br /&gt;  { applications, [ kernel, stdlib @FW_ERL_PREREQ_APPLICATIONS@ ] },&lt;br /&gt;  @FW_ERL_APP_MOD_LINE@&lt;br /&gt;  { env, @FW_ERL_APP_ENVIRONMENT@ }&lt;br /&gt;  @FW_ERL_APP_EXTRA@&lt;br /&gt;]&lt;br /&gt;}.&lt;br /&gt;&lt;/pre&gt;This is an &quot;automake&quot; style template where @VARIABLE@ indicates something that will be substituted.&lt;br /&gt;&lt;br /&gt;Now we can say where each of these templates values comes from when using fw-template-erlang:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;FW_PACKAGE_NAME: specified by the developer.  if you're using automake you've had to specify this already via &lt;a href=&quot;http://www.gnu.org/software/autoconf/manual/autoconf-2.57/html_node/autoconf_16.html&quot;&gt;AC_INIT&lt;/a&gt;, so it's good to reuse that rather than require duplicate specification.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;FW_PACKAGE_SHORT_DESCRIPTION:  specified by the developer.&lt;/li&gt;&lt;li&gt;FW_PACKAGE_VERSION: specified by the developer; like the package name, if you're using automake this information is already contained in the arguments to AC_INIT so reuse that.&lt;/li&gt;&lt;li&gt;FW_ERL_APP_MODULES: generated by analysis of the source code directory.&lt;/li&gt;&lt;li&gt;FW_ERL_APP_REGISTERED: generated by analysis of the source code directory.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;FW_ERL_PREREQ_APPLICATIONS: specified by the developer.&lt;/li&gt;&lt;li&gt;FW_ERL_MOD_LINE: partially generated by analysis of the source code directory, partially specified by the developer (see below).&lt;/li&gt;&lt;li&gt;FW_ERL_APP_ENVIRONMENT: specified by the developer.&lt;/li&gt;&lt;li&gt;FW_ERL_APP_EXTRA: specified by the developer.  this is for unusual extra directives like included applications.&lt;/li&gt;&lt;/ol&gt;So the interesting bits come down to FW_ERL_APP_MODULES, FW_ERL_APP_REGISTERED, and FW_ERL_MOD_LINE being generated automatically via inspection of the source code.&lt;br /&gt;&lt;br /&gt;First, a note on intervention.  Anytime you are attempting to automate a task that was previous done by humans, it's helps to allow a human to override any of the automatic settings that you generate by default.  That way, you can be correct only 95% of the time and still be a huge timesaver.  In practice we've found that although it easy to come up with code examples that flummox the automatic strategies, such code is never actually written by people in the normal course of their work.  In fact, we've found that application files we get from the universe are often missing registered process names that our automatic strategy finds.  So empirically we're running at 100% correct so far, but fw-template-erlang still contains the capability to override any automatically generated value.&lt;br /&gt;&lt;br /&gt;Now the actual trick to computing all the stuff is that Erlang contains an Erlang compiler as a library. Here's an example of leveraging this to generate all the module names from a set of files; any file that contains a &lt;pre&gt;-fwskip()&lt;/pre&gt; directive will be ignored.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;-module (find_modules).&lt;br /&gt;-export ([ main/1 ]).&lt;br /&gt;&lt;br /&gt;is_skipped ([]) -&gt; false;&lt;br /&gt;is_skipped ([ { attribute, _, fwskip, _ } | _ ]) -&gt; true;&lt;br /&gt;is_skipped ([ _ | Rest ]) -&gt; is_skipped (Rest).&lt;br /&gt;&lt;br /&gt;print_module (Dir, F) -&gt;&lt;br /&gt;case compile:file (F, [ binary, 'E', { outdir, Dir } ]) of&lt;br /&gt;{ ok, Mod, { Mod, _, Forms } } -&gt;&lt;br /&gt;case is_skipped (Forms) of&lt;br /&gt;  true -&gt;&lt;br /&gt;    ok;&lt;br /&gt;  false -&gt;&lt;br /&gt;    port_command (get (three), io_lib:format (&quot;~p~n&quot;, [ Mod ]))&lt;br /&gt;end;&lt;br /&gt;_ -&gt;&lt;br /&gt;ok&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;main ([ Dir | Rest ]) -&gt;&lt;br /&gt;ok = file:make_dir (Dir),&lt;br /&gt;&lt;br /&gt;try&lt;br /&gt;  Three = open_port ({ fd, 0, 3 }, [ out ]),&lt;br /&gt;% ugh ... don't want to have to change all these function signatures,&lt;br /&gt;% so i'm gonna be dirty&lt;br /&gt;  put (three, Three),&lt;br /&gt;  lists:foreach (fun (F) -&gt; print_module (Dir, F) end, Rest)&lt;br /&gt;after&lt;br /&gt;  { ok, FileNames } = file:list_dir (Dir),&lt;br /&gt;  lists:foreach (fun (F) -&gt; file:delete (Dir ++ &quot;/&quot; ++ F) end, FileNames),&lt;br /&gt;  file:del_dir (Dir)&lt;br /&gt;end;&lt;br /&gt;main ([]) -&gt;&lt;br /&gt;Port = open_port ({ fd, 0, 2 }, [ out ]),&lt;br /&gt;port_command (Port, &quot;usage: find-modules.esc tmpdir filename [filename ...]\n&quot;),&lt;br /&gt;halt (1).&lt;br /&gt;&lt;/pre&gt;The output is on file descriptor 3 in order to isolate the desired output from various messages being output by the Erlang code.  This was originally an escript but to be compatible with older versions of Erlang we changed it to run as follows:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#! /bin/sh&lt;br /&gt;&lt;br /&gt;# NB: this script is called find-modules.sh&lt;br /&gt;&lt;br /&gt;# unfortunately, escript is a recent innovation ...&lt;br /&gt;&lt;br /&gt;ERL_CRASH_DUMP=/dev/null&lt;br /&gt;export ERL_CRASH_DUMP&lt;br /&gt;&lt;br /&gt;erl -pa &quot;${FW_ROOT}/share/fw/template/erlang/&quot; -pa &quot;${FW_ROOT}/share/fw.local/template/erlang&quot; -pa &quot;${top_srcdir}/fw/template/erlang/&quot; -pa &quot;${top_srcdir}/fw.local/template/erlang&quot; -noshell -noinput -eval '&lt;br /&gt;find_modules:main (init:get_plain_arguments ()),&lt;br /&gt;halt (0).&lt;br /&gt;' -extra &quot;$@&quot; 3&gt;&amp;amp;1 &gt;/dev/null&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In practice this gets executed like&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;find src -name '*.erl' -print | xargs find-modules.sh &quot;$tmpdir&quot; |&lt;br /&gt;perl -ne 'chomp;&lt;br /&gt;     next if $seen{$_}++;&lt;br /&gt;     print &quot;, &quot; if $f;&lt;br /&gt;     print $_;&lt;br /&gt;     $f = 1;'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ok, that was the easy one!  In fact, the problem of finding all the module names seems so easy that one could be tempted to solve it with grep (hmmm: what about preprocesser directives ?).  However the point is that nothing parses Erlang as well as Erlang, so why reinvent the wheel.&lt;br /&gt;&lt;br /&gt;Computing the mod line in the application specification is just slightly harder.  Basically we scan source code for a module which has a &lt;pre&gt;-behaviour(application)&lt;/pre&gt; attribute and assume that is the start module.  The Erlang compiler allows behaviour to be (mis)spelt American-style so we allow that as well.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;-module (find_start_module).&lt;br /&gt;-export ([ main/1 ]).&lt;br /&gt;&lt;br /&gt;is_application ([]) -&gt; false;&lt;br /&gt;is_application ([ { attribute, _, behaviour, [ application ] } | _ ]) -&gt; true;&lt;br /&gt;is_application ([ { attribute, _, behavior, [ application ] } | _ ]) -&gt; true;&lt;br /&gt;is_application ([ _ | Rest ]) -&gt; is_application (Rest).&lt;br /&gt;&lt;br /&gt;is_skipped ([]) -&gt; false;&lt;br /&gt;is_skipped ([ { attribute, _, fwskip, _ } | _ ]) -&gt; true;&lt;br /&gt;is_skipped ([ _ | Rest ]) -&gt; is_skipped (Rest).&lt;br /&gt;&lt;br /&gt;find_start_module (_, []) -&gt;&lt;br /&gt;ok;&lt;br /&gt;find_start_module (Dir, [ F | Rest ]) -&gt;&lt;br /&gt;case compile:file (F, [ binary, 'E', { outdir, Dir } ]) of&lt;br /&gt;{ ok, Mod, { Mod, _, Forms } } -&gt;&lt;br /&gt;  case is_application (Forms) and not is_skipped (Forms) of&lt;br /&gt;    true -&gt;&lt;br /&gt;      port_command (get (three), io_lib:format (&quot;~p~n&quot;, [ Mod ]));&lt;br /&gt;    false -&gt;&lt;br /&gt;      find_start_module (Dir, Rest)&lt;br /&gt;  end;&lt;br /&gt;_ -&gt;&lt;br /&gt;  find_start_module (Dir, Rest)&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;main ([ Dir | Rest ]) -&gt;&lt;br /&gt;ok = file:make_dir (Dir),&lt;br /&gt;&lt;br /&gt;try&lt;br /&gt;Three = open_port ({ fd, 0, 3 }, [ out ]),&lt;br /&gt;% ugh ... don't want to have to change all these function signatures,&lt;br /&gt;% so i'm gonna be dirty&lt;br /&gt;put (three, Three),&lt;br /&gt;find_start_module (Dir, Rest)&lt;br /&gt;after&lt;br /&gt;{ ok, FileNames } = file:list_dir (Dir),&lt;br /&gt;lists:foreach (fun (F) -&gt; file:delete (Dir ++ &quot;/&quot; ++ F) end, FileNames),&lt;br /&gt;file:del_dir (Dir)&lt;br /&gt;end;&lt;br /&gt;main ([]) -&gt;&lt;br /&gt;Port = open_port ({ fd, 0, 2 }, [ out ]),&lt;br /&gt;port_command (Port, &quot;usage: find-modules.esc tmpdir filename [filename ...]\n&quot;),&lt;br /&gt;halt (1).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If there are no applications in the set of files being analyzed, we output nothing for the mod line in the application file, otherwise we output &lt;pre&gt;{ mod, { @FW_ERL_APP_START_MODULE@, @FW_ERL_APP_START_ARGS@ } },&lt;/pre&gt; where FW_ERL_APP_START_MODULE is the output of the above command and FW_ERL_APP_START_ARGS is indicated by the programmer (we use [] by default for FW_ERL_APP_START_ARGS and in practice never use the field).  Obviously, if multiple modules implementing the application behaviour are found then this will not work.  Our style has been to put each application we make in a separate directory to facilitate automatic analysis.&lt;br /&gt;&lt;br /&gt;Anyway now we can tackle the more challenging problem of finding registered processes.  There are many library calls that end up registering a process name; the ones we recognize are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;supervisor child specs that contain calls of the form&lt;/li&gt;&lt;ul&gt;&lt;li&gt;{ _, start, [ { local, xxx }, ... ] } -&gt; xxx being registered&lt;/li&gt;&lt;li&gt;{ _, start_link, [ { local, xxx }, ... ] } -&gt; xxx being registered&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;function calls of the form&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Module:start ({ local, xxx }, ...) -&gt; xxx being registered&lt;/li&gt;&lt;li&gt;Module:start_link ({ local, xxx }, ...) -&gt; xxx being registered&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;calls to erlang:register (xxx, ...) -&gt; xxx being registered&lt;/li&gt;&lt;/ul&gt;There's alot of code here but the general idea is the same:  walk the forms generated by compile and pattern match on one of the above cases, outputting discovered registered process names to file descriptor 3.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;-module (find_registered).&lt;br /&gt;-export ([ main/1 ]).&lt;br /&gt;&lt;br /&gt;%% looks like fun_clauses are the same as clauses (?)&lt;br /&gt;print_registered_fun_clauses (Clauses) -&gt;&lt;br /&gt;print_registered_clauses (Clauses).&lt;br /&gt;&lt;br /&gt;%% looks like icr_clauses are the same as clauses (?)&lt;br /&gt;print_registered_icr_clauses (Clauses) -&gt;&lt;br /&gt;print_registered_clauses (Clauses).&lt;br /&gt;&lt;br /&gt;print_registered_inits (Inits) -&gt;&lt;br /&gt;lists:foreach (fun ({ record_field, _, _, E }) -&gt;&lt;br /&gt;               print_registered_expr (E);&lt;br /&gt;                 (_) -&gt;&lt;br /&gt;               ok&lt;br /&gt;             end,&lt;br /&gt;             Inits).&lt;br /&gt;&lt;br /&gt;print_registered_upds (Upds) -&gt;&lt;br /&gt;lists:foreach (fun ({ record_field, _, _, E }) -&gt;&lt;br /&gt;               print_registered_expr (E);&lt;br /&gt;                 (_) -&gt;&lt;br /&gt;               ok&lt;br /&gt;             end,&lt;br /&gt;             Upds).&lt;br /&gt;&lt;br /&gt;% hmmm ... pretty sure patterns are not supposed to have side-effects ...&lt;br /&gt;print_registered_pattern (_) -&gt; ok.&lt;br /&gt;print_registered_pattern_group (_) -&gt; ok.&lt;br /&gt;&lt;br /&gt;print_registered_quals (Qs) -&gt;&lt;br /&gt;lists:foreach (fun ({ generate, _, P, E }) -&gt;&lt;br /&gt;               print_registered_pattern (P),&lt;br /&gt;               print_registered_expr (E);&lt;br /&gt;                 ({ b_generate, _, P, E }) -&gt;&lt;br /&gt;               print_registered_pattern (P),&lt;br /&gt;               print_registered_expr (E);&lt;br /&gt;                 (E) -&gt;&lt;br /&gt;               print_registered_expr (E)&lt;br /&gt;             end,&lt;br /&gt;             Qs).&lt;br /&gt;&lt;br /&gt;print_registered_expr ({ cons, _, H, T }) -&gt;&lt;br /&gt;print_registered_expr (H),&lt;br /&gt;print_registered_expr (T);&lt;br /&gt;print_registered_expr ({ lc, _, E, Qs }) -&gt;&lt;br /&gt;print_registered_expr (E),&lt;br /&gt;print_registered_quals (Qs);&lt;br /&gt;print_registered_expr ({ bc, _, E, Qs }) -&gt;&lt;br /&gt;print_registered_expr (E),&lt;br /&gt;print_registered_quals (Qs);&lt;br /&gt;&lt;br /&gt;%% Ok, here's some meat:&lt;br /&gt;%% the &quot;supervisor child spec&quot; rule&lt;br /&gt;%% { _, start, [ { local, xxx }, ... ] } -&gt; xxx being registered&lt;br /&gt;%% { _, start_link, [ { local, xxx }, ... ] } -&gt; xxx being registered&lt;br /&gt;print_registered_expr ({ tuple, _,&lt;br /&gt;                     Exprs=[ _,&lt;br /&gt;                       { atom, _, Func },&lt;br /&gt;                       { cons,&lt;br /&gt;                         _,&lt;br /&gt;                         { tuple, _, [ { atom, _, local },&lt;br /&gt;                                       { atom, _, Name } ] },&lt;br /&gt;                         _ } ] }) when (Func =:= start) or&lt;br /&gt;                                       (Func =:= start_link) -&gt;&lt;br /&gt;port_command (get (three), io_lib:format (&quot;~p~n&quot;, [ Name ])),&lt;br /&gt;print_registered_exprs (Exprs);&lt;br /&gt;&lt;br /&gt;print_registered_expr ({ tuple, _, Exprs }) -&gt;&lt;br /&gt;print_registered_exprs (Exprs);&lt;br /&gt;print_registered_expr ({ record_index, _, _, E }) -&gt;&lt;br /&gt;print_registered_expr (E);&lt;br /&gt;print_registered_expr ({ record, _, _, Inits }) -&gt;&lt;br /&gt;print_registered_inits (Inits);&lt;br /&gt;print_registered_expr ({ record_field, _, E0, _, E1 }) -&gt;&lt;br /&gt;print_registered_expr (E0),&lt;br /&gt;print_registered_expr (E1);&lt;br /&gt;print_registered_expr ({ record, _, E, _, Upds }) -&gt;&lt;br /&gt;print_registered_expr (E),&lt;br /&gt;print_registered_upds (Upds);&lt;br /&gt;print_registered_expr ({ record_field, _, E0, E1 }) -&gt;&lt;br /&gt;print_registered_expr (E0),&lt;br /&gt;print_registered_expr (E1);&lt;br /&gt;print_registered_expr ({ block, _, Exprs }) -&gt;&lt;br /&gt;print_registered_exprs (Exprs);&lt;br /&gt;print_registered_expr ({ 'if', _, IcrClauses }) -&gt;&lt;br /&gt;print_registered_icr_clauses (IcrClauses);&lt;br /&gt;print_registered_expr ({ 'case', _, E, IcrClauses }) -&gt;&lt;br /&gt;print_registered_expr (E),&lt;br /&gt;print_registered_icr_clauses (IcrClauses);&lt;br /&gt;print_registered_expr ({ 'receive', _, IcrClauses }) -&gt;&lt;br /&gt;print_registered_icr_clauses (IcrClauses);&lt;br /&gt;print_registered_expr ({ 'receive', _, IcrClauses, E, Exprs }) -&gt;&lt;br /&gt;print_registered_icr_clauses (IcrClauses),&lt;br /&gt;print_registered_expr (E),&lt;br /&gt;print_registered_exprs (Exprs);&lt;br /&gt;print_registered_expr ({ 'try', _, Exprs0, IcrClauses0, IcrClauses1, Exprs1 }) -&gt;&lt;br /&gt;print_registered_exprs (Exprs0),&lt;br /&gt;print_registered_icr_clauses (IcrClauses0),&lt;br /&gt;print_registered_icr_clauses (IcrClauses1),&lt;br /&gt;print_registered_exprs (Exprs1);&lt;br /&gt;print_registered_expr ({ 'fun', _, Body }) -&gt;&lt;br /&gt;case Body of&lt;br /&gt;  { clauses, Cs } -&gt;&lt;br /&gt;    print_registered_fun_clauses (Cs);&lt;br /&gt;  _ -&gt;&lt;br /&gt;    ok&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;%% Ok, here's some meat:&lt;br /&gt;%% Module:start ({ local, xxx }, ...) -&gt; xxx being registered&lt;br /&gt;%% Module:start_link ({ local, xxx }, ...) -&gt; xxx being registered&lt;br /&gt;&lt;br /&gt;print_registered_expr ({ call,&lt;br /&gt;                     _,&lt;br /&gt;                     E={ remote, _, _, { atom, _, Func } },&lt;br /&gt;                     Exprs=[ { tuple, _, [ { atom, _, local },&lt;br /&gt;                                           { atom, _, Name } ] } | _ ] })&lt;br /&gt;                        when (Func =:= start) or&lt;br /&gt;                             (Func =:= start_link) -&gt;&lt;br /&gt;port_command (get (three), io_lib:format (&quot;~p~n&quot;, [ Name ])),&lt;br /&gt;print_registered_expr (E),&lt;br /&gt;print_registered_exprs (Exprs);&lt;br /&gt;&lt;br /&gt;%% Ok, here's some meat:&lt;br /&gt;%% erlang:register (xxx, ...) -&gt; xxx being registered&lt;br /&gt;&lt;br /&gt;print_registered_expr ({ call,&lt;br /&gt;                     _,&lt;br /&gt;                     { remote,&lt;br /&gt;                       _,&lt;br /&gt;                       { atom, _, erlang },&lt;br /&gt;                       { atom, _, register } },&lt;br /&gt;                     Exprs=[ { atom, _, Name } | _ ] }) -&gt;&lt;br /&gt;port_command (get (three), io_lib:format (&quot;~p~n&quot;, [ Name ])),&lt;br /&gt;print_registered_exprs (Exprs);&lt;br /&gt;&lt;br /&gt;print_registered_expr ({ call, _, E, Exprs }) -&gt;&lt;br /&gt;print_registered_expr (E),&lt;br /&gt;print_registered_exprs (Exprs);&lt;br /&gt;print_registered_expr ({ 'catch', _, E }) -&gt;&lt;br /&gt;print_registered_expr (E);&lt;br /&gt;print_registered_expr ({ 'query', _, E }) -&gt;&lt;br /&gt;print_registered_expr (E);&lt;br /&gt;print_registered_expr ({ match, _, P, E }) -&gt;&lt;br /&gt;print_registered_pattern (P),&lt;br /&gt;print_registered_expr (E);&lt;br /&gt;print_registered_expr ({ bin, _, PatternGrp }) -&gt;&lt;br /&gt;print_registered_pattern_group (PatternGrp);&lt;br /&gt;print_registered_expr ({ op, _, _, E }) -&gt;&lt;br /&gt;print_registered_expr (E);&lt;br /&gt;print_registered_expr ({ op, _, _, E0, E1 }) -&gt;&lt;br /&gt;print_registered_expr (E0),&lt;br /&gt;print_registered_expr (E1);&lt;br /&gt;print_registered_expr ({ remote, _, E0, E1 }) -&gt;&lt;br /&gt;print_registered_expr (E0),&lt;br /&gt;print_registered_expr (E1);&lt;br /&gt;print_registered_expr (_) -&gt;&lt;br /&gt;ok.&lt;br /&gt;&lt;br /&gt;print_registered_exprs (Exprs) -&gt;&lt;br /&gt;lists:foreach (fun (E) -&gt; print_registered_expr (E) end, Exprs).&lt;br /&gt;&lt;br /&gt;print_registered_clauses (Clauses) -&gt;&lt;br /&gt;lists:foreach (fun ({ clause, _, _, _, Exprs }) -&gt;&lt;br /&gt;                 print_registered_exprs (Exprs);&lt;br /&gt;                   (_) -&gt;&lt;br /&gt;                 ok&lt;br /&gt;               end,&lt;br /&gt;               Clauses).&lt;br /&gt;&lt;br /&gt;print_registered_forms (Forms) -&gt;&lt;br /&gt;lists:foreach (fun ({ function, _, _, _, Clauses }) -&gt;&lt;br /&gt;                 print_registered_clauses (Clauses);&lt;br /&gt;                   (_) -&gt;&lt;br /&gt;                 ok&lt;br /&gt;               end,&lt;br /&gt;               Forms).&lt;br /&gt;&lt;br /&gt;is_skipped ([]) -&gt; false;&lt;br /&gt;is_skipped ([ { attribute, _, fwskip, _ } | _ ]) -&gt; true;&lt;br /&gt;is_skipped ([ _ | Rest ]) -&gt; is_skipped (Rest).&lt;br /&gt;&lt;br /&gt;print_registered (Dir, F) -&gt;&lt;br /&gt;case compile:file (F, [ binary, 'E', { outdir, Dir } ]) of&lt;br /&gt;{ ok, _, { _, _, Forms } } -&gt;&lt;br /&gt;  case is_skipped (Forms) of&lt;br /&gt;    true -&gt;&lt;br /&gt;      ok;&lt;br /&gt;    false -&gt;&lt;br /&gt;      print_registered_forms (Forms)&lt;br /&gt;  end;&lt;br /&gt;_ -&gt;&lt;br /&gt;  ok&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;main ([ Dir | Rest ]) -&gt;&lt;br /&gt;ok = file:make_dir (Dir),&lt;br /&gt;&lt;br /&gt;try&lt;br /&gt;Three = open_port ({ fd, 0, 3 }, [ out ]),&lt;br /&gt;% ugh ... don't want to have to change all these function signatures,&lt;br /&gt;% so i'm gonna be dirty&lt;br /&gt;put (three, Three),&lt;br /&gt;lists:foreach (fun (F) -&gt; print_registered (Dir, F) end, Rest)&lt;br /&gt;after&lt;br /&gt;{ ok, FileNames } = file:list_dir (Dir),&lt;br /&gt;lists:foreach (fun (F) -&gt; file:delete (Dir ++ &quot;/&quot; ++ F) end, FileNames),&lt;br /&gt;file:del_dir (Dir)&lt;br /&gt;end;&lt;br /&gt;main ([]) -&gt;&lt;br /&gt;Port = open_port ({ fd, 0, 2 }, [ out ]),&lt;br /&gt;port_command (Port, &quot;usage: find-modules.esc tmpdir filename [filename ...]\n&quot;),&lt;br /&gt;halt (1).&lt;br /&gt;&lt;/pre&gt;It's definitely possible to fool the above code.  For instance:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Hidden = therealname,&lt;br /&gt;erlang:register (Hidden, SomePid).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;However in practice developers tend to use either explicitly name their registered process or at worst obscure them with a macro (which, by going through the Erlang compiler, we get expanded for free), so this automatic strategy has been working very well.&lt;br /&gt;&lt;br /&gt;You can download &lt;a href=&quot;http://code.google.com/p/fwtemplates/downloads/list&quot;&gt;fw-template-erlang&lt;/a&gt; from google code and get the complete source code from above plus some intuition about how it is called.  One thing that's been on our TODO list is to combine all these analysis into one pass on the source code; currently we pass through the source code three times, which is clearly suboptimal, although the process is speedy enough that it is only noticeable when analyzing larger projects (like, when we converted yaws and mnesia to fw-template-erlang for our internal use).</content:encoded>
	<dc:date>2008-06-15T13:46:46+00:00</dc:date>
	<dc:creator>Paul Mineiro</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-3729811.post-8789859386655022416">
	<title>Web 2.0 and beyond: Javascript syntax highligting for Firebug</title>
	<link>http://www.rsaccon.com/2008/06/javascript-syntax-highligting-for.html</link>
	<content:encoded>The syntax highligting capabilities of CodeMirror, my favorite Javascript based code editor (for Web IDE-type applications) found their way into Firebug, currently available as additional extension.</content:encoded>
	<dc:date>2008-06-14T14:41:35+00:00</dc:date>
	<dc:creator>Roberto Saccon</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-6265608756663924839.post-6651319658700771609">
	<title>Dukes of Erl: Erlang is so clear.</title>
	<link>http://dukesoferl.blogspot.com/2008/06/erlang-is-so-clear.html</link>
	<content:encoded>Ah the clearness of erlang.&lt;br /&gt;&lt;br /&gt;Someone on the yaws list gets errors and asks:&lt;br /&gt;&lt;blockquote&gt;Can any one please explain me what this error is about and how to&lt;br /&gt;overcome this one?&lt;/blockquote&gt;and gets the reply&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Well - it's fairly clear. It says:&lt;br /&gt;&lt;br /&gt;{undef,[{compile,file,&lt;br /&gt;               [&quot;/home/phanikar/.yaws/yaws/default/m1.erl&quot;,&lt;br /&gt;                [binary,return_errors, ...&lt;br /&gt;&lt;br /&gt;That means that when .yaws page has been transformed into an&lt;br /&gt;.erl page, the yaws server cannot compile the generated .erl file&lt;br /&gt;You need to have the erlang compiler in the load path&lt;/blockquote&gt;I'm going to assume the author was being sarcastic about that being clear,  I mean I get that it couldn't compile something.. but..  no hint of what reasons it couldn't compile.&lt;br /&gt;&lt;br /&gt;maybe  to quote the awesome tude of of the dynamic window manager guys:&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;a href=&quot;http://www.suckless.org/wiki/dwm/&quot;&gt;This keeps its userbase small and elitist. No novices asking stupid questions.&lt;/a&gt;&lt;/blockquote&gt;&lt;br /&gt;Well despite some of these problems erlang is super awesome.  It just needs a little more new blood to inject new attitudes of usability [ or some other language will evbentually just steal it's good ideas, which would be a shame.. we have them now.  ] Also new attitudes around  easier sharing of libraries. [  the &lt;a href=&quot;http://www.erlware.org/&quot;&gt;erlware guys&lt;/a&gt; get that. ].&lt;br /&gt;&lt;br /&gt;I'm pretty proud to see Uncle Jesse and the gang here trying to contribute improvements all the time.  Better mnesia on disk tables in the works,  yaws and erlang patches,  &lt;a href=&quot;http://code.google.com/p/erlrc/wiki/ErlrcHowto&quot;&gt;erlrc&lt;/a&gt;,  &lt;a href=&quot;http://code.google.com/p/fragmentron/&quot;&gt;automatic mnesia fragmentation mangment&lt;/a&gt; and loads more.  I mean we're building a big and real distributed mnesia backed system  so we're learning a lot, and we're certainly not the only ones contributing lately.   &lt;br /&gt;&lt;br /&gt;So, as a novice who asks stupid questions,  I'm telling the rest of you out there not to give up if you run into a few weird error messages or attitudes from language scholars who have been so entrenched they don't see what seems weird at first.  Despite those few small speed bumps, there is some really powerful awesome stuff going on here.  So, don't let em be elitist barge in there and get some erlang for yourself.&lt;br /&gt;&lt;br /&gt;P.S. Pattern matching rules!!!</content:encoded>
	<dc:date>2008-06-13T11:50:50+00:00</dc:date>
	<dc:creator>RoscoeOTPColtrain</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-855944390206940143.post-3589219738909897871">
	<title>EazyErl!: Quick Bash Script for Checking HTTP Headers</title>
	<link>http://easyerl.blogspot.com/2008/06/quick-bash-script-for-checking-http.html</link>
	<content:encoded>Whenever it comes to efficiently configure Web Servers and setting  headers like ETAg, Cache-Control, or Expires and you have more than one server, you need to check them all since any user may hit different servers.&lt;br /&gt;&lt;br /&gt;This script is meant to call wget on every IP returned by dig and display http response headers.    &lt;br /&gt;Usage is simple:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;./script.sh http://www.example.com/ressource/with-long-cache-and-no-etag/big-image.jpg&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here's the code:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;BIN=${0##*/}&lt;br /&gt;URL=${1?usage: $BIN url}&lt;br /&gt;HOST=${URL#http://*}&lt;br /&gt;REQ=${HOST#*/}&lt;br /&gt;HOST=${HOST%%/*}&lt;br /&gt;&lt;br /&gt;function check&lt;br /&gt;{&lt;br /&gt;	wget -S --header=&quot;Host: $HOST&quot; &quot;http://$line/$REQ&quot; -O/dev/null&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;dig +short $HOST | \&lt;br /&gt;while read line&lt;br /&gt;do&lt;br /&gt;	case $line in	&lt;br /&gt;		[a-z]*)&lt;br /&gt;		;;&lt;br /&gt;		[0-9]*.[0-9]*.[0-9]*)&lt;br /&gt;			echo === Testing $HOST with IP $line&lt;br /&gt;			check $line&lt;br /&gt;		;;&lt;br /&gt;		*)&lt;br /&gt;		;;&lt;br /&gt;	esac&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;</content:encoded>
	<dc:date>2008-06-13T11:09:07+00:00</dc:date>
	<dc:creator>rolphin</dc:creator>
</item>
<item rdf:about="http://steve.vinoski.net/blog/?p=73">
	<title>Trapexit's Erlang Blog Filter: Back from JAOO Au</title>
	<link>http://steve.vinoski.net/blog/2008/06/12/back-from-jaoo-au/</link>
	<content:encoded>&lt;p&gt;I recently returned from giving two talks at each of the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://jaoo.dk/&quot;&gt;Brisbane and Sydney JAOO conferences&lt;/a&gt;. JAOO has long been my favorite conference, and even though this was the first time JAOO was held in Australia, my understanding is that overall it was quite a success. There were a couple hundred attendees in each city, and I heard a number of attendees echo something along the lines of &amp;#8220;we really need developer conferences like this that aren&amp;#8217;t marketing and aren&amp;#8217;t academic.&amp;#8221; That&amp;#8217;s precisely why I like JAOO so much &amp;mdash; almost all of the JAOO speakers are practitioners themselves, so as a developer you get a lot of well-grounded useful info rather than product pitches or unproven research.&lt;/p&gt;
&lt;p&gt;My talks were &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://jaoo.com.au/brisbane-2008/presentation/Building+RESTful+Services+with+Erlang+and+Yaws&quot;&gt;&amp;#8220;Building RESTful Services with Erlang and Yaws&amp;#8221;&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://jaoo.com.au/sydney-2008/presentation/Multi-language+Programming&quot;&gt;&amp;#8220;Multilanguage Programming.&amp;#8221;&lt;/a&gt; For first-time talks both went OK, but they could have been better. The biggest problem with both was that I already had too many slides for each one for an hour but when I got there I learned that a scheduling mix-up had reduced the presentation time slots to only 45 minutes, which then meant I had &lt;em&gt;way&lt;/em&gt; too many slides for each talk. The first talk tries to cover a lot of ground, for example, and it&amp;#8217;s hard to remove any of it and still have it make sense. Oh well. I warned the attendees up front about the problem, and since I got reasonable reviews for both talks I hope that means I left the attendees with some useful info.&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s talk in the blogosphere of a strong revival in interest in programming languages, and I&amp;#8217;d have to say there&amp;#8217;s definitely something to that notion because I didn&amp;#8217;t expect so many would be interested in the multilanguage programming talk. I guess I expected to encounter some defensive dyed-in-the-wool &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://steve-yegge.blogspot.com/2007/12/codes-worst-enemy.html&quot;&gt;&amp;#8220;X&amp;#8221; programmers, where &amp;#8220;X&amp;#8221; often seems to be Java&lt;/a&gt;, who would just argue that multilanguage programming is a bad idea, but there were none. Instead I was encouraged by the number of developers who came to the talk and seemed truly interested in the idea of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://computer.org/portal/pages/dsonline/2008/06/w3tow.xml&quot;&gt;learning and using multiple languages&lt;/a&gt; in order to do their jobs in the best possible way.&lt;/p&gt;
&lt;p&gt;Anyway, I strongly recommend that you go to &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://jaoo.dk/conference/&quot;&gt;JAOO Aarhus&lt;/a&gt; if you can.&lt;/p&gt;
&lt;p&gt;Next up: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang-exchange.com/&quot;&gt;Erlang eXchange&lt;/a&gt; in London, which I also strongly recommend. Overall it looks like a &lt;em&gt;very&lt;/em&gt; strong program, and I&amp;#8217;m really looking forward not only to giving my &amp;#8220;Enterprise Integration&amp;#8221; keynote there, but better yet getting to meet more folks in the Erlang community in person. I hope I&amp;#8217;ll see you there.&lt;/p&gt;</content:encoded>
	<dc:date>2008-06-12T05:16:55+00:00</dc:date>
</item>
<item rdf:about="http://ulf.wiger.net/weblog/?p=25">
	<title>Ulf Wiger: Indentation-sensitive Erlang 3</title>
	<link>http://ulf.wiger.net/weblog/2008/06/11/indentation-sensitive-erlang-3/</link>
	<content:encoded>&lt;p&gt;So, maybe I&amp;#8217;m thick enough not to realise in advance when I&amp;#8217;m barking up the wrong tree, or perhaps I just like to follow things through to the bitter end, just to know what exactly didn&amp;#8217;t work&amp;#8230;?&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve gone one more round with my indentation-sensitive Erlang scanner/parser. For a while, it looked like I was winning, but eventually, I had to admit defeat in the face of funs and record constructors.&lt;/p&gt;
&lt;p&gt;Again, the approach I thought I&amp;#8217;d take was to add indentation tokens to the normal scanner, and then add rule clauses to the normal grammar to make it understand both indentation-sensitive code, and all the code you&amp;#8217;re accustomed to writing. The normal parser is an LR(1) grammar, which means that the additions have to be quite symmetrical in order to work.&lt;/p&gt;
&lt;p&gt;This seemed to work in just about all the places that mattered, but I was stumped by funs and record constructors. The main with funs was that you could no longer write them in the conventional way (failing one of my preconditions), and record constructors usually cannot be written without including a few commans in a way that was &amp;#8230;uhm, less than obvious.&lt;/p&gt;
&lt;p&gt;I include the test module, which pretty much illustrates what works, and what doesn&amp;#8217;t. At this point, I doubt that I can achieve better than a 90% solution, which is probably just good enough to eventually drive people crazy.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s been fun, though. I&amp;#8217;m have no particular craving for indentation-sensitive syntax myself, so I thought I&amp;#8217;d tackle this as a learning experience. Not for the first time, I feel like concluding that retrofitting concepts onto existing programming languages is usually very difficult to do well.&lt;/p&gt;
&lt;p&gt;The code is at &lt;a href=&quot;http://svn.ulf.wiger.net/indent/branches/0.3&quot;&gt;http://svn.ulf.wiger.net/indent/branches/0.3&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
&lt;code&gt;
&lt;pre&gt;
-module(test).

-record(r,{a,b}).

-compile(export_all).
-scan(indentation).

f(X) -&amp;gt;
    X+2

g(X) -&amp;gt;
    X+4
.          % dot can either be 'outdented' or
           % terminating last line

g1(X) -&amp;gt;
    X+4.

h(X) -&amp;gt;
    Y = case X of
          a -&amp;gt;
            {a}
          b -&amp;gt;
            {b}
    end          % end is optional
    Y

h1(X) -&amp;gt;
    Y = case X of
          a -&amp;gt;
            {a}
          b -&amp;gt;
            {b}
    Y

h2(X) -&amp;gt;
    case X of
        a -&amp;gt;
            1
        b -&amp;gt;
            2

h3(X) -&amp;gt;
    case X of
        a -&amp;gt; 1;  % must use semicolon here &lt;img src=&quot;http://ulf.wiger.net/weblog/wp-includes/images/smilies/icon_sad.gif&quot; alt=&quot;:-(&quot; class=&quot;wp-smiley&quot; /&gt;
        b -&amp;gt; 2

i(a) -&amp;gt; a
i(b) -&amp;gt; b

j(A,B) -&amp;gt;
    {A
    B}

j1(A,B,C) -&amp;gt;
    {A
     B     % indents must be greater than 1;
     C}    % else they count as aligned

k() -&amp;gt;
    S = &quot;a string &quot;
        &quot;spanning multiple &quot;
        &quot;lines&quot;
    {S}

l0() -&amp;gt;
    fun(1) -&amp;gt; 1; (2) -&amp;gt; 2 end.

l1() -&amp;gt;
    fun            % must break line here and indent.  &lt;img src=&quot;http://ulf.wiger.net/weblog/wp-includes/images/smilies/icon_sad.gif&quot; alt=&quot;:-(&quot; class=&quot;wp-smiley&quot; /&gt;
      (1) -&amp;gt;
            1
      (2) -&amp;gt;
            2

%%% This, alas, doesn't work &lt;img src=&quot;http://ulf.wiger.net/weblog/wp-includes/images/smilies/icon_sad.gif&quot; alt=&quot;:-(&quot; class=&quot;wp-smiley&quot; /&gt;
%%%
%%% l2() -&amp;gt;
%%%     fun(1) -&amp;gt;
%%%             1;
%%%        (2) -&amp;gt;
%%%             2
%%%     end

m() -&amp;gt;
    #r{a = 1, b = 2}.

m1() -&amp;gt;
    R = #r{a = 1}
    R#r.a

%%% indentation syntax works poorly for record assignment.
%%% Both commas are needed &lt;img src=&quot;http://ulf.wiger.net/weblog/wp-includes/images/smilies/icon_sad.gif&quot; alt=&quot;:-(&quot; class=&quot;wp-smiley&quot; /&gt;
m2() -&amp;gt;
    R = #r{a = 1,
           b = 2},
    R

test() -&amp;gt;
    2 = f(0),
    4 = f(2),
    4 = g(0),
    4 = g1(0),
    8 = g(4),
    {a} = h(a),
    {b} = h(b),
    {a} = h1(a),
    {b} = h1(b),
    1 = h2(a),
    2 = h2(b),
    1 = h3(a),
    2 = h3(b),
    a = i(a),
    b = i(b),
    {a,b} = j(a,b),
    {a,b,c} = j1(a,b,c),
    {&quot;a string spanning multiple lines&quot;} = k(),
    F0 = l0(), 1 = F0(1), 2 = F0(2),
    F1 = l1(), 1 = F1(1), 2 = F1(2),
    {r,1,2} = m(),
    1 = m1(),
    ok.
&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/code&gt;
&lt;/p&gt;&lt;/blockquote&gt;</content:encoded>
	<dc:date>2008-06-11T14:13:12+00:00</dc:date>
</item>
<item rdf:about="tag:blogger.com,1999:blog-6265608756663924839.post-7076198302203910448">
	<title>Dukes of Erl: I'm in ur Erlangz, upgrading ur applicationz</title>
	<link>http://dukesoferl.blogspot.com/2008/06/im-in-ur-erlangz-upgrading-ur.html</link>
	<content:encoded>Hot code loading is one of the sexiest features of Erlang; after all, who wants downtime?  If you're running mnesia, it's also very convenient, because as we've learned mnesia does not like to be shut down (more precisely, it makes no attempt to incrementally replicate changes across brief outages, instead doing full table (re)copying; something probably nobody cares about because they never turn it off).&lt;br /&gt;&lt;br /&gt;Erlang's hot code loading support consists of low level language and runtime features, and a high level strategy embodied by release handler.  The latter is a very Java-esque strategy of bundling up the complete new state of the system and upgrading  everything.  Without being normative let's just say that we enjoy using our OS package manager to manage the software on our boxes, and so we were interested in integrating Erlang hot code loading with the OS package manager.&lt;br /&gt;&lt;br /&gt;The result is &lt;a href=&quot;http://code.google.com/p/erlrc&quot;&gt;erlrc&lt;/a&gt;, which when operating looks something like this:&lt;br /&gt;&lt;pre&gt;pmineiro@ub32srvvmw-199% sudo apt-get install egerl&lt;br /&gt;Reading package lists... Done&lt;br /&gt;Building dependency tree    &lt;br /&gt;Reading state information... Done&lt;br /&gt;The following packages will be upgraded:&lt;br /&gt;egerl&lt;br /&gt;1 upgraded, 0 newly installed, 0 to remove and 34 not upgraded.&lt;br /&gt;Need to get 0B/113kB of archives.&lt;br /&gt;After unpacking 0B of additional disk space will be used.&lt;br /&gt;WARNING: The following packages cannot be authenticated!  egerl&lt;br /&gt;Install these packages without verification [y/N]? y&lt;br /&gt;(Reading database ... 48221 files and directories currently installed.)&lt;br /&gt;Preparing to replace egerl 4.0.1 (using .../archives/egerl_4.1.0_all.deb) ...&lt;br /&gt;Unpacking replacement egerl ...&lt;br /&gt;erlrc-upgrade: Upgrading 'egerl': (cb8eec1a1b85ec017517d3e51c5aee7b) upgraded&lt;br /&gt;Setting up egerl (4.1.0) ...&lt;br /&gt;erlrc-start: Starting 'egerl': (cb8eec1a1b85ec017517d3e51c5aee7b) already_running&lt;br /&gt;&lt;/pre&gt;Basically, I issued an apt command, the result was to hot upgrade the corresponding Erlang application on the running Erlang node on the machine.&lt;br /&gt;&lt;br /&gt;In addition to integration with the OS package manager, erlrc also features an extensible boot procedure (basically, using a boot directory instead of a boot file to determine what to start, which makes packaging easier); and in addition erlrc will automatically generate appup files which correspond to most of the common cases outlined in the &lt;a href=&quot;http://www.erlang.org/doc/design_principles/appup_cookbook.html&quot;&gt;appup cookbook&lt;/a&gt;.  Of course, Erlang packages made with &lt;a href=&quot;http://code.google.com/p/fwtemplates/wiki/FwTemplateErlangWalkthrough&quot;&gt;fw-template-erlang&lt;/a&gt; are automatically instrumented for erlrc (but the instrumentation is inert if erlrc is not installed).&lt;br /&gt;&lt;br /&gt;If you're interested, there's &lt;a href=&quot;http://code.google.com/p/erlrc/wiki/ErlrcHowto&quot;&gt;more extensive documentation&lt;/a&gt; on google code.</content:encoded>
	<dc:date>2008-06-11T12:37:08+00:00</dc:date>
	<dc:creator>Paul Mineiro</dc:creator>
</item>
<item rdf:about="http://blogtrader.net/page/dcaoyuan/entry/parsing_performance_of_scala_for">
	<title>Caoyuan's Blog: Parsing Performance of Scala for NetBeans</title>
	<link>http://blogtrader.net/page/dcaoyuan/entry/parsing_performance_of_scala_for</link>
	<content:encoded>&lt;p&gt;I'm re-considering the indexing mechanism of Scala for NetBeans. The indexing is used to store meta-info of parsed templates/methods etc, for auto-completion and document/source offsets searching. Currently, the parsing phases include lexer, syntax and semantic analysis, not include type inference and type check. 

&lt;p&gt;With a basic performance testing on all Scala standard library and liftweb's library, the maxima parsing time seems less than 1s, the average parsing time is around 0.2s, not bad.

&lt;p&gt;So, this may let the indexing feature a lot simple, I can store classes/objects/traits' meta-info only, instead of including their type parameters and their members (fields/methods, scoped importing etc), these additional information can be got via re-parsing the source file or querying the class file.&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</content:encoded>
	<dc:date>2008-06-11T03:30:33+00:00</dc:date>
</item>
<item rdf:about="tag:blogger.com,1999:blog-1893218858608219953.post-2042706619324991488">
	<title>Philip Robinson: &quot;Dynamic&quot; module generation with compile-time macros</title>
	<link>http://chlorophil.blogspot.com/2008/06/dynamic-module-generation-with-compile.html</link>
	<content:encoded>&lt;a href=&quot;http://bp0.blogger.com/_6zQp6LtHMTo/SE6ApnDOyKI/AAAAAAAAAD8/YyLZ_gO9N3k/s1600-h/kelphorse.PNG&quot;&gt;&lt;img src=&quot;http://bp0.blogger.com/_6zQp6LtHMTo/SE6ApnDOyKI/AAAAAAAAAD8/YyLZ_gO9N3k/s320/kelphorse.PNG&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5210243271259768994&quot; /&gt;&lt;/a&gt;&lt;br /&gt;Over on the Erlang Questions mailing list, Jacob Perkins asked:&lt;br /&gt;&lt;br /&gt;&quot;I have a few files that are basically lists of words. What I want to do is generate a module whose functions will return each list of words. So if I have two files named &quot;adjectives&quot; and &quot;nouns&quot;, then the generated module (let's call it 'grammar') should have two functions, adjectives() and nouns(), that return their respective list of words.&lt;br /&gt;&lt;br /&gt;How can I do this?&quot;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If I had some method of running Erlang code at compile-time - and I do - then I could write a program to slurp in those adjective and noun files and generate the appropriate functions.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;adjectives.txt:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;this&lt;br /&gt;that&lt;br /&gt;these&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;nouns.txt:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;apple&lt;br /&gt;banana&lt;br /&gt;carrot&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;grammar.erl:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;-module(grammar).&lt;br /&gt;-export([nouns/0, adjectives/0]).&lt;br /&gt;-compile({parse_transform, emp2}).&lt;br /&gt;&lt;br /&gt;-macro({grammar_macro, generate, [nouns]}).&lt;br /&gt;-macro({grammar_macro, generate, [adjectives]}).&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;grammar_macro.erl:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;-module(grammar_macro).&lt;br /&gt;-export([generate/1]).&lt;br /&gt;&lt;br /&gt;generate(NameFun) -&gt;&lt;br /&gt;    {ok,Fd} = file:open(atom_to_list(NameFun) ++ &quot;.txt&quot;, [read]),&lt;br /&gt;    generate(Fd, NameFun, []).&lt;br /&gt;&lt;br /&gt;generate(Fd, NameFun, Words) -&gt;&lt;br /&gt;    case io:get_line(Fd, &quot;&quot;) of&lt;br /&gt;        eof -&gt;&lt;br /&gt;            ok=file:close(Fd),&lt;br /&gt;            io_lib:format(&quot;~w() -&gt; ~w.~n&quot;, [NameFun, lists:reverse(Words)]);&lt;br /&gt;        Word -&gt; generate(Fd, NameFun, [Word | Words])&lt;br /&gt;        end.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And in the Erlang shell:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;1&gt; c(grammar_macro), c(grammar).&lt;br /&gt;{ok,grammar}&lt;br /&gt;2&gt; grammar:nouns().&lt;br /&gt;[&quot;apple\n&quot;,&quot;banana\n&quot;,&quot;carrot\n&quot;]&lt;br /&gt;3&gt; grammar:adjectives().&lt;br /&gt;[&quot;this\n&quot;,&quot;that\n&quot;,&quot;these\n&quot;]&lt;/pre&gt;</content:encoded>
	<dc:date>2008-06-11T00:26:06+00:00</dc:date>
	<dc:creator>Philip Robinson</dc:creator>
</item>
<item rdf:about="http://prog21.dadgum.com/29.html">
	<title>Programming in the 21st Century: A Spellchecker Used to Be a Major Feat of Software Engineering</title>
	<link>http://prog21.dadgum.com/29.html</link>
	<content:encoded>Here's the situation: it's 1984, and you're assigned to write the spellchecker for a new MS-DOS word processor.  Some users, but not many, will have 640K of memory in their PCs.  You need to support systems with as little as 256K.  That a quarter megabyte to contain the word processor, the document being edited, and the memory needed by the operating system.  Oh, and the spellchecker.
&lt;br /&gt;&lt;br /&gt;For reference, on my MacBook, the standard dictionary in /usr/share/dict/words is 2,486,813 bytes and contains 234,936 words.
&lt;br /&gt;&lt;br /&gt;An enticing first option is a data format that's more compressed than raw text.  The UNIX dictionary contains &lt;i&gt;stop&lt;/i&gt; and &lt;i&gt;stopped&lt;/i&gt; and &lt;i&gt;stopping&lt;/i&gt;, so there's a lot of repetition.  A clever trie implementation might do the trick...but we'll need a big decrease to go from 2+ megabytes to a hundred K or so.
&lt;br /&gt;&lt;br /&gt;In fact, even if we could represent each word in the spellchecker dictionary as a single byte, we need almost all the full 256K just for that, and of course the single byte representation isn't going to work.  So not only does keeping the whole dictionary in RAM look hopeless, but so does keeping the actual dictionary on disk with only an index in RAM.
&lt;br /&gt;&lt;br /&gt;Now it gets messy.  We could try taking a subset of the dictionary, one containing the most common words, and heavily compressing that so it fits in memory.  Then we come up with a slower, disk-based mechanism for looking up the rest of the words.  Or maybe we jump directly to a completely disk-based solution using a custom database of sorts (remembering, too, that we can't assume the user has a hard disk, so the dictionary still needs to be crunched onto a 360K floppy disk).
&lt;br /&gt;&lt;br /&gt;On top of this, we need to handle some other features, such as the user adding new words to the dictionary.
&lt;br /&gt;&lt;br /&gt;Writing a spellchecker in the mid-1980s was a hard problem.  Programmers came up with some impressive data compression methods in response to the spellchecker challenge.  Likewise there were some very clever data structures for quickly finding words in a compressed dictionary.  This was a problem that could take months of focused effort to work out a solution to.  (And, for the record, reducing the size of the dictionary from 200,000+ to 50,000 or even 20,000 words was a reasonable option, but even that doesn't leave the door open for a naive approach.)
&lt;br /&gt;&lt;br /&gt;Fast forward to today.  A program to load /usr/share/dict/words into a hash table is 3-5 lines of Perl or Python, depending on how terse you mind being.  Looking up a word in this hash table dictionary is a trivial expression, one built into the language.  &lt;i&gt;And that's it.&lt;/i&gt;  Sure, you could come up with some ways to decrease the load time or reduce the memory footprint, but that's icing and likely won't be needed.  The basic implementation is so mindlessly trivial that it could be an exercise for the reader in an early chapter of any Python tutorial.
&lt;br /&gt;&lt;br /&gt;That's progress.</content:encoded>
	<dc:date>2008-06-08T06:00:00+00:00</dc:date>
	<dc:creator>James Hague</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-3729811.post-8715084766226292593">
	<title>Web 2.0 and beyond: Google App Engine limitations and workarounds</title>
	<link>http://www.rsaccon.com/2008/06/google-app-engine-limitations-and.html</link>
	<content:encoded>One of the current limitations of the Google App Engine is the lack of scheduled background processes. But early adapters are creative to circumnavigate this and other limitations.  The most  simple solution to this problem has William Vambenepe: he uses Google Reader to subscribe to a dummy RSS feed on his App Engine hosted test app, that results in some kind of regular polling with an interval</content:encoded>
	<dc:date>2008-06-06T13:11:28+00:00</dc:date>
	<dc:creator>Roberto Saccon</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-3729811.post-7994656310753990125">
	<title>Web 2.0 and beyond: The missing feature of the Web: a DNS REST API</title>
	<link>http://www.rsaccon.com/2008/04/missing-feature-of-web-dns-rest-api.html</link>
	<content:encoded>I have been waiting for years, that a quality DNS provider will a offer a REST API for setting DNS Records, but there is still no such a thing on the market. There is a SOAP based offering from Nettica (unfortunately I have an SOAP allergy). And there are the REST APIs some service providers are exposing for updating dynamic IPs.
DNS Made Easy, one of my preferred DNS providers, told me about a</content:encoded>
	<dc:date>2008-06-05T21:04:41+00:00</dc:date>
	<dc:creator>Roberto Saccon</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-7012030999962875668.post-2937248757794621509">
	<title>Eric Merritt: An Introduction to Erlang</title>
	<link>http://erlangish.blogspot.com/2008/05/introduction-to-erlang.html</link>
	<content:encoded>As some of you may have guessed, I am a fan of Erlang. I think that it's a very interesting language with a tremendous amount of promise for the type of server side applications that I usually end up working on. I have talked a lot about various things here on Erlangish, so I thought it would finally be appropriate to spend a bit of time talking about the topic of the blog. For the most part I will be delving into the, somewhat obscure, history of Erlang. I will also spend a bit of time providing some instructions on how to get started with the language.&lt;br /&gt;
&lt;br /&gt;
&lt;span&gt;So What Is Erlang and OTP?&lt;br /&gt;
&lt;br /&gt;
&lt;/span&gt;Erlang is a distributed, concurrent, soft real time functional programming language and runtime environment developed by Ericsson, the Telecoms Infrastructure supplier. It has built-in support for concurrency, distribution and fault tolerance. Since its open source release in 1999, Erlang has been adopted by many leading telecom and IT related companies. It is now successfully being used in other sectors including banking, finance, ecommerce and computer telephony.&lt;br /&gt;
&lt;br /&gt;
OTP is a large collection of libraries for Erlang to do everything from compiling ASN.1 to providing an application embeddable http server. It also consists of implementations of several patterns that have proven useful in massively concurrent development over the years. Most production Erlang applications are actually Erlang/OTP applications. OTP is also open source and distributed with Erlang.&lt;br /&gt;
&lt;br /&gt;
Although Erlang is a general purpose language, it has tried to fill a certain niche. This niche mostly consists of distributed, reliable, soft real-time concurrent systems. These types of applications are telecommunication systems, Servers and Database applications which require soft real-time behavior. Erlang excels at these types of systems because these are the types of systems that it was originally designed around. It contains a number of features that make it particularly useful in this arena. For example; it provides a simple and powerful model for error containment and fault tolerance; concurrency and message passing are a fundamental to the language, applications written in Erlang are often composed of hundreds or thousands of lightweight processes; Context switching between Erlang processes is typically several orders of magnitude cheaper than switching between threads in other languages; it's distribution mechanisms are transparent, programs need not be aware that they are distributed and The runtime system allows code in a running system to be updated without interrupting the program.&lt;br /&gt;
&lt;br /&gt;
Given that there are things that Erlang is good at there are bound to be a few things that it's not so good at. The most common class of 'less suitable' problems is characterized by iterative performance being a prime requirement with constant-factors having a large effect on performance. Typical examples are image processing, signal processing and sorting large volumes of data.&lt;br /&gt;
&lt;br /&gt;
&lt;span&gt;Origins of Erlang&lt;br /&gt;
&lt;br /&gt;
&lt;/span&gt;I am firmly convinced that Erlang's history is a key ingredient to its success. I am not aware of any other language whose early development was so straightforward and pragmatic. For most of its life Erlang was developed inside Ericsson, originally for internal use only. Later on it was made available to the external world and eventually open sourced. The timeline of its development goes something like this.&lt;br /&gt;
&lt;br /&gt;
  1982–1985 Ericsson identified some issues that existed with telecom languages at the time. To address these difficulties they started experiments with the programming of telecom applications using more then twenty different languages. These early experimenters came up with a few features that a useful system needed to supply. They realized that the target language must be a very high level symbolic language in order to achieve productivity gains. This new requirement vastly subseted the language space and resulted in a very short list of languages. The languages included Lisp, Prolog, Parlog, etc.&lt;br /&gt;
&lt;br /&gt;
 1985–1986 Further experiments within this subseted list where performed. New results were generated from this round of experiments as well. They found that the theoretically ideal language also needed to contain primitives for concurrency and error recovery, and the execution model needed to exclude back-tracking. This ruled out two more of the contending languages, Lisp and Prolog. This ideal language also needed to have a granularity of concurrency such that there would be a one to one relationship between one asynchronous telephony process and one process in the language. This ruled out Parlog. At the end of this round of experiments they where left with out any languages in the list they had started with. Being the pragmatic folks that they were, they decided to develop their own language with the desirable features of Lisp, Prolog and Parlog, but with superior concurrency and error recovery built into the language.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;    1987 The first experiments began with this nascent language which became Erlang.&lt;/li&gt;&lt;li&gt;1988 The ACS/Dunder project was started at Ericsson. This was a prototype implementation of PABX by developers external to the core Erlang developers.&lt;/li&gt;&lt;li&gt;1989 The ACS/Dunder project became a full fledged project with the reconstruction of about a tenth of the complete, production PABX called the MD-110 system. The preliminary results where very promising. In this early phase developer productivity was already ten times greater then during the development of the original system in the PLEX language. This reimplementation also pushed forward experiments directed at increasing the speed of Erlang.&lt;/li&gt;&lt;li&gt;    1991 At this point the experiments directed at speeding up Erlang bore fruit. A fast implementation of Erlang was released to growing user community. Erlang was also presented at an international telecom conference that year.&lt;/li&gt;&lt;li&gt;    1992 During this year the user base started growing significantly. Erlang was ported to VxWorks, PC, Macintosh and other platforms. Three new, complete applications were written in Erlang where presented at another conference. The first two production projects using Erlang are started.&lt;/li&gt;&lt;li&gt;    1993 Distribution primitives where added to the language, which made it possible to run a homogeneous Erlang system on heterogeneous hardware. A corporate decision was made within Ericsson to begin selling and supporting Erlang externally. A new organizational structure was built up to maintain and support Erlang implementations and Erlan