<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3408400997537705779</id><updated>2011-12-17T18:46:23.011-08:00</updated><category term='tsung'/><category term='wxErlang'/><category term='erjang'/><category term='Hot Code Swap'/><category term='parallel computing'/><category term='quicksort'/><category term='Primes'/><category term='delayed evaluation'/><category term='Sieve of Eratosthenes'/><category term='Java'/><category term='jvm'/><category term='soak testing'/><category term='EJB'/><category term='Algorithm'/><category term='BubbleSort'/><category term='Factorial'/><category term='Java Thread'/><category term='GS'/><category term='Parallel'/><category term='performance testing'/><category term='Insertion Sort'/><category term='load testing'/><category term='Tcl/Tk'/><category term='Concurrent'/><category term='lazy evaluation'/><category term='Fibonacci'/><category term='Erlang'/><title type='text'>Erlang - Concurrency Software</title><subtitle type='html'>Its a programming language designed for multi-threaded and parallel programs</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>18</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-887837125143524460</id><published>2010-07-05T17:56:00.000-07:00</published><updated>2010-07-06T04:13:39.823-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='erjang'/><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><category scheme='http://www.blogger.com/atom/ns#' term='jvm'/><title type='text'>Erjang - No, its not a typo and its Erlang-on-JVM</title><content type='html'>There's a new Erlang language in town built on-top of the JVM. Its Erjang. I seem to experience a explosion of hosts of languages built on-top of the Java Virtual Machine from Scala (my current favourite), Clojure (Lisp clone), Jython (Python clone), Groovy and JRuby to name a few; for a developer like myself, i do find myself suddenly swamped with a huge list of flavours in which to train myself in. Enough about me.&lt;br /&gt;&lt;br /&gt;So Erjang is a runtime which basically loads the Erlang's BEAM file into the JVM and creates Java classes and its instances. Check out the project's homepage &lt;a href="http://wiki.github.com/krestenkrab/erjang/"&gt;here&lt;/a&gt;. Like all languages, it'll need time to be adopted and adopted. Personally, i'll stick to Erlang since it fulfills most of my use cases from bit-hacking (which i absolutely adore) to general purpose computing and i'll love to listen to the use cases in which the author built Erjang. There's always something to be learned.&lt;br /&gt;&lt;br /&gt;And i found it! Here's the rationale from the Creator which is ossm (check out the &lt;a href="http://vimeo.com/12680475"&gt;video&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt; Over the last few years, I have been meeting "Erlang people" more and  more often, and I was getting this clear impression that "you people"  have some kind of magic ability to reason intuitively about concurrent  systems in a way that I could not.  That bothered me, so I wanted to  learn Erlang.  Being a language implementor, the most obvious way to do  that is to just go ahead and implement an Erlang VM, right?   &lt;br /&gt;&lt;br /&gt;The result of this "little exercise" is Erjang, an open-source JVM-based  Erlang VM, which I think has potential to be useful as a means to push  Erlang into new areas of application, help grow the Erlang community,  and most importantly make all those Java-heads out there willing to  learn how to do concurrency right. In this "brave new world" of  networked services and multi-core everywhere, there are a lot of people  who are challenged in providing even basic reliability, efficiency and  correctness.  My hope is that Erjang's existence can influence some of  those outside the Erlang community to do better.&lt;br /&gt;&lt;br /&gt;In technical terms, Erjang reads .beam files and compiles them to Java's  equivalent .class files which are then read into the running JVM.  It  runs off a plain Erlang/OTP distribution - it only requires the beam  files from there; Erjang itself is written in Java.  As off this  writing, it can run some non-trivial erlang programs, but is not yet  capable of booting OTP [will have to update this abstract as we go along  - follow updates on my blog].  Comparing the BEAM virtual machine and  Erjang, the most obvious differences are that (a) Erjang will not be  able to provide [soft] real-time guarantees since it uses Java's garbage  collector, and (b) it has limited support for native code and port  drivers (other than file and network I/O).  The upside is the new ways  this allows us to deploy Erlang systems.&lt;br /&gt;&lt;br /&gt;In this presentation I will talk about how Erjang works, what behavior  to expect from Erlang programs running on top of Erjang, what I learned  along the way, and demonstrate [live] that Erjang runs well enough to be  obviously useful.       &lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-887837125143524460?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/887837125143524460/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=887837125143524460&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/887837125143524460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/887837125143524460'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2010/07/erjang-no-its-not-typo-and-its-erlang.html' title='Erjang - No, its not a typo and its Erlang-on-JVM'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-7912841482920223347</id><published>2009-11-02T00:05:00.000-08:00</published><updated>2010-07-12T00:02:15.798-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='soak testing'/><category scheme='http://www.blogger.com/atom/ns#' term='load testing'/><category scheme='http://www.blogger.com/atom/ns#' term='tsung'/><category scheme='http://www.blogger.com/atom/ns#' term='performance testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><title type='text'>Tsung - Load Testing Tool in Erlang</title><content type='html'>You've must have heard of Tsung - a load testing tool. Well i've got the opportunity to learn and use it in my current employment and its really versatile in conducting load tests for web-based applications. It has many features that i've come to appreciate after spending a couple of years with Mercury Interactive (its defunct now after being bought over by HP in 2006); admittedly Mercury's solutions were more versatile than what Tsung can offer but considering that web is the common platform where many applications are being hosted on; i think its a safe bet :)&lt;br /&gt;&lt;br /&gt;So, IMO i think&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Tsung is good for conducting load testing scenarios and executing them in a local / distributed manner&lt;/li&gt;&lt;li&gt;Load Testing can be relatively light weight (Erlang processes are hitting the target app) and hence the cost of using relatively heavy weight machines is likely to reduce since there is lesser need to use those machines since more concurrent users can be simulated on 1 machine in Tsung. (I'll see whether this assumption is correct)&lt;/li&gt;&lt;/ol&gt;Good starting points (URLs of interest):&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span class="nobr"&gt;&lt;a href="http://tsung.erlang-projects.org/"&gt;http://tsung.erlang-projects.org/&lt;sup&gt;&lt;/sup&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="nobr"&gt;&lt;a href="http://www.erlang.org/"&gt;http://www.erlang.org&lt;sup&gt;&lt;/sup&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;A load testing tool would be useless if it didn't know how to capture server response data (e.g. checking whether an expected string is returned) and reuse it (e.g. session ids returned from servers which you can use subsequently in a HTTP POST/GET in an URL-rewrite type of string) subsequently, generate dynamic data, read data from an external file (commonly used in storing &amp;lt;&lt;i&gt;username&lt;/i&gt;, &lt;i&gt;password&lt;/i&gt;&amp;gt; pairs)   &lt;br /&gt;So my example would illustrate the logging in to a website (e.g. &lt;span class="nobr"&gt;&lt;a href="http://projecteuler.net/"&gt;http://projecteuler.net&lt;sup&gt;&lt;/sup&gt;&lt;/a&gt;&lt;/span&gt;) and logging out from it - simple enough to illustrate my point.&lt;br /&gt;Next what i did was to record the series of events that mimick my user logging and logging out of the website and this is captured in the tsung_recorder_timestamp.xml&lt;br /&gt;and i used that XML file and included some other stuff so that it looks like what i have for you below (this is a basic load test scenario)&lt;br /&gt;&lt;pre&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE tsung SYSTEM "/usr/local/share/tsung/tsung-1.0.dtd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;tsung loglevel="info" dumptraffic="false" version="1.0"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;clients&amp;gt;&lt;br /&gt;&amp;lt;client host="localhost" use_controller_vm="true"/&amp;gt;&lt;br /&gt;&amp;lt;/clients&amp;gt;&lt;br /&gt;&amp;lt;servers&amp;gt;&lt;br /&gt;&amp;lt;server host="78.110.165.8" port="80" type="tcp"&amp;gt;&amp;lt;/server&amp;gt;&lt;br /&gt;&amp;lt;/servers&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;load&amp;gt;&lt;br /&gt;&amp;lt;arrivalphase phase="1" duration="2" unit="minute"&amp;gt;&lt;br /&gt;&amp;lt;users interarrival="1" unit="minute"&amp;gt;&amp;lt;/users&amp;gt;&lt;br /&gt;&amp;lt;/arrivalphase&amp;gt;&lt;br /&gt;&amp;lt;user session="rec20091102-01:30" start_time="0" unit="second"&amp;gt;&amp;lt;/user&amp;gt;&lt;br /&gt;&amp;lt;/load&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;options&amp;gt;&lt;br /&gt;&amp;lt;option name="file_server" value="/tmp/userlist.csv"&amp;gt;&amp;lt;/option&amp;gt;&lt;br /&gt;&amp;lt;/options&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;sessions&amp;gt;&lt;br /&gt;&amp;lt;session name='rec20091102-01:30' probability='100'  type='ts_http'&amp;gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='http://projecteuler.net/' version='1.1' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='/style_main.css' version='1.1' if_modified_since='Sat, 29 Nov 2008 20:04:00 GMT' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='/images/logo.jpg' version='1.1' if_modified_since='Thu, 28 Dec 2006 14:12:43 GMT' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='/images/icon_register.png' version='1.1' if_modified_since='Fri, 31 Dec 2004 12:48:16 GMT' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='/images/icon_about.png' version='1.1' if_modified_since='Fri, 31 Dec 2004 12:48:28 GMT' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='/images/icon_problems.png' version='1.1' if_modified_since='Fri, 31 Dec 2004 12:48:26 GMT' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='/images/icon_login.png' version='1.1' if_modified_since='Fri, 31 Dec 2004 12:48:32 GMT' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='http://projecteuler.net/images/corner_tr.gif' version='1.1' if_modified_since='Thu, 10 Apr 2008 19:35:02 GMT' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='/images/corner_tl.gif' version='1.1' if_modified_since='Thu, 10 Apr 2008 19:34:41 GMT' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='/images/corner_br.gif' version='1.1' if_modified_since='Thu, 10 Apr 2008 19:35:10 GMT' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='/images/corner_bl.gif' version='1.1' if_modified_since='Thu, 10 Apr 2008 19:34:55 GMT' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='/images/euler_main.jpg' version='1.1' if_modified_since='Mon, 21 Jan 2002 19:18:20 GMT' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;thinktime random='true' value='2'/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='http://projecteuler.net/index.php?section=login' version='1.1' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;thinktime random='true' value='6'/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;request subst="true"&amp;gt;&lt;br /&gt;&amp;lt;match do="continue" when="match"&amp;gt;Logged in as %%readcsv:getUsername%%&amp;lt;/match&amp;gt;&lt;br /&gt;&amp;lt;http url='/index.php' version='1.1'  contents='%%readcsv:getUserString%%' content_type='application/x-www-form-urlencoded' method='POST'&amp;gt;&amp;lt;/http&amp;gt;&lt;br /&gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;thinktime random='true' value='4'/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='/images/icon_tick.png' version='1.1' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;thinktime random='true' value='4'/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;thinktime random='true' value='3'/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;request&amp;gt;&amp;lt;http url='http://projecteuler.net/index.php?section=logout' version='1.1' method='GET'&amp;gt;&amp;lt;/http&amp;gt;&amp;lt;/request&amp;gt;&lt;br /&gt;&amp;lt;/session&amp;gt;&lt;br /&gt;&amp;lt;/sessions&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/tsung&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Hence, the main thing you should note is the use of dynamic substitution (e.g. %%readcsv:getUsername%%) where i wrote a simple erlang program to read my username and password from a file (see the XML tag &lt;i&gt;option&lt;/i&gt; above) and replacing each simulated user with a valid user id and password. &lt;br /&gt;Next, i checked that the server response contains a string &lt;i&gt;Logged in as XXX&lt;/i&gt; where XXX would be dynamically generated by the function (Check out the erlang code for the function, simple stuff).&lt;br /&gt;The erlang program is shown below. &lt;br /&gt;&lt;div class="code panel" style="border-width: 1px;"&gt;&lt;div class="codeContent panelContent"&gt;&lt;pre class="code-none"&gt;1 -module(readcsv).&lt;br /&gt;2 -export([getUserString/1, getUsername/1]).&lt;br /&gt;3&lt;br /&gt;4 getUserString({Pid, DynVar}) -&amp;gt;&lt;br /&gt;5  {ok, Line} = ts_file_server:get_next_line(),&lt;br /&gt;6  [Uid,Pwd] = string:tokens(Line, ","),&lt;br /&gt;7  "username=" ++ Uid ++ "&amp;amp;password=" ++ Pwd ++ "&amp;amp;login=Login".&lt;br /&gt;8&lt;br /&gt;9 getUsername({Pid, DynVar}) -&amp;gt;&lt;br /&gt;10  {ok, Line} = ts_file_server:get_next_line(),&lt;br /&gt;11  [Uid,_] = string:tokens(Line, ","),&lt;br /&gt;12  Uid.&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;The above erlang code must be compiled via &lt;i&gt;erlc&lt;/i&gt; and you place the &lt;i&gt;.beam&lt;/i&gt; file into the directory via a command like this &lt;br /&gt;&lt;pre&gt;sudo mv readcsv.beam /usr/local/lib/erlang/lib/tsung-1.3.1/ebin/&lt;/pre&gt;&lt;br /&gt;Now, running the load test should be alright.&lt;br /&gt;&lt;b&gt;Note:&lt;/b&gt; In this load test, i defined a duration of 2 minutes with 2 users since load testing using 800 gazillion users is considered a chargeable offense so DON'T DO IT. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Have fun!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-7912841482920223347?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/7912841482920223347/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=7912841482920223347&amp;isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/7912841482920223347'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/7912841482920223347'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2009/11/tsung-load-testing-tool-in-erlang.html' title='Tsung - Load Testing Tool in Erlang'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-8208323853438623829</id><published>2009-08-11T00:25:00.000-07:00</published><updated>2009-08-11T00:39:30.011-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wxErlang'/><category scheme='http://www.blogger.com/atom/ns#' term='GS'/><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><title type='text'>wxErlang</title><content type='html'>There's another graphics library other than "gs" aka Graphical System which is an adaptation of &lt;a href="http://www.wxwidgets.org/"&gt;wxWidgets&lt;/a&gt; otherwise known as &lt;a href="http://sourceforge.net/apps/mediawiki/wxerlang/index.php?title=Main_Page"&gt;wxErlang&lt;/a&gt;. If you have never tried using wxErlang to run your stuff then you might run into some problems.&lt;br /&gt;&lt;br /&gt;Sadly, the documentation on this is pitifully little&lt;br /&gt;&lt;br /&gt;For me, i got this error when i attempt to run the default wx libraries shipped with Erlang. &lt;pre&gt;&lt;br /&gt;=ERROR REPORT==== 7-Jun-2009::12:17:09 ===&lt;br /&gt;WX Failed loading "wxe_driver"@"/usr/local/lib/erlang/lib/wx-0.98.1/&lt;br /&gt;priv/i386-apple-darwin9.6.0"&lt;br /&gt;** exception error: {load_driver,"dlopen(/usr/local/lib/erlang/lib/&lt;br /&gt;wx-0.98.1/priv/i386-apple-darwin9.6.0/wxe_driver.so, 2): Symbol not&lt;br /&gt;found: __ZN10wxGLCanvas20MacVisibilityChangedEv\n  Referenced from: /&lt;br /&gt;usr/local/lib/erlang/lib/wx-0.98.1/priv/i386-apple-darwin9.6.0/&lt;br /&gt;wxe_driver.so\n  Expected in: flat namespace\n"}&lt;br /&gt; in function  wxe_server:start/0&lt;br /&gt; in call from wx:new/1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If this is familiar to you, then i suggest you do the following&lt;br /&gt;1. Read all of &lt;a href="http://sourceforge.net/apps/mediawiki/wxerlang/index.php?title=Getting_Started"&gt;this&lt;/a&gt;&lt;br /&gt;or if you are like me building wxErlang &amp;amp; BEAM emulator 5.7 from source&lt;br /&gt;1. Download the wxErlang libraries from wxErlang website and unzip to dir wxMac-2.8.10&lt;br /&gt;2. Change to that directory&lt;br /&gt;3. Execute the following command:&lt;pre&gt;./configure --with-opengl --enable-unicode --disable-shared --enable-graphics_ctx&lt;/pre&gt;&lt;br /&gt;4. Do the following in sequence:&lt;pre&gt;make &amp;amp;&amp;amp; make install&lt;br /&gt;     cd contrib/src/stc/&lt;br /&gt;     make &amp;amp;&amp;amp; make install&lt;/pre&gt;Note that you might need to do a "sudo make install" if you use the default installation prefix which is /usr/local/{bin,lib, etc}&lt;br /&gt;5. Assumed that you've download Erlang-OTP 13B source code and unzipped to a directory&lt;br /&gt;6. Export the PATH variable such that the build directory to your wxErlang is right at the front of the PATH. e.g. export PATH=&amp;lt;wxErlang dir&amp;gt;:&amp;lt;rest of your path&amp;gt;&lt;br /&gt;7. Build your erlang source code as per your preferences/needs as defined in the README&lt;br /&gt;&lt;br /&gt;After all that is over, you should be able to launch your wxErlang programs.&lt;br /&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-5323400-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-8208323853438623829?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/8208323853438623829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=8208323853438623829&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/8208323853438623829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/8208323853438623829'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2009/08/wxerlang.html' title='wxErlang'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-3546118633525762106</id><published>2009-08-06T15:04:00.000-07:00</published><updated>2009-08-07T00:38:32.813-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='delayed evaluation'/><category scheme='http://www.blogger.com/atom/ns#' term='lazy evaluation'/><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><title type='text'>An example of lazy evaluation for generating lists</title><content type='html'>One thing i've learnt from Erlang is only that its very expressive despite its annoyances but a good outcome of this expressiveness is possibly the availability of &lt;a href="http://en.wikipedia.org/wiki/Lazy_evaluation"&gt;lazy(delayed) evaluation&lt;/a&gt;. In the example of passing lists to functions, the lists are evaluated fully before being passed to functions.&lt;br /&gt;&lt;br /&gt;The big deal here is that you could potentially craft a function that's computationally expensive but the user of this function might not need all the results all at once. Example would be using these sorts of functions to obtain database records and to display them on a webpage but every good UI designer knows that its ineffective to display all 15,000 records at 1 time and you could design a web page that displays 10 - 20 records at a time and have "next" buttons/links to display subsequent pages.&lt;br /&gt;&lt;br /&gt;So, naturally we can craft functions such that we can have lazy evaluation. A simple example is as follows where the function next/1 behaves like a generator function but only delayed; another way to think of this concept is possibly &lt;a href="http://docs.python.org/tutorial/classes.html#generators"&gt;python generators&lt;/a&gt;. In my example below, its not hard to imagine that next/1 could be your computationally expensive operation.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;1 -module(lazy_eval).&lt;br /&gt;2 -export([next/1, test/2]).&lt;br /&gt;3&lt;br /&gt;4 next(Num) -&amp;gt;&lt;br /&gt;5         fun() -&amp;gt; [Num|next(Num+1)] end.&lt;br /&gt;6&lt;br /&gt;7 test(Seq, Fun) when Seq =:= 100 -&amp;gt; [Seq];&lt;br /&gt;8 test(Seq, Fun) when Seq &amp;lt; 100 -&amp;gt;&lt;br /&gt;9         [Val|Func] = Fun(),&lt;br /&gt;10 %        io:format("~p ~p~n", [Val, Func()]),&lt;br /&gt;11         [Val | test(Seq + 1, Func) ].&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A sample output (with debugging statements):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;6&gt; lazy_eval:test(1, lazy_eval:next(1)).&lt;br /&gt;1 [2|#Fun&amp;lt;lazy_eval.0.5801025&amp;gt;]&lt;br /&gt;2 [3|#Fun&amp;lt;lazy_eval.0.5801025&amp;gt;]&lt;br /&gt;3 [4|#Fun&amp;lt;lazy_eval.0.5801025&amp;gt;]&lt;br /&gt;4 [5|#Fun&amp;lt;lazy_eval.0.5801025&amp;gt;]&lt;br /&gt;...&lt;br /&gt;99 [100|#Fun&amp;lt;lazy_eval.0.5801025&amp;gt;]&lt;br /&gt;[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,&lt;br /&gt;23,24,25,26,27,28,29|...]&lt;br /&gt;&lt;/pre&gt;Have fun!&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-5323400-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-3546118633525762106?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/3546118633525762106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=3546118633525762106&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/3546118633525762106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/3546118633525762106'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2009/08/example-of-lazy-evaluation-for.html' title='An example of lazy evaluation for generating lists'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-2334624025247525271</id><published>2009-08-03T17:22:00.000-07:00</published><updated>2009-08-04T03:06:02.752-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><title type='text'>Why Erlang Sucks - by Damien Katz</title><content type='html'>Found another interesting read why Erlang sucks. This post is not to create some sort of flame war and the end result is crucifying Damien but rather his post is a rather insightful look into the annoying part of Erlang that most Erlang developers must have seen (me including) and felt. &lt;br /&gt;&lt;br /&gt;Examples of what i thought was good was his&lt;br /&gt;* comparison of "if" and "case" in Erlang&lt;br /&gt;* Erlang's concept of strings (Which is a real irritance personally to me)&lt;br /&gt;* Erlang's concept of records which is super similar to C's struct (Another irritance but you can get the hang of it...after a while)&lt;br /&gt;* Absolutely love Damien's take of exit(...) and his comments on hara-kiri (Really hilarious)&lt;br /&gt;* I share Damien's criticisms on Erlang's documentation of the libraries&lt;br /&gt;&lt;br /&gt;Overall, its a very honest look into the weaknesses of Erlang as a whole and there's more though...you can form your own opinions about the language though.&lt;br /&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-5323400-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-2334624025247525271?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://damienkatz.net/2008/03/what_sucks_abou.html' title='Why Erlang Sucks - by Damien Katz'/><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/2334624025247525271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=2334624025247525271&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/2334624025247525271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/2334624025247525271'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2009/08/why-erlang-sucks-by-damien-katz.html' title='Why Erlang Sucks - by Damien Katz'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-5579140699149894532</id><published>2009-08-03T03:14:00.000-07:00</published><updated>2009-08-04T03:06:24.718-07:00</updated><title type='text'>Job openings at Linden Lab</title><content type='html'>Linden Lab is hiring lots of talented people out there for software development and QA (that's where i'm in). Visit http://lindenlab.com/employment and if you do find something you like, feel free to drop me a email to tay_boon_leong@yahoo.com.sg or ray@lindenlab.com and yes we do stuff in Erlang, Python, Perl, Django blah blah blah&lt;br /&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-5323400-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-5579140699149894532?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/5579140699149894532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=5579140699149894532&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/5579140699149894532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/5579140699149894532'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2009/08/job-openings-at-linden-lab.html' title='Job openings at Linden Lab'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-7755952004723594479</id><published>2009-08-02T18:51:00.000-07:00</published><updated>2009-08-04T03:06:47.170-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quicksort'/><category scheme='http://www.blogger.com/atom/ns#' term='Algorithm'/><category scheme='http://www.blogger.com/atom/ns#' term='parallel computing'/><title type='text'>Parallel QuickSort</title><content type='html'>Found an interesting blog by a Erlang enthusiast where he implemented a parallel version of the popular QuickSort algorithm. Read about his entry at http://bicosyes.com/paralelizando-quicksort-en-erlang/ where he used the list-comprehension version of QuickSort to implement parallel computation. Its very helpful to see how he made use of erlang:make_ref() to help in the algorithm. Good read.&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-5323400-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-7755952004723594479?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/7755952004723594479/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=7755952004723594479&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/7755952004723594479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/7755952004723594479'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2009/08/parallel-quicksort.html' title='Parallel QuickSort'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-1767360869674281694</id><published>2009-04-21T06:44:00.000-07:00</published><updated>2009-04-21T06:46:23.928-07:00</updated><title type='text'>Notice</title><content type='html'>Hi all, its been a while since i last blogged on Erlang ... infact its almost a year. Its not that i have given up on erlang but rather things have been moving in my career and life in general which left me little time to blog about this but i'll be picking this up again and hopefully u'll like it&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-1767360869674281694?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/1767360869674281694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=1767360869674281694&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/1767360869674281694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/1767360869674281694'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2009/04/notice.html' title='Notice'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-7768726497834198501</id><published>2007-11-07T06:49:00.000-08:00</published><updated>2009-08-04T03:07:07.709-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Algorithm'/><category scheme='http://www.blogger.com/atom/ns#' term='Insertion Sort'/><category scheme='http://www.blogger.com/atom/ns#' term='GS'/><title type='text'>Core Erlang + "GS" = GUI version of the "Insertion Sort"</title><content type='html'>In this article, i got another popular sorting algorithm commonly known as the "&lt;a href="http://en.wikipedia.org/wiki/Insertion_sort"&gt;Insertion Sort&lt;/a&gt;". Basically, this sort an example of (a) &lt;a href="http://en.wikipedia.org/wiki/In-place_algorithm"&gt;in-place&lt;/a&gt; , (b) &lt;a href="http://en.wikipedia.org/wiki/Comparison_sort"&gt;comparison-sort&lt;/a&gt; .You may wish to consult your favourite algorithm texts or visit the Wikipedia (I've heard its rather unreliable but i'm not so sure why). Again like all my previous articles, there are two parts to this: (a) Non-graphical, (b) Graphical version.&lt;br /&gt;&lt;br /&gt;Here's the codes:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="color: rgb(51, 204, 0);"&gt;Filename:&lt;/span&gt; "&lt;span style="color: rgb(51, 204, 0);"&gt;isort.erl&lt;/span&gt;"&lt;/span&gt;&lt;br /&gt;-module(isort).&lt;br /&gt;-export([start/1]).&lt;br /&gt;-copyright('Copyright (c) 2007 Raymond Tay').&lt;br /&gt;-vsn('$Revision: 1').&lt;br /&gt;%&lt;br /&gt;%&lt;br /&gt;% The insertion sort is a good middle-of-the-road choice for sorting lists of&lt;br /&gt;% a few thousand items or less. The algorithm is significantly simpler than&lt;br /&gt;% the shell sort, with only a small trade off in efficiency. At the same time&lt;br /&gt;% the insertion sort is over twice as fast as the bubble sort and almost 40%&lt;br /&gt;% faster than the selection sort. The insertion sort shouldn't be used for&lt;br /&gt;% sorting lists larger than a couple thousands items or repetitive sorting&lt;br /&gt;%of lists larger than a couple hundred items&lt;br /&gt;%&lt;br /&gt;% insertionSort(array A)&lt;br /&gt;%          for i = 1 to length[A]-1 do&lt;br /&gt;%                 value = A[i]&lt;br /&gt;%                 j = i-1&lt;br /&gt;%                 while j &amp;gt;= 0 and A[j] &amp;gt; value do&lt;br /&gt;%                          A[j + 1] = A[j]&lt;br /&gt;%                          j = j-1&lt;br /&gt;%                 A[j+1] = value&lt;br /&gt;%&lt;br /&gt;&lt;br /&gt;genNum(N,N,L,F,Num) -&amp;gt; [F(Num),L];&lt;br /&gt;genNum(I,N,L,F,Num) -&amp;gt; Val = F(Num),  genNum(I+1,N,[Val,L],F,Num).&lt;br /&gt;&lt;br /&gt;for(N,N,F,L) -&amp;gt; Val = lists:nth(N,L), J = N - 1,T = lists:nth(J,L), F(J,L,Val,T);&lt;br /&gt;for(I,N,F,L) -&amp;gt; Val = lists:nth(I,L), J = I - 1,T = lists:nth(J,L), L2 = F(J,L,Val,T), for(I+1,N,F,L2).&lt;br /&gt;&lt;br /&gt;checkNInsert(Index,L,Value,T) when Index &amp;gt;= 1 andalso T &amp;gt; Value -&amp;gt;&lt;br /&gt;{L1,L2} = lists:split(Index,L),&lt;br /&gt;[_H|T1] = L2,&lt;br /&gt;Temp1 = lists:flatten(lists:append([L1],[T])),&lt;br /&gt;Temp2 = lists:append(Temp1, T1),&lt;br /&gt;if&lt;br /&gt;  Index - 1 /= 0 -&amp;gt;&lt;br /&gt;   NewVal = lists:nth(Index - 1, Temp2),&lt;br /&gt;   checkNInsert(Index - 1, Temp2, Value, NewVal);&lt;br /&gt;  Index - 1 =:= 0 -&amp;gt;&lt;br /&gt;   checkNInsert(Index - 1, Temp2, Value, Value)&lt;br /&gt;end;&lt;br /&gt;checkNInsert(Index,L,Value,T) when Index =&amp;lt; 1 orelse T =&amp;lt; Value -&amp;gt;&lt;br /&gt;{L1,L2} = lists:split(Index,L),&lt;br /&gt;[_H|T1] = L2,&lt;br /&gt;lists:append(lists:append(L1,[Value]),T1).&lt;br /&gt;&lt;br /&gt;start(N) -&amp;gt;&lt;br /&gt;L = lists:flatten(genNum(1,N,[],fun random:uniform/1, N)),&lt;br /&gt;for(2, length(L), fun checkNInsert/4, L).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And next is for the graphical version&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="color: rgb(51, 204, 0);"&gt;Filename:&lt;/span&gt; "&lt;span style="color: rgb(51, 204, 0);"&gt;isortgui.erl&lt;/span&gt;"&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;-module(isortgui).&lt;br /&gt;-export([start/0]).&lt;br /&gt;-copyright('Copyright (c) 2007 Raymond Tay').&lt;br /&gt;-vsn('$Revision: 1').&lt;br /&gt;%&lt;br /&gt;% The insertion sort is a good middle-of-the-road choice for sorting lists of&lt;br /&gt;% a few thousand items or less. The algorithm is significantly simpler than&lt;br /&gt;% the shell sort, with only a small trade off in efficiency. At the same time&lt;br /&gt;% the insertion sort is over twice as fast as the bubble sort and almost 40%&lt;br /&gt;% faster than the selection sort. The insertion sort shouldn't be used for&lt;br /&gt;% sorting lists larger than a couple thousands items or repetitive sorting&lt;br /&gt;% of lists larger than a couple hundred items&lt;br /&gt;%&lt;br /&gt;% insertionSort(array A)&lt;br /&gt;%          for i = 1 to length[A]-1 do&lt;br /&gt;%                 value = A[i]&lt;br /&gt;%                 j = i-1&lt;br /&gt;%                 while j &amp;gt;= 0 and A[j] &amp;gt; value do&lt;br /&gt;%                          A[j + 1] = A[j]&lt;br /&gt;%                          j = j-1&lt;br /&gt;%                 A[j+1] = value&lt;br /&gt;%&lt;br /&gt;forL(N,N,{stretch,_N,_X}) -&amp;gt; [{stretch,_N,_X}];&lt;br /&gt;forL(I,N,{stretch,_N,_X}) -&amp;gt; [{stretch,_N,_X}|forL(I+1,N,{stretch,_N,_X})].&lt;br /&gt;&lt;br /&gt;for(N,N,F,L) -&amp;gt; {_,Val} = gs:read(dict:fetch({1,N},L),label), J = N - 1, {_,T} = gs:read(dict:fetch({1,J},L),label), {Val1,_} = string:to_integer(Val), {T1,_} = string:to_integer(T),F(J,L,Val1,T1);&lt;br /&gt;for(I,N,F,L) -&amp;gt; {_,Val} = gs:read(dict:fetch({1,I},L),label), J = I - 1, {_,T} = gs:read(dict:fetch({1,J},L),label), {Val1,_} = string:to_integer(Val), {T1,_} = string:to_integer(T), D2 = F(J,L,Val1,T1), for(I+1,N,F,D2).&lt;br /&gt;&lt;br /&gt;checkNInsert(Index,L,Value,T) when Index &amp;gt;= 1 andalso T &amp;gt; Value -&amp;gt;&lt;br /&gt;ButId = dict:fetch({1,Index+1},L),&lt;br /&gt;gs:config(ButId, [{label, {text, T}}]),&lt;br /&gt;gs:config(ButId, [flash]),&lt;br /&gt;sleep(50),&lt;br /&gt;if&lt;br /&gt; Index - 1 =:= 0 -&amp;gt; checkNInsert(0,L,Value,Value);&lt;br /&gt; Index - 1  /= 0 -&amp;gt;&lt;br /&gt;   {_,Val} = gs:read(dict:fetch({1,Index -1},L),label),&lt;br /&gt;   {Val1,_} = string:to_integer(Val),&lt;br /&gt;   if&lt;br /&gt;     Val1 =&amp;lt; Value -&amp;gt; checkNInsert(Index - 1, L, Value, Value);&lt;br /&gt;     Val1 &amp;gt; Value -&amp;gt; checkNInsert(Index - 1, L, Value, Val1)&lt;br /&gt;   end&lt;br /&gt;end;&lt;br /&gt;checkNInsert(Index,L,Value,T) when Index =:= 0 orelse T =&amp;lt; Value -&amp;gt;&lt;br /&gt;ButId = dict:fetch({1,Index+1},L),&lt;br /&gt;gs:config(ButId, [{label, {text, Value}}]),&lt;br /&gt;gs:config(ButId, [flash]),&lt;br /&gt;L.&lt;br /&gt;&lt;br /&gt;isort(Dict) -&amp;gt;&lt;br /&gt;for(2, 50, fun checkNInsert/4, Dict). % Sort it for 2-to-&amp;lt;number of columns in GUI&amp;gt;&lt;br /&gt;&lt;br /&gt;start() -&amp;gt;&lt;br /&gt;      D = dict:new(),&lt;br /&gt;      WH = [{width, 1000}, {height, 50}],&lt;br /&gt; Win = gs:window(gs:start(), [{map, true}, {configure, true}, {title, "Insertion-Sort Algorithm"} |WH]),&lt;br /&gt; XOpts = forL(1,50,{stretch,1,20}),&lt;br /&gt; YOpts = [{stretch,1,20}],&lt;br /&gt; gs:frame(packer, Win, [{packer_x, XOpts}, {packer_y, YOpts}]),&lt;br /&gt;      NewD = genBut(1,1,D),&lt;br /&gt;      gs:config(packer,WH),&lt;br /&gt; dumpDict(NewD),&lt;br /&gt; isort(NewD),&lt;br /&gt; dumpDict(NewD),&lt;br /&gt; io:format("algo done~n",[]),&lt;br /&gt;      loop().&lt;br /&gt;%&lt;br /&gt;%&lt;br /&gt;% Generate the "button" GUI objects&lt;br /&gt;%&lt;br /&gt;genBut(Row,Col,Dict) when Col =&amp;lt; 50 -&amp;gt;&lt;br /&gt; ButId = gs:button(packer, [{label, {text, random:uniform(50)}}, {pack_xy, {Col,Row}}]),&lt;br /&gt; NewDict = dict:store({Row,Col}, ButId, Dict), % used later for GUI manipulation&lt;br /&gt; genBut(Row,Col+1,NewDict);&lt;br /&gt;genBut(Row,Col,Dict) when Col &amp;gt; 50 -&amp;gt; Dict.&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;% Pretty standard GUI-event loop&lt;br /&gt;%&lt;br /&gt;loop() -&amp;gt;&lt;br /&gt;receive&lt;br /&gt;{gs,_Id,destroy,_Data,_Arg} -&amp;gt; bye;&lt;br /&gt;{gs,_Id,configure,_Data,[W,H|_]} -&amp;gt;&lt;br /&gt;   gs:config(packer, [{width,W}, {height,H}]), %refresh to initial size&lt;br /&gt;   loop();&lt;br /&gt;_Other -&amp;gt; loop()&lt;br /&gt;end.&lt;br /&gt;%&lt;br /&gt;% Pretty standard "sleep" function&lt;br /&gt;%&lt;br /&gt;sleep(T) -&amp;gt;&lt;br /&gt;receive&lt;br /&gt;after T -&amp;gt; ok&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;% Dump the dictionary&lt;br /&gt;%&lt;br /&gt;dumpDict(D) -&amp;gt;&lt;br /&gt;Keys = lists:sort(dict:fetch_keys(D)),&lt;br /&gt;lists:foreach( fun({R,C}) -&amp;gt; Val = gs:read(dict:fetch({R,C},D),label), io:format("{~p,~p}-&amp;gt;~p~n", [R,C,Val]) end, Keys).&lt;br /&gt;&lt;/pre&gt;While the algorithm is executing, you will notice that the buttons will flash every time it detects a re-positioning is required. Here is a screen shot and do let me know if you have any comments, it would be much appreciated; that applies to ideas as well :-)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_n2HkB0XD3Kw/RzOoUjra6tI/AAAAAAAAAl4/3ZQ-2h-I-5E/s1600-h/Screenshot-Insertion-Sort+Algorithm.png"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_n2HkB0XD3Kw/RzOoUjra6tI/AAAAAAAAAl4/3ZQ-2h-I-5E/s320/Screenshot-Insertion-Sort+Algorithm.png" alt="" id="BLOGGER_PHOTO_ID_5130629471633337042" border="0" /&gt;&lt;/a&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-5323400-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-7768726497834198501?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/7768726497834198501/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=7768726497834198501&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/7768726497834198501'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/7768726497834198501'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2007/11/core-erlang-gs-gui-version-of-insertion.html' title='Core Erlang + &quot;GS&quot; = GUI version of the &quot;Insertion Sort&quot;'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_n2HkB0XD3Kw/RzOoUjra6tI/AAAAAAAAAl4/3ZQ-2h-I-5E/s72-c/Screenshot-Insertion-Sort+Algorithm.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-6683762241958367234</id><published>2007-11-03T17:45:00.000-07:00</published><updated>2009-08-04T03:07:22.884-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Algorithm'/><category scheme='http://www.blogger.com/atom/ns#' term='GS'/><category scheme='http://www.blogger.com/atom/ns#' term='BubbleSort'/><title type='text'>Core Erlang + "GS" = GUI version of the "BubbleSort"</title><content type='html'>Everyone who has studied Computer Science would know about the &lt;a href="http://en.wikipedia.org/wiki/Bubble_sort"&gt;Bubble Sort&lt;/a&gt; algorithm. This is a simple sorting algorithm which runs at O(n^2). You may wish to consult your standard data structure text or the above hyperlink for further information.&lt;br /&gt;&lt;br /&gt;Since this particular blog of mine is about Erlang and also i'm quite "hooked" to it, so again this article is about illustrating this algorithm implemented using Erlang. It's a fun exercise.&lt;br /&gt;&lt;br /&gt;I have included source codes for running 2 versions: (a) Non-graphical and (b) Graphical.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;%&lt;br /&gt;% This is an attempt to create a GUI version of the "Bubble Sort"&lt;br /&gt;%&lt;br /&gt;% procedure bubblesort(A:list of unsorted items) defined as:&lt;br /&gt;%  do&lt;br /&gt;%   swapped := false&lt;br /&gt;%   for each i in 0 to length(A) -2 do&lt;br /&gt;%    if A[i] &amp;gt; A[i+1] then&lt;br /&gt;%     swap(A[i], A[i+1])&lt;br /&gt;%     swapped := true&lt;br /&gt;%    end if&lt;br /&gt;%   end for&lt;br /&gt;%   while swapped&lt;br /&gt;% end procedure&lt;br /&gt;&lt;br /&gt;-module(bsort).&lt;br /&gt;-export([start/1, init/1]).&lt;br /&gt;-copyright('Copyright (c) 2007 Raymond Tay').&lt;br /&gt;-vsn('$Revision: 1').&lt;br /&gt;&lt;br /&gt;start(N) -&amp;gt; spawn(bsort, init, [N]).&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;% Standard "for"-loop concept&lt;br /&gt;%&lt;br /&gt;for(N,N,Dict,F,Num) -&amp;gt; Val = F(Num), NewDict = dict:store(N,Val,Dict), NewDict;&lt;br /&gt;for(I,N,Dict,F,Num) -&amp;gt; Val = F(Num), NewDict = dict:store(I,Val,Dict), for(I+1,N,NewDict,F,Num).&lt;br /&gt;&lt;br /&gt;% Swaps the value but not the position of the record&lt;br /&gt;%&lt;br /&gt;swap({Pos1,Value1},{Pos2,Value2},Dict) -&amp;gt;&lt;br /&gt;NewDict1 = dict:store(Pos1,Value2,Dict),&lt;br /&gt;NewDict2 = dict:store(Pos2,Value1,NewDict1),&lt;br /&gt;NewDict2.&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;% BubbleSort implementation&lt;br /&gt;%&lt;br /&gt;bsort(D,Swapped) when Swapped =:= false -&amp;gt; D;&lt;br /&gt;bsort(D,Swapped) when Swapped =:= true -&amp;gt;&lt;br /&gt;Len = erlang:length(dict:fetch_keys(D)),&lt;br /&gt;{Again, NewDict} = checkNSwap(D,1,Len, false),&lt;br /&gt;bsort(NewDict,Again).&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;% Check-N-Swap&lt;br /&gt;%&lt;br /&gt;checkNSwap(Dict,N,N,Again) -&amp;gt; {Again,Dict};&lt;br /&gt;checkNSwap(Dict,I,N,Again) -&amp;gt;&lt;br /&gt;Ele1 = dict:fetch(I,Dict),&lt;br /&gt;Ele2 = dict:fetch(I+1,Dict),&lt;br /&gt;if&lt;br /&gt; Ele1 &amp;gt; Ele2 -&amp;gt; NewDict = swap({I,Ele1},{I+1,Ele2},Dict), checkNSwap(NewDict, I+1,N,true);&lt;br /&gt; Ele1 =&amp;lt; Ele2 -&amp;gt; checkNSwap(Dict,I+1,N,Again)&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;init(N) -&amp;gt; Dict = dict:new(),&lt;br /&gt;         NewDict = for(1,N,Dict, fun random:uniform/1, N),&lt;br /&gt;   dumpDict(bsort(NewDict,true)).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;dumpDict(Dict) -&amp;gt;&lt;br /&gt;Keys = lists:sort(dict:fetch_keys(Dict)),&lt;br /&gt;lists:foreach(fun(X) -&amp;gt; io:format("{~p,~p} ...", [X,dict:fetch(X,Dict)]) end, Keys).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The next is the source code for the graphical version of the "Bubble Sort" and some screen-shots of the algorithm in action. I used an 25 x 25 "grid" composed of buttons (Will explore using the canvas when i have more time) and i tried the 100 x 100 "grid" but it didn't work out on my laptop as i had some resolution problems, but i think as an exercise a 25 x 25 was good enough for me :-)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;-module(bsortgui).&lt;br /&gt;-export([start/0]).&lt;br /&gt;%&lt;br /&gt;% BubbleSort implementation&lt;br /&gt;%&lt;br /&gt;bsort(D,Swapped) when Swapped =:= false -&amp;gt; D;&lt;br /&gt;bsort(D,Swapped) when Swapped =:= true -&amp;gt;&lt;br /&gt;{Again, NewDict} = checkNSwap(D,1,25, false),&lt;br /&gt;bsort(NewDict,Again).&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;% Swaps the value but not the position of the record&lt;br /&gt;%&lt;br /&gt;swap({Pos1,Value1,ButId1},{Pos2,Value2,ButId2},Dict) -&amp;gt;&lt;br /&gt;gs:config(ButId1,[{label, {text, ""}}]),&lt;br /&gt;gs:config(ButId2,[{label, {text, ""}}]),&lt;br /&gt;NewButId1 = dict:fetch({Value1,Pos2},Dict),&lt;br /&gt;NewButId2 = dict:fetch({Value2,Pos1},Dict),&lt;br /&gt;gs:config(NewButId1,[{label, {text, Value1}}]),&lt;br /&gt;gs:config(NewButId2,[{label, {text, Value2}}]),&lt;br /&gt;NewDict1 = dict:store(Pos1,{Value2,NewButId2},Dict),&lt;br /&gt;NewDict2 = dict:store(Pos2,{Value1,NewButId1},NewDict1), NewDict2.&lt;br /&gt;&lt;br /&gt;sleep(T) -&amp;gt;&lt;br /&gt;receive&lt;br /&gt;after T -&amp;gt; ok end.&lt;br /&gt;%&lt;br /&gt;% Check-N-Swap&lt;br /&gt;%&lt;br /&gt;checkNSwap(Dict,N,N,Again) -&amp;gt; {Again,Dict};&lt;br /&gt;checkNSwap(Dict,I,N,Again) -&amp;gt;&lt;br /&gt;{Ele1,ButId1} = dict:fetch(I,Dict),&lt;br /&gt;{Ele2,ButId2} = dict:fetch(I+1,Dict),&lt;br /&gt;%io:format("Col:~p,Row:~p~n", [I,Ele1]),&lt;br /&gt;%io:format("Col:~p,Row:~p~n", [I+1,Ele2]),&lt;br /&gt;if&lt;br /&gt; Ele1 &amp;gt; Ele2 -&amp;gt; NewDict = swap({I,Ele1,ButId1},{I+1,Ele2,ButId2},Dict), sleep(300), checkNSwap(NewDict, I+1,N,true);&lt;br /&gt; Ele1 =&amp;lt; Ele2 -&amp;gt; checkNSwap(Dict,I+1,N,Again)&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;forL(N,N,{stretch,_N,_X}) -&amp;gt; [{stretch,_N,_X}];&lt;br /&gt;forL(I,N,{stretch,_N,_X}) -&amp;gt; [{stretch,_N,_X}|forL(I+1,N,{stretch,_N,_X})].&lt;br /&gt;&lt;br /&gt;%for(N,N,[H|_], D, F) -&amp;gt; F(H,D);&lt;br /&gt;%for(I,N,[H|T], D, F) -&amp;gt; NewD = F(H,D), for(I+1,N,T,NewD,F).&lt;br /&gt;&lt;br /&gt;genBut(Row,Col,Dict) when Row*Col =&amp;lt; 625  -&amp;gt;&lt;br /&gt;if&lt;br /&gt; Col =&amp;lt; 25 -&amp;gt;&lt;br /&gt;  ButId = gs:button(packer, [{label, {text, ""}}, {pack_xy, {Col,Row}}]),&lt;br /&gt;  NewDict = dict:store({Row,Col}, ButId, Dict), % used later for GUI manipulation&lt;br /&gt;  %io:format("genBut(), Row:~p, Col:~p, Id:~p~n", [Row,Col,ButId]),&lt;br /&gt; genBut(Row,Col+1,NewDict);&lt;br /&gt; Col &amp;gt; 25 -&amp;gt; genBut(Row+1, 1, Dict)&lt;br /&gt;end;&lt;br /&gt;genBut(Row,Col,Dict) when Row*Col &amp;gt; 625 -&amp;gt; Dict.&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;% Fill each column with exactly 1 random number&lt;br /&gt;%&lt;br /&gt;fillRand(Col,Dict) when Col =&amp;lt; 25  -&amp;gt;&lt;br /&gt;Ran = random:uniform(25),&lt;br /&gt;if&lt;br /&gt; Col =&amp;lt; 25 -&amp;gt;&lt;br /&gt;  ButId = dict:fetch({Ran,Col},Dict),&lt;br /&gt;  gs:config(ButId, [{label, {text, Ran}}]),&lt;br /&gt;  NewDict = dict:store(Col, {Ran,ButId}, Dict), % used later for GUI manipulation&lt;br /&gt;  %io:format("Row:~p,Col:~p,Val:~p~n", [Ran,Col,Ran]),&lt;br /&gt;  fillRand(Col+1,NewDict)&lt;br /&gt;end;&lt;br /&gt;fillRand(Col,Dict) when Col &amp;gt; 25 -&amp;gt; Dict.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;start() -&amp;gt;&lt;br /&gt;       D = dict:new(),&lt;br /&gt;       WH = [{width, 800}, {height, 800}],&lt;br /&gt; Win = gs:window(gs:start(), [{map, true}, {configure, true}, {title, "BubbleSort Algorithm"} |WH]),&lt;br /&gt; XOpts = forL(1,25,{stretch,1,15}),&lt;br /&gt; YOpts = forL(1,25,{stretch,1,15}),&lt;br /&gt; gs:frame(packer, Win, [{packer_x, XOpts}, {packer_y, YOpts}]),&lt;br /&gt;       NewD = genBut(1,1,D),&lt;br /&gt;       NewD2 = fillRand(1,NewD),&lt;br /&gt;       gs:config(packer,WH),&lt;br /&gt; bsort(NewD2,true),&lt;br /&gt; io:format("Done~n",[]),&lt;br /&gt;       loop().&lt;br /&gt;%&lt;br /&gt;% A typical loop for receiving messages&lt;br /&gt;%&lt;br /&gt;loop() -&amp;gt;&lt;br /&gt;receive&lt;br /&gt; {gs,_Id,destroy,_Data,_Arg} -&amp;gt; bye;&lt;br /&gt; {gs,_Id,configure,_Data,[W,H|_]} -&amp;gt;&lt;br /&gt;    gs:config(packer, [{width,W},{height,H}]), %refresh to initial size&lt;br /&gt;    loop();&lt;br /&gt; _Other -&amp;gt; loop()&lt;br /&gt;end.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Below are some screenshots.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_n2HkB0XD3Kw/Ry232zijEWI/AAAAAAAAAlg/rwBnNrFCQOU/s1600-h/bsort1.png"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_n2HkB0XD3Kw/Ry232zijEWI/AAAAAAAAAlg/rwBnNrFCQOU/s320/bsort1.png" alt="" id="BLOGGER_PHOTO_ID_5128957702820794722" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_n2HkB0XD3Kw/Ry24GjijEXI/AAAAAAAAAlo/rQJEVpXIHsE/s1600-h/bsort3.png"&gt;&lt;img style="cursor: pointer;" src="http://bp0.blogger.com/_n2HkB0XD3Kw/Ry24GjijEXI/AAAAAAAAAlo/rQJEVpXIHsE/s320/bsort3.png" alt="" id="BLOGGER_PHOTO_ID_5128957973403734386" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_n2HkB0XD3Kw/Ry24RzijEYI/AAAAAAAAAlw/_t32RCkBYH4/s1600-h/bsort4.png"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_n2HkB0XD3Kw/Ry24RzijEYI/AAAAAAAAAlw/_t32RCkBYH4/s320/bsort4.png" alt="" id="BLOGGER_PHOTO_ID_5128958166677262722" border="0" /&gt;&lt;/a&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-5323400-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Let me know your comments if you got any :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-6683762241958367234?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/6683762241958367234/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=6683762241958367234&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/6683762241958367234'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/6683762241958367234'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2007/11/core-erlang-gs-gui-version-of.html' title='Core Erlang + &quot;GS&quot; = GUI version of the &quot;BubbleSort&quot;'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_n2HkB0XD3Kw/Ry232zijEWI/AAAAAAAAAlg/rwBnNrFCQOU/s72-c/bsort1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-2835120559485447187</id><published>2007-10-29T02:36:00.000-07:00</published><updated>2009-08-04T03:07:35.530-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sieve of Eratosthenes'/><category scheme='http://www.blogger.com/atom/ns#' term='GS'/><title type='text'>Core Erlang + "GS" = GUI version of the "Sieve"</title><content type='html'>In this article, i want to demonstrate a bit more about the G.S. Previously, i wrote an extremely simple  &lt;a href="http://erlangraymondtay.blogspot.com/2007/10/using-graphical-system-aka-gs-module-in.html"&gt;Erlang Window&lt;/a&gt; just to see how it easy it was, apparently it's not very difficult.&lt;br /&gt;&lt;br /&gt;What i subsequently did was to combine the both the "GS" and the &lt;a href="http://erlangraymondtay.blogspot.com/2007/10/sieve-of-eratosthenes.html"&gt;Sieve of Eratosthenes&lt;/a&gt; to produce a graphical version of the "sieving" problem. The point of this exercise was to illustrate how easy it was to code in Erlang once you have gotten used to its semantics, i had fun doing it.&lt;br /&gt;&lt;br /&gt;Owing to my laptop's screen resolution, i could only manage a 25-by-25 grid but that's not the point of this exercise. Here are some screen shots and a working code (Code needs to be smoothen though, let me know your comments)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;%&lt;br /&gt;% This is an attempt to create a GUI version of the &amp;quot;Sieve of Erasothenes'&lt;br /&gt;% &lt;br /&gt;%&lt;br /&gt;-module(sievegui).&lt;br /&gt;-export([start/0, init/1]).&lt;br /&gt;-copyright('Copyright (c) 2007 Raymond Tay').&lt;br /&gt;-vsn('$Revision: 1').&lt;br /&gt;%&lt;br /&gt;% The following generates a list of multiples-of-Base&lt;br /&gt;% e.g. To generate multiples of 3 less than 100, enter &amp;quot;sieve:genmulti(0,3,100)&amp;quot;&lt;br /&gt;%      and you get [9,12,15,18|...]&lt;br /&gt;%&lt;br /&gt;genmulti(Index,Base,Limit) when (Base*Base+Index*Base) &amp;gt; Limit -&amp;gt; [];&lt;br /&gt;genmulti(Index,Base,Limit) when (Base*Base+Index*Base) =&amp;lt; Limit -&amp;gt; [Base*Base+Index*Base | genmulti(Index+1,Base,Limit) ].&lt;br /&gt;&lt;br /&gt;sleep(T) -&amp;gt;&lt;br /&gt; receive&lt;br /&gt; after T -&amp;gt; ok&lt;br /&gt; end.&lt;br /&gt;%&lt;br /&gt;% Obtains the GS's &amp;quot;object id&amp;quot; and manipulates the display&lt;br /&gt;%&lt;br /&gt;filterDisplay(ObjId,List) -&amp;gt; &lt;br /&gt;                   {_,ObjValue} = gs:read(ObjId, label),&lt;br /&gt;     {IntValue,X} = string:to_integer(ObjValue),&lt;br /&gt;     Result = lists:member(IntValue,List),&lt;br /&gt;     if &lt;br /&gt;   Result =:= true -&amp;gt; gs:config(ObjId,[{label, {text, &amp;quot;&amp;quot;}}]);&lt;br /&gt;   Result =:= false -&amp;gt; ok &lt;br /&gt;                   end,&lt;br /&gt;     sleep(50).&lt;br /&gt;% filterDisplay(ObjId,List) -&amp;gt; &lt;br /&gt;%                    {_,ObjValue} = gs:read(ObjId, label),&lt;br /&gt;%      Result = lists:member(ObjValue,List),&lt;br /&gt;%                    if &lt;br /&gt;%                       Result =:= true -&amp;gt; gs:config(ObjId,[{label, {text, &amp;quot;&amp;quot;}}])&lt;br /&gt;%                    end.&lt;br /&gt;&lt;br /&gt;removeMultiples(Index, List, Limit, Dict) when Index /= erlang:length(List) -&amp;gt;&lt;br /&gt; Head = lists:nth(Index,List),&lt;br /&gt;        RemoveList = genmulti(0,Head,Limit),&lt;br /&gt;        Keys = dict:fetch_keys(Dict),&lt;br /&gt;        lists:foreach( fun(X) -&amp;gt; filterDisplay(X,RemoveList) end, Keys),&lt;br /&gt; NewList = List -- RemoveList,&lt;br /&gt; removeMultiples(Index+1, NewList, Limit, Dict);&lt;br /&gt;removeMultiples(Index, List, _, _) when Index =:= erlang:length(List) -&amp;gt; List.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;% A standard Erlang &amp;quot;for&amp;quot;-loop&lt;br /&gt;%&lt;br /&gt;for(N,N,F) -&amp;gt; F();&lt;br /&gt;for(I,N,F) -&amp;gt; F(),for(I+1,N,F).&lt;br /&gt;&lt;br /&gt;forL(N,N,{stretch,_N,_X}) -&amp;gt; [{stretch,_N,_X}];&lt;br /&gt;forL(I,N,{stretch,_N,_X}) -&amp;gt; [{stretch,_N,_X}|forL(I+1,N,{stretch,_N,_X})].&lt;br /&gt;%&lt;br /&gt;% start() -&amp;gt; You can call this if you wish; the only difference between this and init() is that start() starts&lt;br /&gt;%            a spawned process&lt;br /&gt;%&lt;br /&gt;start() -&amp;gt; spawn(gsdemo, init, [625]).&lt;br /&gt;&lt;br /&gt;% &lt;br /&gt;% Generates the GUI for the button &lt;br /&gt;% where the label for each button is that of incremental number&lt;br /&gt;%&lt;br /&gt;genBut(Row,Col,Text,Dict) when Row*Col =&amp;lt; 625  -&amp;gt;&lt;br /&gt; if&lt;br /&gt;  Col =&amp;lt; 25 -&amp;gt; &lt;br /&gt;   %io:format(&amp;quot;R:~p,C:~p,T:~p~n&amp;quot;, [Row,Col,erlang:integer_to_list(Text,10)]),&lt;br /&gt;   ButId = gs:button(packer, [{label, {text, erlang:integer_to_list(Text,10)}}, {pack_xy, {Col,Row}}]),&lt;br /&gt;   NewDict = dict:store(ButId, ButId, Dict),&lt;br /&gt;   NewText = Text+1,&lt;br /&gt;   genBut(Row,Col+1, NewText, NewDict);&lt;br /&gt;  Col &amp;gt; 25 -&amp;gt; genBut(Row+1, 1, Text, Dict)&lt;br /&gt; end;&lt;br /&gt;genBut(Row,Col,_Text, Dict) when Row*Col &amp;gt; 625 -&amp;gt; Dict.&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;% init() - You can call this if you wish&lt;br /&gt;% &lt;br /&gt; init(Num) -&amp;gt;&lt;br /&gt; _Dict = dict:new(), % process dictionary&lt;br /&gt; WH = [{width, 800}, {height, 800}],&lt;br /&gt; Win = gs:window(gs:start(), [{map, true}, {configure, true}, {title, &amp;quot;Sieve of Erasothenes&amp;quot;} |WH]),&lt;br /&gt; XOpts = forL(1,25,{stretch,1,8}),&lt;br /&gt; YOpts = forL(1,25,{stretch,1,8}),&lt;br /&gt; gs:frame(packer, Win, [{packer_x, XOpts}, {packer_y, YOpts}]),&lt;br /&gt; NewDict = genBut(1,1,2,_Dict),&lt;br /&gt; gs:config(packer, WH), %refresh to initial size&lt;br /&gt; List = lists:seq(2,Num),&lt;br /&gt; FinalList = removeMultiples(1, List, lists:max(List), NewDict),&lt;br /&gt; loop().&lt;br /&gt;%&lt;br /&gt;% A typical loop for receiving messages&lt;br /&gt;%&lt;br /&gt;loop() -&amp;gt;&lt;br /&gt; receive&lt;br /&gt;  {gs,_Id,destroy,_Data,_Arg} -&amp;gt; bye;&lt;br /&gt;  Other -&amp;gt; loop()&lt;br /&gt; end.&lt;br /&gt;&lt;/pre&gt;There are three screenshots below of this application to illustrate the program sieving through the numbers&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_n2HkB0XD3Kw/Rylz2zijETI/AAAAAAAAAlI/l7p4Q-Gqegg/s1600-h/1.png"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_n2HkB0XD3Kw/Rylz2zijETI/AAAAAAAAAlI/l7p4Q-Gqegg/s320/1.png" alt="" id="BLOGGER_PHOTO_ID_5127757036123263282" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_n2HkB0XD3Kw/Ryl0WTijEUI/AAAAAAAAAlQ/wikqHln4eOw/s1600-h/2.png"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_n2HkB0XD3Kw/Ryl0WTijEUI/AAAAAAAAAlQ/wikqHln4eOw/s320/2.png" alt="" id="BLOGGER_PHOTO_ID_5127757577289142594" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_n2HkB0XD3Kw/Ryl0bDijEVI/AAAAAAAAAlY/d9bpaSfdQU4/s1600-h/3.png"&gt;&lt;img style="cursor: pointer;" src="http://bp2.blogger.com/_n2HkB0XD3Kw/Ryl0bDijEVI/AAAAAAAAAlY/d9bpaSfdQU4/s320/3.png" alt="" id="BLOGGER_PHOTO_ID_5127757658893521234" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;That's it, all comments are welcome.&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-5323400-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-2835120559485447187?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/2835120559485447187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=2835120559485447187&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/2835120559485447187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/2835120559485447187'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2007/10/core-erlang-gs-gui-version-of-sieve.html' title='Core Erlang + &quot;GS&quot; = GUI version of the &quot;Sieve&quot;'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_n2HkB0XD3Kw/Rylz2zijETI/AAAAAAAAAlI/l7p4Q-Gqegg/s72-c/1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-7680935833099820478</id><published>2007-10-14T21:47:00.000-07:00</published><updated>2007-10-29T05:23:29.696-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EJB'/><category scheme='http://www.blogger.com/atom/ns#' term='Hot Code Swap'/><title type='text'>Erlang Hot Code Swapping</title><content type='html'>In this post, i'm going to repeat Joe Armstrong's technique of &lt;span style="font-style: italic; color: rgb(0, 153, 0);"&gt;hot code swapping&lt;/span&gt; using Erlang. It's a extremely powerful technique which basically allows you to swap/interchange code without restarting the server(s).&lt;a href="http://armstrongonsoftware.blogspot.com/"&gt;Joe Armstrong&lt;/a&gt;, in his book, demonstrated the technique of hot swapping and i would like to repeat that with a J2EE twist to it. To my knowledge, most J2EE container cannot perform this smoothly yet; however, do let me know if my information is not correct.&lt;br /&gt;&lt;br /&gt;What i have is a simple &lt;a href="http://java.sun.com/j2ee/1.4/docs/tutorial/doc/EJBConcepts9.html#wp80214"&gt;Stateless Session&lt;/a&gt; EJB (&lt;a href="http://java.sun.com/products/ejb/"&gt;Enterprise Java Bean&lt;/a&gt;). The J2EE container model uses a callback invocation + client-server architecture so that the container can run both client and lifecycle functions.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;Filename: "Converter.java" --- Actual EJB remote class&lt;/span&gt;&lt;br /&gt;import javax.ejb.EJBObject;&lt;br /&gt;import java.rmi.RemoteException;&lt;br /&gt;import java.math.*;&lt;br /&gt;&lt;br /&gt;public interface Converter extends EJBObject {&lt;br /&gt;public BigDecimal dollarToYen(BigDecimal dollars) throws RemoteException;&lt;br /&gt;public BigDecimal yenToEuro(BigDecimal yen) throws RemoteException;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;Filename: "ConverterHome.java" --- Actual EJB Home class&lt;/span&gt;&lt;br /&gt;import java.rmi.RemoteException;&lt;br /&gt;import javax.ejb.CreateException;&lt;br /&gt;import javax.ejb.EJBHome;&lt;br /&gt;&lt;br /&gt;public interface ConverterHome extends EJBHome {&lt;br /&gt;Converter create() throws RemoteException, CreateException;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;Filename: "ConverterBean.java" --- Actual EJB class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;import java.rmi.RemoteException;&lt;br /&gt;import javax.ejb.SessionBean;&lt;br /&gt;import javax.ejb.SessionContext;&lt;br /&gt;import java.math.*;&lt;br /&gt;&lt;br /&gt;public class ConverterBean implements SessionBean {&lt;br /&gt;&lt;br /&gt;BigDecimal yenRate = new BigDecimal("121.6000");&lt;br /&gt;BigDecimal euroRate = new BigDecimal("0.0077");&lt;br /&gt;&lt;br /&gt;public BigDecimal dollarToYen(BigDecimal dollars) {&lt;br /&gt;BigDecimal result = dollars.multiply(yenRate);&lt;br /&gt;return result.setScale(2,BigDecimal.ROUND_UP);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public BigDecimal yenToEuro(BigDecimal yen) {&lt;br /&gt;BigDecimal result = yen.multiply(euroRate);&lt;br /&gt;return result.setScale(2,BigDecimal.ROUND_UP);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public ConverterBean() {}&lt;br /&gt;public void ejbCreate() {}&lt;br /&gt;public void ejbRemove() {}&lt;br /&gt;public void ejbActivate() {}&lt;br /&gt;public void ejbPassivate() {}&lt;br /&gt;public void setSessionContext(SessionContext sc) {}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;So, how do you accomplished the above to the Erlang equivalent? The toughest part is building a framework that will invoke the lifecycle methods like those ejbXXX as well as conformation to the specifications laid out by the &lt;a href="http://jcp.org/en/participation/committee"&gt;J2EE Community&lt;/a&gt; and i will skip that part, for now and hence, i will concentrate on the client-server part as well as hot code swapping. Below is my attempt at the above mentioned J2EE implementation.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;Filename: "callback.erl"&lt;/span&gt;&lt;br /&gt;-module(callback).&lt;br /&gt;-export([init/0, ejbActivate/0, ejbPassivate/0, ejbRemove/0, dollarToYen/1, yenToEuro/1, handle/2]).&lt;br /&gt;-import(container, [rpc/2]).&lt;br /&gt;&lt;br /&gt;%% client routines&lt;br /&gt;dollarToYen(Dollars) -&gt; rpc(ejbserver, {convertToYen, Dollars}).&lt;br /&gt;yenToEuro(Yen) -&gt; rpc(ejbserver, {convertToEuro, Yen}).&lt;br /&gt;ejbActivate() -&gt; rpc(ejbserver, {ejbactivate}).&lt;br /&gt;ejbPassivate() -&gt; rpc(ejbserver, {ejbpassivate}).&lt;br /&gt;ejbRemove() -&gt; rpc(ejbserver, {ejbremove}).&lt;br /&gt;&lt;br /&gt;%% callback routines&lt;br /&gt;init() -&gt; dict:new().&lt;br /&gt;&lt;br /&gt;handle({convertToYen, Dollars}, Dict) -&gt; { Dollars * 126, Dict};&lt;br /&gt;handle({ejbactivate}, Dict) -&gt; { ejbActivate , Dict};&lt;br /&gt;handle({ejbpassivate}, Dict) -&gt; { ejbPassivate , Dict};&lt;br /&gt;handle({ejbremove}, Dict) -&gt; { ejbRemove , Dict};&lt;br /&gt;handle({convertToEuro, Yen}, Dict) -&gt; {Yen * 0.0077, Dict}.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;Filename: "container.erl"&lt;/span&gt;&lt;br /&gt;-module(container).&lt;br /&gt;-export([start/2, rpc/2, swap_code/2]).&lt;br /&gt;&lt;br /&gt;start(Name, Mod) -&gt;&lt;br /&gt;register(Name, spawn(fun() -&gt; loop(Name, Mod, Mod:init()) end)).&lt;br /&gt;&lt;br /&gt;swap_code(Name,Mod) -&gt; rpc(Name, {swap_code, Mod}).&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;% Standard code for abstracting the "RPC-call" layer&lt;br /&gt;%&lt;br /&gt;rpc(Name, Request) -&gt;&lt;br /&gt;Name ! {self(), Request},&lt;br /&gt;receive&lt;br /&gt;{Name, Response} -&gt; Response&lt;br /&gt;end.&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;% Standard code for looping and waiting for messages from clients&lt;br /&gt;%&lt;br /&gt;loop(Name, Mod, OldState) -&gt;&lt;br /&gt;receive&lt;br /&gt;{From, {swap_code, NewCallbackMod}} -&gt;&lt;br /&gt;From ! {Name, ack},&lt;br /&gt;loop(Name, NewCallbackMod, OldState);&lt;br /&gt;{From, Request} -&gt;&lt;br /&gt;{Response, NewState} = Mod:handle(Request,OldState),&lt;br /&gt;From ! {Name, Response},&lt;br /&gt;loop(Name, Mod, NewState)&lt;br /&gt;end.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So how do you run it ? Refer to the figure below&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_n2HkB0XD3Kw/RxW3cSxo6bI/AAAAAAAAAkg/LFMpcOfQrec/s1600-h/simple_callback.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp0.blogger.com/_n2HkB0XD3Kw/RxW3cSxo6bI/AAAAAAAAAkg/LFMpcOfQrec/s320/simple_callback.png" alt="" id="BLOGGER_PHOTO_ID_5122201847908067762" border="0" /&gt;&lt;/a&gt;I shall briefly explain what i did,&lt;br /&gt;1/ compile the "server"&lt;br /&gt;2/ compile the "callback" a.k.a. EJB&lt;br /&gt;3/ start up the "server"&lt;br /&gt;4/ invoke the callback / EJB to run the interface functions&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So, the next thing is how do i do hot code swapping without bringing down the server? What you need to do first is to decide what your replacement code is going to be and swap it with the code that was just running. E.g. let's assume that i have decided to replace the callback.erl with another code callback2.erl and i want to replace the former with the latter.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;Filename: "callback2.erl"&lt;/span&gt;&lt;br /&gt;-module(callback2).&lt;br /&gt;-export([init/0, ejbActivate/0, ejbPassivate/0, ejbRemove/0, dollarToYenSpecial/1, yenToEuroSpecial/1, handle/2]).&lt;br /&gt;-import(container, [rpc/2]).&lt;br /&gt;&lt;br /&gt;%% client routines&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;dollarToYenSpecial(Dollars)&lt;/span&gt; -&gt; rpc(ejbserver, {convertToYen, Dollars}).&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;yenToEuroSpecial(Yen)&lt;/span&gt; -&gt; rpc(ejbserver, {convertToEuro, Yen}).&lt;br /&gt;ejbActivate() -&gt; rpc(ejbserver, {ejbactivate}).&lt;br /&gt;ejbPassivate() -&gt; rpc(ejbserver, {ejbpassivate}).&lt;br /&gt;ejbRemove() -&gt; rpc(ejbserver, {ejbremove}).&lt;br /&gt;&lt;br /&gt;%% callback routines&lt;br /&gt;init() -&gt; dict:new().&lt;br /&gt;&lt;br /&gt;handle({convertToYen, Dollars}, Dict) -&gt; &lt;span style="font-weight: bold;"&gt;{ Dollars * 126 * 126, Dict};&lt;/span&gt;&lt;br /&gt;handle({ejbactivate}, Dict) -&gt; { ejbActivate , Dict};&lt;br /&gt;handle({ejbpassivate}, Dict) -&gt; { ejbPassivate , Dict};&lt;br /&gt;handle({ejbremove}, Dict) -&gt; { ejbRemove , Dict};&lt;br /&gt;handle({convertToEuro, Yen}, Dict) -&gt; &lt;span style="font-weight: bold;"&gt;{Yen * 0.0077 * 0.0077, Dict}&lt;/span&gt;.&lt;br /&gt;&lt;/pre&gt;The changes are highlighted in bold for easy viewing. After, you need to compile it and swap it with the running code. &lt;span style="font-weight: bold;"&gt;Note&lt;/span&gt; that the &lt;span style="color: rgb(51, 102, 255);"&gt;Mod:init()&lt;/span&gt; does not run again. Refer to the figure below for a sample hot code swapping.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_n2HkB0XD3Kw/RxW5USxo6cI/AAAAAAAAAko/Wy6M5LNRDik/s1600-h/simple_callback_hotswap.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp0.blogger.com/_n2HkB0XD3Kw/RxW5USxo6cI/AAAAAAAAAko/Wy6M5LNRDik/s320/simple_callback_hotswap.png" alt="" id="BLOGGER_PHOTO_ID_5122203909492369858" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I hope this demonstrates how powerful Erlang can be and possibly a replacement language for Java and the like?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-7680935833099820478?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/7680935833099820478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=7680935833099820478&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/7680935833099820478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/7680935833099820478'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2007/10/erlang-hot-code-swapping.html' title='Erlang Hot Code Swapping'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_n2HkB0XD3Kw/RxW3cSxo6bI/AAAAAAAAAkg/LFMpcOfQrec/s72-c/simple_callback.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-2906721879964980658</id><published>2007-10-06T21:36:00.000-07:00</published><updated>2009-08-04T03:07:46.613-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sieve of Eratosthenes'/><category scheme='http://www.blogger.com/atom/ns#' term='Primes'/><title type='text'>Sieve of Eratosthenes</title><content type='html'>People whom studied computer science has heard of the "&lt;a href="http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes"&gt;Sieve of Eratosthenes&lt;/a&gt;" and i took the implementation in Erlang as an exercise and collected the run-times of the program to determine the number of primes less than 120, 1000, 10000, 100000 and 1000000.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Filename: "sieve.erl"&lt;/span&gt;&lt;br /&gt;-module(sieve).&lt;br /&gt;-export([findPrimes/1, genmulti/3, removeMultiples/3]).&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;% The following generates a list of multiples-of-Base&lt;br /&gt;% e.g. To generate multiples of 3 less than 100, enter "sieve:genmulti(0,3,100)"&lt;br /&gt;%      and you get [9,12,15,18|...]&lt;br /&gt;%&lt;br /&gt;genmulti(Index,Base,Limit) when (Base*Base+Index*Base) &gt; Limit -&gt; [];&lt;br /&gt;genmulti(Index,Base,Limit) when (Base*Base+Index*Base) =&lt;&gt; [Base*Base+Index*Base | genmulti(Index+1,Base,Limit) ].&lt;br /&gt;&lt;br /&gt;removeMultiples(Index, List, Limit) when Index /= erlang:length(List) -&gt;&lt;br /&gt;Head = lists:nth(Index,List),&lt;br /&gt;NewList = List -- genmulti(0,Head,Limit),&lt;br /&gt;removeMultiples(Index+1, NewList, Limit);&lt;br /&gt;removeMultiples(Index, List, _) when Index =:= erlang:length(List) -&gt; List.&lt;br /&gt;&lt;br /&gt;findPrimes(Num) -&gt; List = lists:seq(2,Num),&lt;br /&gt;statistics(runtime),&lt;br /&gt;statistics(wall_clock),&lt;br /&gt;       FinalList = removeMultiples(1, List, lists:max(List)),&lt;br /&gt;{_, Time1} = statistics(runtime),&lt;br /&gt;{_, Time2} = statistics(wall_clock),&lt;br /&gt;       io:format("Total discovered primes:~w~n", [erlang:length(FinalList)]),&lt;br /&gt;io:format("Runtime:~w(s) Wall-clock Time:~w(s)~n", [Time1/1000, Time2/1000]),&lt;br /&gt;       lists:foreach( fun(X) -&gt; io:format("~w, ", [X]) end, FinalList).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To run this, there are a few ways you can do this in Erlang but the most common is the following:&lt;br /&gt;1/ Copy-paste the code into a file of your choice, in my case its "sieve.erl"&lt;br /&gt;2/ Start a Erlang shell&lt;br /&gt;3/ Compile the program via "c(sieve)."&lt;br /&gt;4/ Execute the program via "sieve:findPrimes(120)" which is to find the number of primes numbers less than or equal to 120.&lt;br /&gt;&lt;br /&gt;My program will reveal how many primes have been discovered and the computation time it took and you can counter check the number of primes discovered against this site &lt;a href="http://primes.utm.edu/howmany.shtml"&gt;How Many Primes Are There?&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Finally, the run-times for discovering the number of primes less than 120, 1000, 10000, 100000 and 1000000 are displayed below.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sieve:findPrimes(&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;120&lt;/span&gt;).&lt;br /&gt;Total discovered primes:30&lt;br /&gt;Runtime:0.00000e+0(s) Wall-clock Time:0.00000e+0(s)&lt;br /&gt;&lt;br /&gt;sieve:findPrimes(&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;1000&lt;/span&gt;).&lt;br /&gt;Total discovered primes:168&lt;br /&gt;Runtime:1.00000e-2(s) Wall-clock Time:9.00000e-3(s)&lt;br /&gt;&lt;br /&gt;sieve:findPrimes(&lt;span style="color: rgb(51, 102, 255); font-weight: bold;"&gt;10000&lt;/span&gt;).&lt;br /&gt;Total discovered primes:1229&lt;br /&gt;Runtime:0.290000(s) Wall-clock Time:0.295000(s)&lt;br /&gt;&lt;br /&gt;sieve:findPrimes(&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;100000&lt;/span&gt;).&lt;br /&gt;Total discovered primes:9592&lt;br /&gt;Runtime:29.8900(s) Wall-clock Time:30.0060(s)&lt;br /&gt;&lt;br /&gt;sieve:findPrimes(&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;1000000&lt;/span&gt;).&lt;br /&gt;Total discovered primes:78498&lt;br /&gt;Runtime:3025.86(s) Wall-clock Time:3042.31(s)&lt;br /&gt;&lt;/pre&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-5323400-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-2906721879964980658?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/2906721879964980658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=2906721879964980658&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/2906721879964980658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/2906721879964980658'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2007/10/sieve-of-eratosthenes.html' title='Sieve of Eratosthenes'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-8697771508618865803</id><published>2007-10-05T08:04:00.000-07:00</published><updated>2009-08-11T17:56:18.712-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tcl/Tk'/><category scheme='http://www.blogger.com/atom/ns#' term='GS'/><title type='text'>Using the Graphical System a.k.a "gs" module in Erlang</title><content type='html'>In this article, i want to present some basic usage of the graphical system otherwise known as the Erlang module "&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;gs&lt;/span&gt;". The pre-requisites is the requirement for &lt;a href="http://www.tcl.tk/software/tcltk/"&gt;Tcl/Tk&lt;/a&gt; to be installed on your Linux system, otherwise you will get the error "&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;{error,backend_died}&lt;/span&gt;" when you invoke the "&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;gs:start()&lt;/span&gt;" and lastly include the path to your linux user so that Erlang can locate the "tk".&lt;br /&gt;&lt;br /&gt;I have a contrived example of a simple Erlang GUI&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;-module(simple_window).&lt;br /&gt;-export([start/0]).&lt;br /&gt;&lt;br /&gt;start() -&gt;&lt;br /&gt;Id = gs:start(),&lt;br /&gt;Win = gs:create(window, Id, [{width, 200}, {height, 100}],&lt;br /&gt;Butt = gs:create(button, Win, [{label, {text, "Press Me"}}, {x, 0}]),&lt;br /&gt;Butt2 = gs:create(button, Win, [{label, {text, "Stop"}}, {x, 100}]),&lt;br /&gt;gs:config(Win, {map, true}),&lt;br /&gt;loop(Butt, Butt2, Win).&lt;br /&gt;&lt;br /&gt;loop(Butt, Butt2, Win) -&gt;&lt;br /&gt;receive&lt;br /&gt;  {gs, Butt, click, Data, Args} -&gt;&lt;br /&gt;    io:format("Hello There~n", []),&lt;br /&gt;    loop(Butt);&lt;br /&gt;  {gs, Butt2, click, Data, Args} -&gt;&lt;br /&gt;    gs:destroy(Win)&lt;br /&gt;end.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;What just happened is this&lt;br /&gt;&lt;ol&gt;&lt;li&gt;A graphics server was created via the "&lt;span style="font-weight: bold; color: rgb(51, 102, 255);"&gt;gs:start()&lt;/span&gt;"&lt;/li&gt;&lt;li&gt;A window was created with the defined &lt;span style="font-style: italic; color: rgb(51, 102, 255);"&gt;width&lt;/span&gt; and &lt;span style="font-style: italic; color: rgb(51, 102, 255);"&gt;height&lt;/span&gt; &lt;/li&gt;&lt;li&gt;A button was created inside the window with a text&lt;/li&gt;&lt;li&gt;A event-loop was created that will receive the GUI-events from the user&lt;/li&gt;&lt;/ol&gt;That's about the amount of effort u need to create a simple GUI window. The figure shows a screenshot&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_n2HkB0XD3Kw/RwdcXyxo6aI/AAAAAAAAAkA/P9Sy9hM2_m0/s1600-h/simple_window_erlang.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp0.blogger.com/_n2HkB0XD3Kw/RwdcXyxo6aI/AAAAAAAAAkA/P9Sy9hM2_m0/s320/simple_window_erlang.png" alt="" id="BLOGGER_PHOTO_ID_5118161065366579618" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;From the screenshot, if you keep hitting the button "Press Me" then the Erlang shell will display "Hello There" and if you hit the button "Stop" then the window will close cleanly&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-5323400-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-8697771508618865803?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/8697771508618865803/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=8697771508618865803&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/8697771508618865803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/8697771508618865803'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2007/10/using-graphical-system-aka-gs-module-in.html' title='Using the Graphical System a.k.a &quot;gs&quot; module in Erlang'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_n2HkB0XD3Kw/RwdcXyxo6aI/AAAAAAAAAkA/P9Sy9hM2_m0/s72-c/simple_window_erlang.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-141187717606945224</id><published>2007-09-29T06:28:00.000-07:00</published><updated>2009-08-04T03:08:14.403-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Java Thread'/><category scheme='http://www.blogger.com/atom/ns#' term='Concurrent'/><title type='text'>Erlang/Java Performance in Concurrency</title><content type='html'>I've been learning Erlang for 1 week now and i discover its a nice language for programming. This language is definitely different from C, C++ and Java.&lt;br /&gt;&lt;br /&gt;In this post, i shall boldly compare the difference in runtimes for Erlang and Java w.r.t. concurrency.&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://www.erlang.org/"&gt;Erlang&lt;/a&gt;, I created a file &lt;span style="COLOR: rgb(102,51,255)"&gt;ring.erl&lt;/span&gt; which contains the following code&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;-module(ring).&lt;br /&gt;-export([start/2, for/3, loop/0]).&lt;br /&gt;&lt;br /&gt;-ifndef(debug).&lt;br /&gt;-define(TRACE(X), io:format("~p:~p ~p~n", [?MODULE, ?FILE, X])).&lt;br /&gt;-else.&lt;br /&gt;-define(TRACE(X), void).&lt;br /&gt;-endif.&lt;br /&gt;&lt;br /&gt;for(N, N, F) -&gt; F();&lt;br /&gt;for(I, N, F) -&gt; F(),for(I+1, N,F).&lt;br /&gt;&lt;br /&gt;%&lt;br /&gt;% Create N processes and send a message M times&lt;br /&gt;% to each process. Therefore, we should generate N * M&lt;br /&gt;% messages.&lt;br /&gt;%&lt;br /&gt;&lt;br /&gt;loop() -&gt;&lt;br /&gt;   receive&lt;br /&gt;           {msg, Pid} -&gt; Pid, loop()&lt;br /&gt;   after 5000 -&gt;&lt;br /&gt;           done&lt;br /&gt;   end.&lt;br /&gt;&lt;br /&gt;start(N, M) -&gt;&lt;br /&gt;   statistics(runtime),&lt;br /&gt;   statistics(wall_clock),&lt;br /&gt;   ring:for(1, N, fun() -&gt; Pid = spawn(ring, loop, []), ring:for(1, M, fun() -&gt; Pid ! {msg, Pid} end) end),&lt;br /&gt;   {_, Time1} = statistics(runtime),&lt;br /&gt;   {_, Time2} = statistics(wall_clock),&lt;br /&gt;   io:format("Runtime:~p, Walltime:~p~n", [Time1, Time2]).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In Java, I used &lt;a href="http://www.netbeans.org/"&gt;Netbeans 5.5.1&lt;/a&gt; (&lt;a href="http://www.java.sun.com/"&gt;JDK 1.5.0_12&lt;/a&gt;) to develop the following simple multi-threaded Java code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package simplemultithread;&lt;br /&gt;&lt;br /&gt;public class Main {&lt;br /&gt;&lt;br /&gt;/** Creates a new instance of Main */&lt;br /&gt;public Main() {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * @param args the command line arguments&lt;br /&gt; */&lt;br /&gt;public static void main(String[] args) {&lt;br /&gt;    // TODO code application logic here&lt;br /&gt;    long startTime = System.currentTimeMillis();&lt;br /&gt;    if ( args.length != 2 ) {&lt;br /&gt;        System.err.println("usage: java Main &amp;lt;Number of threads&amp;gt; &amp;lt;Number of msg to send to each thread&amp;gt;");&lt;br /&gt;        System.exit(-1);&lt;br /&gt;    }&lt;br /&gt;    int numOfThreads = Integer.parseInt(args[0]);&lt;br /&gt;    final int numOfMsgsPerThread = Integer.parseInt(args[1]);&lt;br /&gt;    Thread threads[] = new Thread[numOfThreads];&lt;br /&gt;&lt;br /&gt;    for( int i = 0; i &amp;lt; numOfThreads; i++ ) {&lt;br /&gt;        threads[i] = new Thread() {&lt;br /&gt;            private int msgsToProcess = numOfMsgsPerThread;&lt;br /&gt;            public void run() {&lt;br /&gt;                for( int i = 0, j = 0; i &amp;lt; msgsToProcess; i++ ) {&lt;br /&gt;                    // do something simple&lt;br /&gt;                    j++;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        };&lt;br /&gt;        try { threads[i].join();} catch (InterruptedException ie) {}&lt;br /&gt;    }&lt;br /&gt;    for( int i = 0; i &amp;lt; numOfThreads; i++ ) {&lt;br /&gt;        threads[i].start();&lt;br /&gt;    }&lt;br /&gt;    long endTime = System.currentTimeMillis();&lt;br /&gt;    System.out.println("Total time:" + (endTime - startTime)/1000.00 + "seconds");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And the performance difference is quite remarkable after comparing the runtimes of both programs which perform almost the same thing i.e. start N processes/threads and each process executes its action M-times.&lt;br /&gt;&lt;br /&gt;In my tests, i used a Compaq notebook Intel-M 2.4 Ghz with 512 MB RAM running SUSE Linux 9.3 Professional Operating System.&lt;br /&gt;&lt;br /&gt;The figure on the left is the runtime, in milliseconds, of the Erlang code above and that on the right is that of the Java code. From the figures, you can see that Erlang runs better than Java in order of approximately 2-3 times!&lt;br /&gt;&lt;br /&gt;How does Erlang do it? The best way to understand it is to see this &lt;a href="http://www.defmacro.org/ramblings/concurrency.html"&gt;article&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_n2HkB0XD3Kw/Rv5wpCxo6YI/AAAAAAAAAjY/saSl-LnZVRQ/s1600-h/ErlangMultiProcessPerf.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5115650077161482626" style="FLOAT: left; MARGIN: 0pt 10px 10px 0pt; CURSOR: pointer" alt="" src="http://bp0.blogger.com/_n2HkB0XD3Kw/Rv5wpCxo6YI/AAAAAAAAAjY/saSl-LnZVRQ/s320/ErlangMultiProcessPerf.png" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_n2HkB0XD3Kw/Rv5zESxo6ZI/AAAAAAAAAjg/Q0xnt8cjAak/s1600-h/JavaMultiThreadPerf.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5115652744336173458" style="FLOAT: left; MARGIN: 0pt 10px 10px 0pt; CURSOR: pointer" alt="" src="http://bp1.blogger.com/_n2HkB0XD3Kw/Rv5zESxo6ZI/AAAAAAAAAjg/Q0xnt8cjAak/s320/JavaMultiThreadPerf.png" border="0" /&gt;&lt;/a&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-5323400-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-141187717606945224?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/141187717606945224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=141187717606945224&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/141187717606945224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/141187717606945224'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2007/09/erlangjava-performance-in-concurrency.html' title='Erlang/Java Performance in Concurrency'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_n2HkB0XD3Kw/Rv5wpCxo6YI/AAAAAAAAAjY/saSl-LnZVRQ/s72-c/ErlangMultiProcessPerf.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-4538519212211136412</id><published>2007-09-26T21:57:00.000-07:00</published><updated>2009-08-04T03:08:36.709-07:00</updated><title type='text'>Understand your implementation by "tracing" the execution</title><content type='html'>In my previous post, i used Erlang to implement 2 simple algorithms when run, produced the desired results which i am pleased. But, upon reflection i found that i need to better my understanding of how Erlang executes the function i knew i needed to trace it.&lt;br /&gt;&lt;br /&gt;Therefore, how do you add "debug/trace" feature into your own implementations ?&lt;br /&gt;&lt;br /&gt;What i did is:&lt;br /&gt;&lt;br /&gt;1/ Create a macro named "TRACE"&lt;br /&gt;2/ Compiled the code using the "c"-command with an extra argument&lt;br /&gt;3/ Ran the compiled code to view it, and voila! its done.&lt;br /&gt;&lt;br /&gt;Below is an illustration of how i did it:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;%&lt;br /&gt;% Create a Erlang macro and include it in your *.erl file&lt;br /&gt;%&lt;br /&gt;-ifdef(debug).&lt;br /&gt;-define(TRACE(X), io:format("TRACE ~p:~p ~p~n", [?MODULE, ?LINE, X])).&lt;br /&gt;-else.&lt;br /&gt;-define(TRACE(X), void).&lt;br /&gt;-endif.&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;%&lt;br /&gt;% N-th Permutation&lt;br /&gt;% Note: the code in "bold" is an expansion of the newly created macro "TRACE"&lt;br /&gt;%&lt;br /&gt;perms([]) -&gt; [[]];&lt;br /&gt;perms(L) -&gt; &lt;span style="font-weight: bold;"&gt;?TRACE(L)&lt;/span&gt;, [[H|T] || H &lt;- L, T &lt;- perms(L--[H])]. ... ... &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, once you have done this naturally you would save the file and next you start up the Erlang shell and compile the file as illustrated in the screenshot below, afterwhich you run it!&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_n2HkB0XD3Kw/Rvs6vCxo6XI/AAAAAAAAAjQ/pnhxCUBUsV8/s1600-h/Erlang-startupshell-withdebug.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp1.blogger.com/_n2HkB0XD3Kw/Rvs6vCxo6XI/AAAAAAAAAjQ/pnhxCUBUsV8/s320/Erlang-startupshell-withdebug.png" alt="" id="BLOGGER_PHOTO_ID_5114746381682665842" border="0" /&gt;&lt;/a&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-5323400-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-4538519212211136412?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/4538519212211136412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=4538519212211136412&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/4538519212211136412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/4538519212211136412'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2007/09/understand-your-implementation-by.html' title='Understand your implementation by &quot;tracing&quot; the execution'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_n2HkB0XD3Kw/Rvs6vCxo6XI/AAAAAAAAAjQ/pnhxCUBUsV8/s72-c/Erlang-startupshell-withdebug.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-7718933802380540493</id><published>2007-09-21T03:05:00.000-07:00</published><updated>2009-08-04T03:08:25.864-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Factorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Fibonacci'/><title type='text'>Implementing Algorithms (Part 1)</title><content type='html'>I just started learning this language which belongs to a class of languages known as &lt;span style="font-style: italic;"&gt;Functional Language&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;For starters, I am going to demonstrate some simple stuff.&lt;br /&gt;&lt;br /&gt;1/ Calculate &lt;span style="font-style: italic;"&gt;Factorial&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;%&lt;br /&gt;% Algorithm to calculate the Nth Factorial&lt;br /&gt;%&lt;br /&gt;-module(fac).&lt;br /&gt;-export([factorial/1]).&lt;br /&gt;&lt;br /&gt;factorial(0) -&gt; 1;&lt;br /&gt;factorial(1) -&gt; 1;&lt;br /&gt;factorial(N) when N &gt; 0 -&gt; N * factorial(N-1).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;2/ Calculate &lt;span style="font-style: italic;"&gt;N-th Fibonacci Sequence&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;%&lt;br /&gt;% Algorithm to calculate the sum of Nth Fibonacci Sequence&lt;br /&gt;%&lt;br /&gt;-module(fib).&lt;br /&gt;-export([fibonacci/1]).&lt;br /&gt;&lt;br /&gt;fibonacci(0) -&gt; 0;&lt;br /&gt;fibonacci(1) -&gt; 1;&lt;br /&gt;fibonacci(N) when N &gt; 1 -&gt; fibonacci(N-1) + fibonacci(N-2).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In order to run the above scripts, do the following&lt;br /&gt;&lt;br /&gt;a) Create a file call fac.erl or fib.erl (&lt;span style="font-weight: bold;"&gt;Note:&lt;/span&gt; name of file must be the same as the string given in the "&lt;span style="font-weight: bold;"&gt;-module&lt;/span&gt;")&lt;br /&gt;b) Copy and paste the respective code into the respective file&lt;br /&gt;c) Start up the Erlang Shell and type the following (Note the period character '.'):&lt;br /&gt;c.1) &lt;span style="font-style: italic; color: rgb(102, 51, 255);"&gt;c(fib).&lt;/span&gt;&lt;br /&gt;c.2) &lt;span style="color: rgb(102, 51, 255);"&gt;c(fac).&lt;/span&gt;&lt;br /&gt;If your compilation was successful, you should have the following screen&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_n2HkB0XD3Kw/RvPb7Cxo6WI/AAAAAAAAAjI/A68ngnilaDY/s1600-h/Erlang_startupshell.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp1.blogger.com/_n2HkB0XD3Kw/RvPb7Cxo6WI/AAAAAAAAAjI/A68ngnilaDY/s320/Erlang_startupshell.png" alt="" id="BLOGGER_PHOTO_ID_5112671809399482722" border="0" /&gt;&lt;/a&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-5323400-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-7718933802380540493?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/7718933802380540493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=7718933802380540493&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/7718933802380540493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/7718933802380540493'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2007/09/implementing-algorithms-part-1.html' title='Implementing Algorithms (Part 1)'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_n2HkB0XD3Kw/RvPb7Cxo6WI/AAAAAAAAAjI/A68ngnilaDY/s72-c/Erlang_startupshell.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3408400997537705779.post-6751389612701932992</id><published>2007-09-19T17:59:00.000-07:00</published><updated>2009-08-04T03:08:44.163-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Concurrent'/><category scheme='http://www.blogger.com/atom/ns#' term='Parallel'/><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><title type='text'>What is Erlang and what is its role going to be ?</title><content type='html'>I borrowed the following quote from the book &lt;a href="http://www.amazon.com/Programming-Erlang-Software-Concurrent-World/dp/193435600X/ref=pd_bbs_sr_1/002-1588129-0618438?ie=UTF8&amp;amp;s=books&amp;amp;qid=1190250470&amp;amp;sr=8-1"&gt;Programming Erlang&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;For years we have relied on processors getting faster and faster. That trend is ending. Instead, we now have multicore  processors - 2, 4 or more processors running in parallel. The problem is, unless your program can execute in parallel, it will use only one of these cores at a time.&lt;br /&gt;&lt;br /&gt;The Erlang programming language lets you build highly parallel, distributed, fault-tolerant systems - systems that can exploit these new architectures. It has been used commercially for many years to create massive fault tolerant and highly reliable systems.&lt;br /&gt;&lt;br /&gt;Erlang programs run seamlessly on multicore computers with no extra code on your part. Erlang combines ideas from the world of functional programming with techniques for building fault-tolerant systems. The result is a powerful language that makes it much easier to build the massively parallel networked applications of the future.&lt;/blockquote&gt;Therefore, in the coming blogs i am going to write stuff about Erlang and programming in it, in general.&lt;br /&gt;&lt;br /&gt;For a brief introduction to the language features, follow this &lt;a href="http://www.erlang.org/white_paper.html"&gt;article.&lt;/a&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");&lt;br /&gt;document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;try {&lt;br /&gt;var pageTracker = _gat._getTracker("UA-5323400-2");&lt;br /&gt;pageTracker._trackPageview();&lt;br /&gt;} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3408400997537705779-6751389612701932992?l=erlangraymondtay.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://erlangraymondtay.blogspot.com/feeds/6751389612701932992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3408400997537705779&amp;postID=6751389612701932992&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/6751389612701932992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3408400997537705779/posts/default/6751389612701932992'/><link rel='alternate' type='text/html' href='http://erlangraymondtay.blogspot.com/2007/09/what-is-erlang-and-what-is-its-role.html' title='What is Erlang and what is its role going to be ?'/><author><name>Raymond Tay</name><uri>https://profiles.google.com/110897033209560123249</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-4ZP-rPmLNSw/AAAAAAAAAAI/AAAAAAAABao/8f4AuUXNrno/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry></feed>
