<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Full of BS &#187; Erlang</title>
	<atom:link href="http://fullof.bs/category/programming/erlang/feed/" rel="self" type="application/rss+xml" />
	<link>http://fullof.bs</link>
	<description>He just never stops talking</description>
	<lastBuildDate>Mon, 19 Oct 2009 15:08:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Erlang jokes are too rare</title>
		<link>http://fullof.bs/erlang-jokes-are-too-rare/</link>
		<comments>http://fullof.bs/erlang-jokes-are-too-rare/#comments</comments>
		<pubDate>Fri, 08 May 2009 22:23:04 +0000</pubDate>
		<dc:creator>John Haugeland</dc:creator>
				<category><![CDATA[Erlang]]></category>
		<category><![CDATA[General Interest]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[munctional]]></category>
		<category><![CDATA[parallelism]]></category>

		<guid isPermaLink="false">http://fullof.bs/?p=500</guid>
		<description><![CDATA[But this one&#8217;s funny.
Munctional
]]></description>
			<content:encoded><![CDATA[<p>But this one&#8217;s funny.</p>
<p><a href="http://www.youtube.com/watch?v=1yH_j8-VVLo">Munctional</a></p>
]]></content:encoded>
			<wfw:commentRss>http://fullof.bs/erlang-jokes-are-too-rare/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reminders are nice</title>
		<link>http://fullof.bs/reminders-are-nice/</link>
		<comments>http://fullof.bs/reminders-are-nice/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 01:49:35 +0000</pubDate>
		<dc:creator>John Haugeland</dc:creator>
				<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://fullof.bs/?p=493</guid>
		<description><![CDATA[Always nice when someone lets you know, y&#8217;know?
[19:43] &#60;apples&#62; by the way StoneCypher, if you're curious, the level
          of functionality provided by my SMTP server in C, which is
          ~1000 lines, i trimmed down to less than [...]]]></description>
			<content:encoded><![CDATA[<p>Always nice when someone lets you know, y&#8217;know?</p>
<pre>[19:43] &lt;apples&gt; by the way StoneCypher, if you're curious, the level
          of functionality provided by my SMTP server in C, which is
          ~1000 lines, i trimmed down to less than 100 in erlang :p
[19:45] &lt;StoneCypher&gt; lel
[19:45] &lt;StoneCypher&gt; and i bet it's less buggy now too
[19:45] &lt;apples&gt; quite
[19:46] &lt;apples&gt; oh, and i wrote it in an hour
[19:46] &lt;StoneCypher&gt; awesome
[19:46] &lt;StoneCypher&gt; can i post that quote on my blog?
[19:46] &lt;apples&gt; sure thing</pre>
<p>Helps one remember one&#8217;s doing the right thing to push people to learn new things.</p>
]]></content:encoded>
			<wfw:commentRss>http://fullof.bs/reminders-are-nice/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Better Erlang TCP listening pattern: addressing the fast packet loss problem</title>
		<link>http://fullof.bs/a-better-erlang-tcp-listening-pattern-addressingthe-fast-packet-loss-problem/</link>
		<comments>http://fullof.bs/a-better-erlang-tcp-listening-pattern-addressingthe-fast-packet-loss-problem/#comments</comments>
		<pubDate>Thu, 01 Jan 2009 03:04:59 +0000</pubDate>
		<dc:creator>John Haugeland</dc:creator>
				<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tools and Libraries]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[accept]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[defect]]></category>
		<category><![CDATA[erlang server]]></category>
		<category><![CDATA[fast packet loss problem]]></category>
		<category><![CDATA[fast packet problem]]></category>
		<category><![CDATA[gen_tcp]]></category>
		<category><![CDATA[idiom]]></category>
		<category><![CDATA[idiomatic]]></category>
		<category><![CDATA[listen]]></category>
		<category><![CDATA[listen loop]]></category>
		<category><![CDATA[listener]]></category>
		<category><![CDATA[listener loop]]></category>
		<category><![CDATA[listener pattern]]></category>
		<category><![CDATA[network server]]></category>
		<category><![CDATA[pattern]]></category>
		<category><![CDATA[scutil]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[server listen]]></category>
		<category><![CDATA[server listener]]></category>
		<category><![CDATA[tcp server]]></category>

		<guid isPermaLink="false">http://fullof.bs/?p=466</guid>
		<description><![CDATA[[digg-reddit-me]I&#8217;ve had mixed reactions to this when I&#8217;ve discussed it with people on IRC.  This may be well known to oldbear Erlang programmers.  I suppose it&#8217;s also possible that I&#8217;m wrong, though I&#8217;ve talked to several people I respect, and more than one of them have suggested that they were already aware of this problem.  [...]]]></description>
			<content:encoded><![CDATA[<p>[digg-reddit-me]I&#8217;ve had mixed reactions to this when I&#8217;ve discussed it with people on IRC.  This may be well known to oldbear Erlang programmers.  I suppose it&#8217;s also possible that I&#8217;m wrong, though I&#8217;ve talked to several people I respect, and more than one of them have suggested that they were already aware of this problem.  If I&#8217;m wrong, please let me know; I&#8217;m open to the possibility that there&#8217;s a better answer that I just don&#8217;t know about.  <span style="text-decoration: line-through">I&#8217;ve never seen it discussed on the web, at least.</span> <span style="color: #ff9900">Update: Serge Aleynikov points out that</span> <a title="TCP Server, OTP Principles" href="http://trapexit.org/Building_a_Non-blocking_TCP_server_using_OTP_principles" target="_blank">this TrapExit tutorial</a> <span style="color: #ff9900">documents this approach.</span></p>
<p>I think this is probably real.</p>
<p>I believe there is a significant defect in the idiomatic listener pattern as discussed by most Erlang websites and as provided by most Erlang example code, and which is found in many Erlang applications.  This defect is relatively easily repaired once noticed without significant impact on surrounding code, and I have added functionality to my <a title="The ScUtil Library" href="http://scutil.com/" target="_blank">ScUtil Library</a> to handle this automatically under the name <tt><a title="standard_listener documentation" href="http://scutil.com/docs/#standard_listener-3" target="_blank">standard_listener</a></tt>.</p>
<p>The fundamental problem is essentially a form of race condition.  The idiomatic listener is, roughly:</p>
<blockquote>
<pre><span style="color: #008000"><strong>do_listen(Port, Opts, Handler) -&gt;

    case gen_tcp:listen(Port, Opts) of

        { ok, ListeningSocket } -&gt;
            listen_loop(ListeningSocket, Handler);

        { error, E } -&gt;
            { error, E }

    end.

listen_loop(ListeningSocket, Handler) -&gt;

    case gen_tcp:accept(ListeningSocket) of

        { ok, ConnectedSocket } -&gt;
            spawn(node(), Handler, [ConnectedSocket]),
            listen_loop(ListeningSocket);

        { error, E } -&gt;
            { error, E }

    end.
</strong></span></pre>
</blockquote>
<p>Now consider the case of a server under very heavy load.  Further, consider that the listening socket is opened either <span style="color: #008000"><tt>{active,true}</tt></span> or <span style="color: #008000"><tt>{active,once}</tt></span>, which is true in the vast bulk of Erlang network applications, meaning that packets are delivered automatically to the socket owner.  The general pattern is that the listening socket accepts a connection, spawns a handling process, passes the connected socket to that handling process, and the handling process takes ownership of the socket.</p>
<p>The problem is that it takes time for that all to happen, and Erlang doesn&#8217;t specify or allow you to control its timeslicing behavior (as well it should not).  As active sockets are managed by a standalone process, this means that if the connecting client is fast and the network is fast, the first packet (even the first several under extreme circumstances) could be delivered before the socket has been taken over by the handling PID, meaning that its contents would be dispatched to the wrong process, with no indication of where they were meant to go.  This invalidates connections and fills a non-discarding mailbox, which is a potentially serious memory leak (especially given that erlang&#8217;s response to out of memory conditions is to abort an entire VM.)</p>
<p>Obviously, this is intolerable.  There are better answers, though, than to switch to <span style="color: #008000"><tt>{active,false}</tt></span>.  One suggestion I heard was to pre-spawn handlers in order to reduce the gap time, but that doesn&#8217;t solve the problem, it just makes it less likely.</p>
<p>The approach that I took is to lie.  <span style="color: #008000"><tt>standard_listener </tt></span>takes the following steps to resolve the problem:</p>
<ol>
<li>Add the default <span style="color: #008000"><tt>{active,true}</tt></span> to the inet options list, if it isn&#8217;t already present.</li>
<li>Strip out the <span style="color: #008000"><tt>{active,Foo}</tt></span> from the inet options list, and store it as <span style="color: #008000"><tt>ActiveStatus</tt></span>.</li>
<li>Add <span style="color: #008000"><tt>{active,false}</tt></span> to the inet options list, and use that options list to open the listener.</li>
<li>When spawning handler processes, pass a shunt as the starting function, taking the real handling function and the real <span style="color: #008000"><tt>ActiveStatus</tt></span> as arguments</li>
<li>The shunt sets the real <span style="color: #008000"><tt>ActiveStatus</tt></span> from inside the handler process, at which point the socket begins delivering messages</li>
</ol>
<p>This neatly closes the problem.  A free, MIT license implementation can be found in <a title="The ScUtil Library" href="http://scutil.com/" target="_blank">ScUtil</a> beginning in version 96.  A simplified, corrected example follows for immediate reference; the thing in ScUtil is more feature complete.</p>
<blockquote>
<pre><span><strong><span style="color: #008000"><strong>do_listen(Port, Opts) -&gt;

    ActiveStatus = case proplists:get_value(active, SocketOptions) of
        undefined -&gt; true;
        Other     -&gt; Other
    end,

    FixedOpts = proplists:delete(active, SocketOptions)
             ++ [{active, false}],

    case gen_tcp:listen(Port, FixedOpts) of

        { ok, ListeningSocket } -&gt;
            listen_loop(ActiveStatus, ListeningSocket);

        { error, E } -&gt;
            { error, E }

    end.

listen_loop(</strong></span></strong></span><span><strong><span><strong><span><strong><span style="color: #008000"><strong>ActiveStatus, </strong></span></strong></span></strong></span></strong></span><span><strong><span style="color: #008000"><strong>ListeningSocket, Handler) -&gt;

    case gen_tcp:accept(ListeningSocket) of

        { ok, ConnectedSocket } -&gt;
            spawn(?MODULE, shunt, [ActiveStatus,ConnectedSocket,</strong></span></strong></span><span><strong><span><strong><span><strong><span style="color: #008000"><strong>Handler</strong></span></strong></span></strong></span></strong></span><span><strong><span style="color: #008000"><strong>]),
            listen_loop(</strong></span></strong></span><span><strong><span><strong><span><strong><span style="color: #008000"><strong>ActiveStatus, </strong></span></strong></span></strong></span></strong></span><span><strong><span style="color: #008000"><strong>ListeningSocket, Handler</strong></span></strong></span><span><strong><span style="color: #008000"><strong>);

        { error, E } -&gt;
            { error, E }

    end.

shunt(ActiveStatus, ConnectedSocket, Handler) -&gt;

</strong></span></strong></span><span><strong><span style="color: #008000"><strong>    controlling_process(ConnectedSocket, self()),
    inet:setopts(ConnectedSocket, [{active, ActiveStatus}]),
    Handler(ConnectedSocket).</strong></span></strong></span></pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://fullof.bs/a-better-erlang-tcp-listening-pattern-addressingthe-fast-packet-loss-problem/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Making significant strides towards documenting ScUtil</title>
		<link>http://fullof.bs/making-significant-strides-towards-documenting-scutil/</link>
		<comments>http://fullof.bs/making-significant-strides-towards-documenting-scutil/#comments</comments>
		<pubDate>Sun, 07 Dec 2008 19:37:37 +0000</pubDate>
		<dc:creator>John Haugeland</dc:creator>
				<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tools and Libraries]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[documentation]]></category>
		<category><![CDATA[erlang example code]]></category>
		<category><![CDATA[example code]]></category>
		<category><![CDATA[examples]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[mit license]]></category>
		<category><![CDATA[scutil]]></category>
		<category><![CDATA[scutil documentation]]></category>

		<guid isPermaLink="false">http://fullof.bs/?p=448</guid>
		<description><![CDATA[[digg-reddit-me]My erlang library ScUtil has been public at the ScUtil page for some time now.  Recently, I&#8217;ve been working on documenting it.  It&#8217;s about half documented in its current state.
Here&#8217;s the prototype ScUtil documentation.  I&#8217;m open to commentary.
]]></description>
			<content:encoded><![CDATA[<p>[digg-reddit-me]My erlang library ScUtil has been public at <a title="StoneCypher's Utility Library" href="http://scutil.com/" target="_blank">the ScUtil page</a> for some time now.  Recently, I&#8217;ve been working on documenting it.  It&#8217;s about half documented in its current state.</p>
<p>Here&#8217;s the <a title="Prototype ScUtil Documentation" href="http://sc.tri-bit.com/outgoing/scutil.html" target="_blank">prototype ScUtil documentation</a>.  I&#8217;m open to commentary.</p>
]]></content:encoded>
			<wfw:commentRss>http://fullof.bs/making-significant-strides-towards-documenting-scutil/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Prototype: EEP18 Considered Harmful: The problems with Erlang to JSON term translation</title>
		<link>http://fullof.bs/prototype-eep-18-considered-harmful-the-problems-with-erlang-to-json-term-translation/</link>
		<comments>http://fullof.bs/prototype-eep-18-considered-harmful-the-problems-with-erlang-to-json-term-translation/#comments</comments>
		<pubDate>Sat, 06 Dec 2008 20:40:26 +0000</pubDate>
		<dc:creator>John Haugeland</dc:creator>
				<category><![CDATA[ECMA / Javascript]]></category>
		<category><![CDATA[ECMAScript]]></category>
		<category><![CDATA[Erlang]]></category>
		<category><![CDATA[General Interest]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rants]]></category>
		<category><![CDATA[Tools and Libraries]]></category>
		<category><![CDATA[Web and Web Standards]]></category>
		<category><![CDATA[bif]]></category>
		<category><![CDATA[conversion]]></category>
		<category><![CDATA[convert]]></category>
		<category><![CDATA[eep]]></category>
		<category><![CDATA[eep 18]]></category>
		<category><![CDATA[eep18]]></category>
		<category><![CDATA[eeps]]></category>
		<category><![CDATA[erlang enhancement proposal 18]]></category>
		<category><![CDATA[javascript object notation]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[json bif]]></category>

		<guid isPermaLink="false">http://fullof.bs/?p=402</guid>
		<description><![CDATA[THIS IS ONLY HALF WRITTEN.  I have been sitting on this post, waiting for the mood to finish it, for months; because EEP18 is now being treated as a likely implement, I am immediately publishing the half-written version, because it exposes many (though not all) of the serious, irreconcilable problems with EEP18.
On the mailing list, [...]]]></description>
			<content:encoded><![CDATA[<p><span style="color: #ff0000"><em><strong>THIS IS ONLY HALF WRITTEN.  I have been sitting on this post, waiting for the mood to finish it, for months; because EEP18 is now being treated as a likely implement, I am immediately publishing the half-written version, because it exposes many (though not all) of the serious, irreconcilable problems with EEP18.</strong></em></span></p>
<p>On the mailing list, people are actively trying to bring Erlang up to snuff with regards to web standards.  One of the more unfortunate choices being discussed is JSON as a data notation.  JSON, unfortunately, does not actually map to Erlang in a useful way.  Joe Armstrong has gone as far as to suggest BIFs, which are decidedly unrealistic as well as unnecessary.  My goal is to create a JSON handling library.  However, the mailing list is beginning to put momentum behind an alternative proposal which is currently presented in BIF form.</p>
<p>This post explains why my approach is different.  Many of the issues herein are discussed by <a title="Richard O'Keefe's EEP18, JSON BIFs" href="http://www.erlang.org/eeps/eep-0018.html" target="_blank">the tabled EEP</a> (EEP 18, &#8220;JSON BIFs&#8221; by Rickard O&#8217;Keefe), but some are not, and some of these issues are accepted when I believe they should not be.  <span style="text-decoration: underline"><strong>It is my position that EEP 18 is unacceptably dangerous</strong></span>.  I will explain why.</p>
<p><span id="more-402"></span></p>
<p>This paper assumes you are familiar with Erlang and with fundamental containers (the list, the array and the key/value map).  It is very helpful, but not required, to be familiar with JSON, or JavaScript or any ECMA derived language such as ActionScript.</p>
<h1>Premise</h1>
<p>There&#8217;s a movement starting to use Erlang for web work.  There are several stumbling blocks to that end.  Among them are a simple primary webserver, a simple primary unicode system and a simple primary JSON manager.</p>
<p>The webserver problem is mostly solved: there&#8217;s the httpd module, there&#8217;s yaws, there&#8217;s mochiweb, there&#8217;s the currently unavailable work at Tobbe&#8217;s Red Hot Erlang Blog, there&#8217;s even Joe&#8217;s HTTPD tutorial.  YAWS and MochiWeb in particular get a lot of action these days.  The situation isn&#8217;t amazingly straightforward, but it&#8217;s fairly straightforward; we&#8217;re in &#8220;Good Enough&#8221; territory.  (I&#8217;m building another webserver that behaves like factor&#8217;s drop-and-go server, based on Joe&#8217;s tutorial, but that&#8217;s not for here.)</p>
<p>The unicode problem, however, as well as the JSON problem, are not solved.  Unfortunately, whereas the Erlang community has had the foresight to deal with complex problems in modules first then to move them to syntax later, this process seems to be failing with both JSON and Unicode.  It can be argued that some of the choices made in each process are dangerous.  This community will, by and on the whole, remember the re: module, which is being replaced now with a partially incompatible successor that takes account of limitations and problems in the prior attempt, as well as moves to a stronger RE dialect.  It is important that this ability be retained for JSON and Unicode, both of which are subtly strikingly difficult problems, and both of which are unlikely to be Gotten Right™ on their respective first attempts.</p>
<h1>The Principle of Least Surprise</h1>
<p>One of the most important parts of writing libraries is to not write nasty shocks into place for users.  In transcoding libraries, there is one rule that defines least surprise more powerfully than any other: <em><strong>round-trip translations must not lose data</strong></em>.  No configuration of EEP 18 can achieve this.  Indeed, it is my position that a one to one translation of JSON to Erlang terms cannot exist, and that any attempt to present a not-1:1 translation as a translation is unacceptable, in that people will expect <span style="color: #0000ff"><code>j2e(e2j(X)) == X</code></span>, and that cannot be true.  This is especially important given that the suggestion that these translations become BIFs seems to be being taken seriously; <span style="color: #0000ff"><code>foo_to_bar(X)</code></span> bifs are currently never lossy, and this would create a worrying change in the meaning of several basic naming practices.</p>
<p>It is of critical importance, in my opinion, that we do not provide libraries which fail round-trip conversion in either direction.  At this time, EEP 18 attempts to satisfy this clause with creation-time configurability; I will explain my stance that this is inadequate below.</p>
<h1>Why Translation is Unclear</h1>
<p>There are, in fact, quite a few problems that prevent 1:1 translation.  We&#8217;ll go over them one by one.</p>
<ol>
<li>The notations offer different fundamental containers
<ol>
<li>Erlang offers dense sequence (&#8220;tuple&#8221;, <span style="color: #0000ff"><code>{}</code></span>) and singly linked list (&#8220;list&#8221;, <span style="color: #0000ff"><code>[]</code></span>) containers.  The erlang standard library offers other containers; I discuss later in this document why I&#8217;m not using them.</li>
<li>JSON offers dense sequence (&#8220;array&#8221;, <span style="color: #0000ff"><code>[]</code></span>) and key-value map (&#8220;object&#8221;, <span style="color: #0000ff"><code>{}</code></span>) containers.  That&#8217;s it.</li>
</ol>
</li>
<li>The notations offer different fundamental datatypes
<ol>
<li>JSON has a fundamental string type; erlang doesn&#8217;t.</li>
<li>Erlang has atoms; JSON doesn&#8217;t.</li>
<li>JSON has booleans and &#8220;null&#8221;; Erlang doesn&#8217;t.  For transcoding, pretending they&#8217;re atoms creates ambiguity, and is therefore unacceptable.</li>
<li>JSON has explicit support for unicode characters in strings.  Erlang doesn&#8217;t have strings at all, but rather lists of characters (in the way that C has arrays of characters).  Those lists are context and usage defined; C++ programmers may think of this as parallel to array strings vs std::string.  Erlang currently has no concept of Unicode (<span style="color: #999999"><em>though that&#8217;s another issue I&#8217;m working on as divergent from the current mailing list / EEP approach</em>.</span>)</li>
<li>JSON and Erlang have very different lists of quoted terms for strings.
<ol>
<li>Erlang supports embedded octal with shortening, and a bunch of semi-defunct control characters like form feed (<span style="color: #0000ff"><code>"\f"</code></span>) and escape (<span style="color: #0000ff"><code>"\e"</code></span>).</li>
<li>JSON supports 16-bit Unicode character embedding.</li>
<li>Problematically, JSON does not define whether that embedding is UTF16, UCS2 or something else.  Most software implementations assume UTF16.  This document will carefully avoid the issue, which is a serious defect in this document, and a serious defect in JSON.</li>
</ol>
</li>
<li>Erlang terms are byte-available, meaning Erlang programmers may be aware of endianness; JSON objects are not.  This suggests that the handling library needs to either make a choice about internal endianness, or needs to provide control to the user.</li>
</ol>
</li>
<li>The notation for similar containers is dissimilar</li>
<li>Similar notations are similar, not identical</li>
<li>Dangerous string ambiguities</li>
</ol>
<p>Working from http://sc.tri-bit.com/outgoing/scjson%20parser%20halp.html</p>
]]></content:encoded>
			<wfw:commentRss>http://fullof.bs/prototype-eep-18-considered-harmful-the-problems-with-erlang-to-json-term-translation/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Moments, Skewness and Kurtosis (Statistics in Erlang part 8)</title>
		<link>http://fullof.bs/moments-skewness-and-kurtosis-statistics-in-erlang-part-8/</link>
		<comments>http://fullof.bs/moments-skewness-and-kurtosis-statistics-in-erlang-part-8/#comments</comments>
		<pubDate>Thu, 28 Aug 2008 02:43:28 +0000</pubDate>
		<dc:creator>John Haugeland</dc:creator>
				<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Statistics]]></category>
		<category><![CDATA[Tools and Libraries]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[central moment]]></category>
		<category><![CDATA[kurtosis]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[moment]]></category>
		<category><![CDATA[skewness]]></category>
		<category><![CDATA[stats]]></category>

		<guid isPermaLink="false">http://fullof.bs/?p=365</guid>
		<description><![CDATA[[digg-reddit-me]So, it was pointed out to me that I had the central moments, but not the moments &#8211; ie, the ones not normalized against the input&#8217;s average.  Also, it was pointed out that most people don&#8217;t know that kurtosis and skewness are related to the central moments.  Furthermore, it turns out (and I didn&#8217;t know [...]]]></description>
			<content:encoded><![CDATA[<p>[digg-reddit-me]So, it was pointed out to me that I had the central moments, but not the moments &#8211; ie, the ones not normalized against the input&#8217;s average.  Also, it was pointed out that most people don&#8217;t know that kurtosis and skewness are related to the central moments.  Furthermore, it turns out (and I didn&#8217;t know this) that there are in fact meaningful uses of floating-point exponents in moments.</p>
<p>So, I implemented moments, I replaced my central moments implementation, and I gave name wrappers for skewness and kurtosis to make them easier to identify.</p>
<p>This closes issues <a title="Crunchy Development issue 132, Skewness" href="http://crunchyd.com/forum/project.php?issueid=169" target="_blank">169</a>, <a title="Crunchy Development issue 170, Kurtosis" href="http://crunchyd.com/forum/project.php?issueid=170" target="_blank">170</a>, <a title="Crunchy Development issue 171, Moments" href="http://crunchyd.com/forum/project.php?issueid=171" target="_blank">171</a>, <a title="Crunchy Development issue 172, Real valued moments" href="http://crunchyd.com/forum/project.php?issueid=172" target="_blank">172</a> and <a title="Crunchy Development issue 173, Real valued central moments" href="http://crunchyd.com/forum/project.php?issueid=173" target="_blank">173</a>.  As usual, this code is part of <a title="The ScUtil Library" href="http://scutil.com/" target="_blank">the ScUtil library</a>, which is free and MIT licensed, because the GPL is evil.</p>
<pre style="padding-left: 30px">moment(List, N) when is_list(List), is_number(N) -&gt;
    scutil:arithmetic_mean( [ pow(Item, N) || Item &lt;- List ] ).

moments(List) -&gt;
    moments(List, [2,3,4]).

moments(List, Moments) when is_list(Moments) -&gt;
    [ moment(List, M) || M &lt;- Moments ].

central_moment(List, N) when is_list(List), is_number(N) -&gt;
    ListAMean = scutil:arithmetic_mean(List),
    scutil:arithmetic_mean( [ pow(Item-ListAMean, N) || Item &lt;- List ] ).

central_moments(List) -&gt;
    central_moments(List, [2,3,4]).

central_moments(List, Moments) when is_list(Moments) -&gt;
    [ central_moment(List, M) || M &lt;- Moments ].

skewness(List) -&gt; central_moment(List, 3).
kurtosis(List) -&gt; central_moment(List, 4).</pre>
]]></content:encoded>
			<wfw:commentRss>http://fullof.bs/moments-skewness-and-kurtosis-statistics-in-erlang-part-8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spearman&#8217;s Rank Correlation Coefficient (Statistics in Erlang part 7)</title>
		<link>http://fullof.bs/spearmans-rank-correlation-coefficient-statistics-in-erlang-part-7/</link>
		<comments>http://fullof.bs/spearmans-rank-correlation-coefficient-statistics-in-erlang-part-7/#comments</comments>
		<pubDate>Sun, 24 Aug 2008 16:29:33 +0000</pubDate>
		<dc:creator>John Haugeland</dc:creator>
				<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Statistics]]></category>
		<category><![CDATA[Tools and Libraries]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[mit license]]></category>
		<category><![CDATA[spearman]]></category>
		<category><![CDATA[spearman correlation]]></category>
		<category><![CDATA[spearman rank]]></category>
		<category><![CDATA[spearman rho]]></category>
		<category><![CDATA[spearman's rank correlation coefficient]]></category>
		<category><![CDATA[stats]]></category>

		<guid isPermaLink="false">http://fullof.bs/?p=353</guid>
		<description><![CDATA[[digg-reddit-me]Spearman&#8217;s Rank Correlation Coefficient &#8211; usually just called The Spearman Correlation, sometimes Spearman&#8217;s Rank or Spearman&#8217;s Rho &#8211; is a method of determining the similarity between two numeric sets (we also go over the Pearson and the Kendall).  If you don&#8217;t know what a correlation is, start with Statistics in Erlang part 5, which covers [...]]]></description>
			<content:encoded><![CDATA[<p>[digg-reddit-me]Spearman&#8217;s Rank Correlation Coefficient &#8211; usually just called The Spearman Correlation, sometimes Spearman&#8217;s Rank or Spearman&#8217;s Rho &#8211; is a method of determining the similarity between two numeric sets (we also go over the <a title="Statistics in Erlang part 6" href="http://fullof.bs/the-pearson-correlation-coefficient-statistics-in-erlang-part-6" target="_blank">Pearson</a> and the Kendall).  If you don&#8217;t know what a correlation is, start with <a title="Statistics in Erlang part 5" href="http://fullof.bs/statistical-correlations-statistics-in-erlang-part-5" target="_blank">Statistics in Erlang part 5</a>, which covers the basic idea of correlations.  A good math-based explanation is available at <a title="Hyperstat - Spearman's Rho" href="http://davidmlane.com/hyperstat/A62436.html" target="_blank">David M Lane&#8217;s Hyperstat</a>.</p>
<p>In English, for two lists of length N, you take the square of the difference between each matched row in the two lists, sum them, multiply by six, and divide by N cubed minus N.  This provides the rank correlation squared, which is over the interval [-1, 1].  However, with spearman you usually use the rank squared, so we leave it that way instead of providing the root; the tuple&#8217;s atom label makes it clear that&#8217;s happening.</p>
<p>Sorry again about the screwy formatting; I&#8217;m just getting things to fit on the blog.  The stuff in the library is better formatted.</p>
<pre style="padding-left: 30px">spearman_correlation(List1, List2) when
    is_list(List1), is_list(List2),
    length(List1) /= length(List2) -&gt; {error, lists_must_be_same_length};

spearman_correlation(List1, List2) when is_list(List1), is_list(List2) -&gt;

    {TR1,_} = lists:unzip(ordered_ranks_of(List1)),
    {TR2,_} = lists:unzip(ordered_ranks_of(List2)),

    Numerator   = 6 * lists:sum([ (D1-D2)*(D1-D2)
                               || {D1,D2} &lt;- lists:zip(TR1,TR2) ]),
    Denominator = math:pow(length(List1),3)-length(List1),

    {rsquared,1-(Numerator/Denominator)}.</pre>
<p>Test data is available at <a title="Geography Fieldwork - Spearman's Rank" href="http://geographyfieldwork.com/SpearmansRank.htm" target="_blank">Geography Fieldwork</a>.</p>
<pre style="padding-left: 30px"><span style="color: #008080"><strong><span style="color: #000080">1&gt; X = [50,175,270,375,425,580,710,790,890,980].</span>
[50,175,270,375,425,580,710,790,890,980]
<span style="color: #000080">2&gt; Y = [1.80,1.20,2.00,1.00,1.00,1.20,0.80,0.60,1.00,0.85].</span>
[1.80000, 1.20000, 2.00000, 1.00000, 1.00000,
 1.20000, 0.800000, 0.600000, 1.00000, 0.850000]
<span style="color: #000080">3&gt; scutil:spearman_correlation(X,Y).</span>
{rsquared,-0.730303}</strong></span></pre>
<p>This code is part of <a title="The ScUtil Library" href="http://scutil.com/" target="_blank">the ScUtil library</a>.  This code is free and MIT licensed, because the GPL is evil.  This code uses the ordered ranks code from <a title="Statistics in Erlang part 4" href="http://fullof.bs/ranks-of-ordered-ranks-of-and-tied-ranks-of-statistics-in-erlang-part-4" target="_blank">Part 4</a>.  This closes <a title="Crunchy Development issue 139, Spearman's Rank" href="http://crunchyd.com/forum/project.php?issueid=139" target="_blank">issue 139</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://fullof.bs/spearmans-rank-correlation-coefficient-statistics-in-erlang-part-7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Pearson Correlation Coefficient (Statistics in Erlang part 6)</title>
		<link>http://fullof.bs/the-pearson-correlation-coefficient-statistics-in-erlang-part-6/</link>
		<comments>http://fullof.bs/the-pearson-correlation-coefficient-statistics-in-erlang-part-6/#comments</comments>
		<pubDate>Sun, 24 Aug 2008 01:46:39 +0000</pubDate>
		<dc:creator>John Haugeland</dc:creator>
				<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Statistics]]></category>
		<category><![CDATA[Tools and Libraries]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[correlation]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[pearson correlation]]></category>
		<category><![CDATA[pearson correlation coefficient]]></category>
		<category><![CDATA[stats]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://fullof.bs/?p=343</guid>
		<description><![CDATA[[digg-reddit-me]I went over much of the concept of correlations in Part 5; if you don&#8217;t know what statistical correlations are, you should read part 5 first.
The Pearson Correlation Coefficient is one method of generating the correlation of sets.  You can get a good math-based explanation at David Lane&#8217;s Hyperstat.
In english, basically, you take two numeric [...]]]></description>
			<content:encoded><![CDATA[<p>[digg-reddit-me]I went over much of the concept of correlations in <a title="Statistics in Erlang part 5" href="http://fullof.bs/statistical-correlations-statistics-in-erlang-part-5" target="_blank">Part 5</a>; if you don&#8217;t know what statistical correlations are, you should read part 5 first.</p>
<p>The Pearson Correlation Coefficient is one method of generating the correlation of sets.  You can get a good math-based explanation at <a title="Hyperstat - Computing Pearson's Correlation" href="http://davidmlane.com/hyperstat/A51911.html" target="_blank">David Lane&#8217;s Hyperstat</a>.</p>
<p>In english, basically, you take two numeric lists of the same length, X and Y, then calculate five sums and a length from them:</p>
<ol>
<li>The sum of the items in List X (SumX)</li>
<li>The sum of the items in List Y (SumY)</li>
<li>The sum of the squares of the items in List X (SumXX)</li>
<li>The sum of the squares of the items in List Y (SumYY)</li>
<li>The sum of the products of the matched items in Lists X and Y (SumXY)</li>
<li>The length of the lists, which should be the same (N)</li>
</ol>
<p>Using those, you can construct a polynomial which is honestly best expressed in code:</p>
<pre style="padding-left: 30px">pearson_correlation(List1, List2) when is_list(List1), is_list(List2) -&gt;

    SumXY = lists:sum([A*B || {A,B} &lt;- lists:zip(List1,List2) ]),   ]

    SumX  = lists:sum(List1),
    SumY  = lists:sum(List2),

    SumXX = lists:sum([L*L || L&lt;-List1]),
    SumYY = lists:sum([L*L || L&lt;-List2]),

    N     = length(List1),

    Numer = (N*SumXY) - (SumX * SumY),
    Denom = math:sqrt(((N*SumXX)-(SumX*SumX)) * ((N*SumYY)-(SumY*SumY))),

    {r, (Numer/Denom)}.</pre>
<p>This code is part of the <a title="The ScUtil Library" href="http://scutil.com/" target="_blank">ScUtil Library</a>.  The ScUtil library is free and MIT licensed, because the GPL is evil.</p>
<pre style="padding-left: 30px"><span style="color: #008080"><strong><span style="color: #000080">1&gt; X = [1,3,5,6,8,9,6,4,3,2].  </span>    </strong>
[1,3,5,6,8,9,6,4,3,2]
<strong><span style="color: #000080">2&gt; Y = [2,5,6,6,7,7,5,3,1,1].</span>  </strong>
[2,5,6,6,7,7,5,3,1,1]
<span style="color: #000080"><strong>3&gt; scutil:pearson_correlation(X,Y).</strong></span>
{r,0.854706}</span></pre>
<p>Verification of test data is available at <a title="Chaing Minds - Pearson Correlation" href="http://changingminds.org/explanations/research/analysis/pearson.htm" target="_blank">Changing Minds</a>.  This closes <a title="Crunchy Development issue 140, Pearson Correlation" href="http://crunchyd.com/forum/project.php?issueid=140" target="_blank">issue 140</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://fullof.bs/the-pearson-correlation-coefficient-statistics-in-erlang-part-6/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Statistical Correlations (Statistics in Erlang part 5)</title>
		<link>http://fullof.bs/statistical-correlations-statistics-in-erlang-part-5/</link>
		<comments>http://fullof.bs/statistical-correlations-statistics-in-erlang-part-5/#comments</comments>
		<pubDate>Sat, 23 Aug 2008 22:45:05 +0000</pubDate>
		<dc:creator>John Haugeland</dc:creator>
				<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Statistics]]></category>
		<category><![CDATA[Tools and Libraries]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[correlation]]></category>
		<category><![CDATA[kendall correlation]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[pearson correlation]]></category>
		<category><![CDATA[spearman correlation]]></category>
		<category><![CDATA[stats]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://fullof.bs/?p=326</guid>
		<description><![CDATA[[digg-reddit-me]Since most of my readers are programmers, I&#8217;m going to explain this in programmer-speak.  Also, it&#8217;s damned hard to find a non-math explanation of this stuff.
The general idea with correlations is simple: we want to measure how much changes in one set affect the other set &#8211; that is, their correlation.  Correlations aren&#8217;t about the [...]]]></description>
			<content:encoded><![CDATA[<p>[digg-reddit-me]Since most of my readers are programmers, I&#8217;m going to explain this in programmer-speak.  Also, it&#8217;s damned hard to find a non-math explanation of this stuff.</p>
<p>The general idea with correlations is simple: we want to measure how much changes in one set affect the other set &#8211; that is, their correlation.  Correlations aren&#8217;t about the actual values involved in the two columns, so much as how they seem to affect one another.</p>
<p>A simple example is the edge size and volume of a cube.  As the edge size goes up, so will the volume.  To that end, if you make a two-column table where one column is edge size and the other volume (or, for that matter, face size works too), and then the rows are just a bunch of example data, you would want to see a &#8220;perfect correlation&#8221; &#8211; without fail, the change in column 1 should show a perfect match for changes in column 2.  For a perfect match like that, you get a correlation of 1.0.  Similarly, if you measure the average density of a fixed number of particles in that space, as the edge size goes up, the average density goes down; you would see a &#8220;perfect inverse&#8221; correlation, or a value of -1.0.  If you measure two values which aren&#8217;t correlated &#8211; where values in one column don&#8217;t seem to affect values in the other &#8211; you should get a value at or near zero.</p>
<p>The purpose of the correlation coefficient is to tell how how strongly two columns are correlated, as well as whether their correlation is positive (similar) or negative (inverse).  You can use measurements to determine whether sets of measurements are related.</p>
<p>Consider, for example, a table of height and weight among a distribution of people.  One expects a strong correlation, but not perfect; some people are over- and under-weight for their height.  The closer that measurement comes to 1, the less the outside factors matter.  The closer that measurement comes to zero, the less dominant the measured term is in the measured result.  In practical terms, if you see (for example) a stronger correlation between users of Medicine X and outbreaks of Symptom Y than in the general population, it is likely that Medicine X has Symptom Y as a long-term ramification.</p>
<p>The way this is achieved is through ranking, which was covered in <a title="Statistics in Erlang part 4" href="http://fullof.bs/ranks-of-ordered-ranks-of-and-tied-ranks-of-statistics-in-erlang-part-4" target="_blank">Statistics in Erlang part 4</a>.  The general idea is straightforward: just make a list of your values&#8217; ranks from most significant (usually largest) to least, starting counting at 1.  Do that for both columns, then sort by the first column (keep the columns correlated of course).  At that point, what you actually do to measure the correlation varies from method to method, but the general landscape of things should now be apparent: we&#8217;re just measuring how much the difference in rank varies when sorted by one column.</p>
<p>There are several ways to get such correlations.  We&#8217;re going to go over the big three &#8211; the Pearson Correlation Coefficient, the Kendall Tau Rank Correlation, and the Spearman Rank Correlation Coefficient.  Each one is covered in one of the upcoming tutorials: <a title="Statistics in Erlang part 6" href="http://fullof.bs/the-pearson-correlation-coefficient-statistics-in-erlang-part-6" target="_blank">Pearson Correlation in Erlang</a> (part 6), Spearman Correlation in Erlang (part 7) and Kendall Correlation in Erlang (part 8).</p>
]]></content:encoded>
			<wfw:commentRss>http://fullof.bs/statistical-correlations-statistics-in-erlang-part-5/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ranks Of, Ordered Ranks Of and Tied Ranks Of (Statistics in Erlang part 4)</title>
		<link>http://fullof.bs/ranks-of-ordered-ranks-of-and-tied-ranks-of-statistics-in-erlang-part-4/</link>
		<comments>http://fullof.bs/ranks-of-ordered-ranks-of-and-tied-ranks-of-statistics-in-erlang-part-4/#comments</comments>
		<pubDate>Fri, 15 Aug 2008 04:09:49 +0000</pubDate>
		<dc:creator>John Haugeland</dc:creator>
				<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Statistics]]></category>
		<category><![CDATA[Tools and Libraries]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[ordered ranks of]]></category>
		<category><![CDATA[ranks of]]></category>
		<category><![CDATA[scutil]]></category>
		<category><![CDATA[stats]]></category>
		<category><![CDATA[tied ranks of]]></category>

		<guid isPermaLink="false">http://fullof.bs/?p=323</guid>
		<description><![CDATA[[digg-reddit-me]The upcoming Statistics in Erlang post, on correlations, requires some groundwork tools.  At this time, I don&#8217;t actually know the proper statistical names for these functions, and in fact such names probably don&#8217;t exist, so I just made some up; these functions are treated by the texts describing correlations as an inline part of the [...]]]></description>
			<content:encoded><![CDATA[<p>[digg-reddit-me]The upcoming Statistics in Erlang post, on correlations, requires some groundwork tools.  At this time, I don&#8217;t actually know the proper statistical names for these functions, and in fact such names probably don&#8217;t exist, so I just made some up; these functions are treated by the texts describing correlations as an inline part of the process, but the process is much easier to understand if they&#8217;re seperate, so I seperated them.</p>
<p>Witness ranks_of(), ordered_ranks_of() and tied_ranks_of().  On their own, their importance isn&#8217;t tremendously apparent, but when we get to correlations, it&#8217;ll suddenly become obvious.</p>
<ul>
<li>ranks_of()
<ul>
<li>Ranks of takes a list and reverse sorts it, then returns a series of 2-tuples whose first member is the &#8220;rank&#8221; or 1-offset ordinal of the item&#8217;s list position, and whose second member is the original list value.  Erlang sort is used to order the terms, so they don&#8217;t actually need to be strictly numeric, though the function is pretty meaningless otherwise.  Soon, a version will be provided that takes a predicate for custom sorting.</li>
<li>Tied (equal) values are listed in order as separate ranks.  If you want those ties to be expressed as average values, use tied_ranks_of() below.  Because there are no ties, ranks are expressed as integers.</li>
<li>Values are presented with highest rank (rank 1, highest literal value) sorted to the front.</li>
<li><span style="color: #0000ff"><strong><span style="color: #008000">1&gt; scutil:ranks_of([3,8,22,8,535]).</span><br />
[{1,535},{2,22},{3,8},{4,8},{5,3}]</strong></span></li>
</ul>
</li>
<li>tied_ranks_of()
<ul>
<li>Very similar to ranks_of(), except that ranks are presented as tied when values are equivalent.  Notice how with ranks_of(), the two 8s are ranked 3 and 4; here, they are both ranked 3.5.</li>
<li>Because ties can create half-values, ranks are presented as floats.</li>
<li><span style="color: #0000ff"><strong><span style="color: #008000">86&gt; scutil:tied_ranks_of([3,8,22,8,535]).<br />
<span style="color: #0000ff">[{1.00000,535},{2.00000,22},{3.50000,8},{3.50000,8},{5.00000,3}]</span></span></strong></span></li>
</ul>
</li>
<li>ordered_ranks_of()
<ul>
<li>Correlations frequently need to be column cross-sorted.  The easiest way to deal with this is to provide a ranking function which provides the rankings in the column&#8217;s original order.  ordered_ranks_of() is tied_ranks_of() which does not alter list ordering.</li>
<li><span style="color: #0000ff"><strong><span style="color: #008000"><span style="color: #008000">3</span><span style="color: #0000ff"><span style="color: #008000">&gt; scutil:ordered_ranks_of([3,8,22,8,535]).</span><br />
[{5.00000,3},{3.50000,8},{2.00000,22},{3.50000,8},{1.00000,535}]</span></span></strong></span></li>
</ul>
</li>
</ul>
<p>These functions are important building blocks to the correlations, coming up in parts 5 and 6.</p>
<p><span class="entry">As usual, <a title="StoneCypher's Utility Library" href="http://scutil.com/" target="_blank">this code is part of the ScUtil library</a>.  ScUtil is free and MIT license, because the GPL is evil.</span></p>
<p>This code doesn&#8217;t need any of the prior parts <a title="Part 1 of Statistics in Erlang" href="http://fullof.bs/arithmetic-mean-geometric-mean-harmonic-mean-and-weighted-arithmetic-mean-statistics-in-erlang-part" target="_blank">1</a>, <a title="Part 2 of Statistics in Erlang" href="http://fullof.bs/mean-median-mode-and-histograph-statistics-in-erlang-part-2" target="_blank">2</a>, or <a title="Part 3 of Statistics in Erlang" href="http://fullof.bs/standard-deviation-root-mean-square-and-the-central-moments-statistics-in-erlang-part-3" target="_blank">3</a> of Statistics in Erlang, but I&#8217;m linking them to make them easy to find.</p>
<p>This closes issue <a title="Issue 129 at Crunchy Development" href="http://crunchyd.com/forum/project.php?issueid=129" target="_blank">129</a>.</p>
<p>Sorry about the screwy formatting; it&#8217;s hard fitting code into a blog.  The formatting in the module is much nicer.</p>
<pre style="padding-left: 30px">ranks_of(List) when is_list(List) -&gt;
    lists:zip(lists:seq(1,length(List)),lists:reverse(lists:sort(List))).

tied_ranks_of(List) -&gt;
    tied_rank_worker(ranks_of(List), [], no_prev_value).

tied_add_prev(Work, {FoundAt, NewValue}) -&gt;
    lists:duplicate(
        length(FoundAt),
        {lists:sum(FoundAt) / length(FoundAt), NewValue}
    ) ++ Work.

tied_rank_worker([], Work, PrevValue) -&gt;
    lists:reverse(tied_add_prev(Work, PrevValue));

tied_rank_worker([Item|Remainder], Work, PrevValue) -&gt;
    case PrevValue of
        no_prev_value -&gt;
            {BaseRank,BaseVal} = Item,
            tied_rank_worker(Remainder, Work, {[BaseRank],BaseVal});
        {FoundAt,OldVal} -&gt;
            case Item of
                {Id,OldVal} -&gt;
                    tied_rank_worker(
                        Remainder,
                        Work,
                        {[Id]++FoundAt,OldVal});
                {Id,NewVal} -&gt;
                    tied_rank_worker(Remainder,
                        tied_add_prev(Work, PrevValue),
                        {[Id],NewVal})
            end
    end.

ordered_ranks_of(List) when is_list(List) -&gt;
    ordered_ranks_of(List, tied_ranks_of(List), []).

ordered_ranks_of([], [], Work) -&gt;
    lists:reverse(Work);

ordered_ranks_of([Front|Rem], Ranks, Work) -&gt;
    {value,Item} = lists:keysearch(Front,2,Ranks),
    {IRank,Front} = Item,
    ordered_ranks_of(Rem, Ranks--[Item], [{IRank,Front}]++Work).</pre>
]]></content:encoded>
			<wfw:commentRss>http://fullof.bs/ranks-of-ordered-ranks-of-and-tied-ranks-of-statistics-in-erlang-part-4/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
