<?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>Lojic Technologies Blog &#187; programming</title>
	<atom:link href="http://lojic.com/blog/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://lojic.com/blog</link>
	<description></description>
	<lastBuildDate>Fri, 25 Nov 2011 20:12:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Beware of YAML serialization on Linux without libyaml</title>
		<link>http://lojic.com/blog/2011/11/22/beware-of-yaml-serialization-on-linux-without-libyaml/</link>
		<comments>http://lojic.com/blog/2011/11/22/beware-of-yaml-serialization-on-linux-without-libyaml/#comments</comments>
		<pubDate>Tue, 22 Nov 2011 19:44:46 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=876</guid>
		<description><![CDATA[The Problem
I noticed some unusual behavior with respect to YAML String serialization between my Linux production system and my Mac OSX development system.
After dumping the production database via pg_dump -O &#8211;no-acl mydb &#124; gzip &#62; ~/mydb.sql.gz and then restoring it on my development system via rake db:drop; rake db:create; psql mydb &#60; mydb.sql, I noticed [...]]]></description>
			<content:encoded><![CDATA[<h1>The Problem</h1>
<p>I noticed some unusual behavior with respect to <a href="http://www.yaml.org/">YAML</a> String serialization between my Linux production system and my Mac OSX development system.</p>
<p>After dumping the production database via pg_dump -O &#8211;no-acl mydb | gzip &gt; ~/mydb.sql.gz and then restoring it on my development system via rake db:drop; rake db:create; psql mydb &lt; mydb.sql, I noticed that a particular <em>serialized</em> field in my Rails app that should always be an Array of String objects occasionally contained Integers.</p>
<p>After a little research and experimentation, I discovered that the production Linux system would occasionally omit quotations around Strings containing only numeric digits. I haven&#8217;t analyzed the pattern fully, but here are some examples where the YAML serialization did or did not use quotes:</p>
<ul>
<li>&#8220;90103&#8243;</li>
<li>000080</li>
<li>&#8220;000071&#8243;</li>
<li>&#8220;000124&#8243;</li>
<li>&#8220;000003&#8243;</li>
<li>008397</li>
<li>000408</li>
<li>000009</li>
<li>000188</li>
<li>&#8220;000021&#8243;</li>
</ul>
<p>Further investigation revealed that the Linux production system was using Syck (a &#8220;dated C implementation of YAML 1.0&#8243;) and my Mac OSX development system was using psych (a &#8220;libyaml wrapper (in Ruby core for 1.9.2)&#8221;). libyaml is a &#8220;fast C implementation of YAML 1.1. So, either the quotation rules have changed between YAML 1.0 and YAML 1.1, or there is a bug in one of the implementations (likely Syck).</p>
<h1>The Solution</h1>
<p>The solution for proper &#8220;future&#8221; behavior is pretty simple. Install libyaml on the Linux system as follows:</p>
<pre>wget http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gz
tar xzf yaml-0.1.4.tar.gz
cd yaml-0.1.4
./configure
make
make install</pre>
<p>I <em>think</em> that&#8217;s enough, but I went ahead and rebuilt my Ruby 1.9.2 just in case it needed to know about the existence of libyaml at build time.</p>
<p>The solution for converting my database with YAML 1.0 serialization to YAML 1.1 serialization is a bit trickier. Since the &#8220;dump&#8221; and &#8220;load&#8221; operations are matched for a particular version of YAML, it seems difficult to load the data using YAML 1.0 (thereby retaining the String type when reading an unquoted 000088) and then dump the data using YAML 1.1 (to get proper quoting of &#8216;000088&#8242;). Further complicating this is the fact that Rails handles the serialization operations automatically.</p>
<p>It does appear possible to dynamically switch between syck and psyck by using the following:</p>
<pre>YAML::ENGINE.yamler = 'syck'
YAML::ENGINE.yamler = 'psych'</pre>
<p>So, one option is to repeatedly switch to syck, read in data, switch to psych, and then write the data. &lt;sigh&gt;</p>
<p><strong>Update:</strong></p>
<p>It appears that due to the semantics of the Rails serialize function, it&#8217;s not enough to just read the model object using <em>syck</em> and then immediately write with <em>psych</em> because that doesn&#8217;t appear to be enough to cause the field to be deserialized. I had to refer to the field for each object. This is a pain because it prevents me from doing a generic loop where I can handle all model objects easily w/o reference to their specific fields.</p>
<p>I&#8217;ll withhold judgment for a while, but my first inclination is to consider abandoning YAML serialization for something a little more robust and portable.</p>
<p><strong>Update 2:</strong></p>
<p>It appears my welcome from psych is a serious memory leak. I&#8217;ve been running long running Ruby/Rails processes for years, and this is the first time I&#8217;ve experienced a failure due to an out of memory condition. There are a number of Google hits regarding the issue. After I fix the leak, I&#8217;ll begin researching alternatives to YAML serialization in Rails.</p>
<p><strong>Update 3:</strong></p>
<p>The number of bug reports on psych and rubygems I&#8217;ve had to wade through recently is amazing. My current solution is to remove the psych system gem and install Ruby 1.9.3p0 which required upgrading Passenger to the latest version from source to get Ruby 1.9.3 compatibility. I still had to track down a few odd errors such as &#8220;undefined method `yaml&#8217; for #&lt;Psych::Nodes::Stream:&#8230;&gt;&#8221; and &#8220;invalid date format in specification: &#8220;2011-10-02 00:00:00.000000000Z&#8221;" &#8211; all because I chose to use the default Rails serialization assuming there would be no issues. Lesson learned.</p>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2011/11/22/beware-of-yaml-serialization-on-linux-without-libyaml/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Programming Language Popularity &#8211; Part Four</title>
		<link>http://lojic.com/blog/2011/09/22/programming-language-popularity-part-four/</link>
		<comments>http://lojic.com/blog/2011/09/22/programming-language-popularity-part-four/#comments</comments>
		<pubDate>Thu, 22 Sep 2011 15:37:07 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[arc]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[scheme]]></category>
		<category><![CDATA[sml]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=866</guid>
		<description><![CDATA[I compiled some programming language popularity statistics in April 2009, October 2009 and October 2010 . Here&#8217;s an update for September 2011:
I made a number of Google searches of the forms below and summed the results (previous posts averaged the results):
"implemented in &#60;language&#62;"
  "written in &#60;language&#62;"
Naturally this is of very limited utility, and the [...]]]></description>
			<content:encoded><![CDATA[<p>I compiled some programming language popularity statistics in <a href="http://lojic.com/blog/2009/04/21/programming-language-popularity/">April 2009</a>, <a href="http://lojic.com/blog/2009/10/24/programming-language-popularity-part-two/">October 2009</a> and <a href="http://lojic.com/blog/2010/10/08/programming-language-popularity-%E2%80%93-part-three/">October 2010</a> . Here&#8217;s an update for September 2011:</p>
<p>I made a number of Google searches of the forms below and summed the results (previous posts averaged the results):</p>
<pre class="code">"implemented in &lt;language&gt;"
  "written in &lt;language&gt;"</pre>
<p>Naturally this is of very limited utility, and the numbers are only useful when comparing relatively within the same search since the number of results Google returns can vary greatly over time.<br />
<!-- use ML and SML --></p>
<table border="0">
<tbody>
<tr>
<th>Language</th>
<th style="text-align: left;">Total</th>
<th style="text-align: right;">Prev. Position</th>
<th style="text-align: right;"> Position Delta</th>
</tr>
<tr>
<td>C</td>
<td style="text-align: right;">10,360,000</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;"><strong>1</strong></td>
</tr>
<tr>
<td>PHP</td>
<td style="text-align: right;">10,351,000</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>C++</td>
<td style="text-align: right;">6,495,000</td>
<td style="text-align: right;">3</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td>Python</td>
<td style="text-align: right;">5,759,000</td>
<td style="text-align: right;">5</td>
<td style="text-align: right;"><strong>1</strong></td>
</tr>
<tr>
<td>C#</td>
<td style="text-align: right;">5,335,000</td>
<td style="text-align: right;">4</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>&nbsp;</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Java</td>
<td style="text-align: right;">4,890,000</td>
<td style="text-align: right;">8</td>
<td style="text-align: right;"><strong>2</strong></td>
</tr>
<tr>
<td>Perl</td>
<td style="text-align: right;">3,702,000</td>
<td style="text-align: right;">6</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>JavaScript</td>
<td style="text-align: right;">3,077,000</td>
<td style="text-align: right;">7</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>Ruby</td>
<td style="text-align: right;">1,654,000</td>
<td style="text-align: right;">9</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td>Lisp Family<sup>1</sup></td>
<td style="text-align: right;">1,022,870</td>
<td style="text-align: right;">11</td>
<td style="text-align: right;"><strong>1</strong></td>
</tr>
<tr>
<td>&nbsp;</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>FORTRAN</td>
<td style="text-align: right;">975,600</td>
<td style="text-align: right;">10</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>Tcl</td>
<td style="text-align: right;">594,500</td>
<td style="text-align: right;">12</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td>Lisp</td>
<td style="text-align: right;">486,000</td>
<td style="text-align: right;">14</td>
<td style="text-align: right;"><strong>1</strong></td>
</tr>
<tr>
<td>Haskell</td>
<td style="text-align: right;">450,500</td>
<td style="text-align: right;">16</td>
<td style="text-align: right;"><strong>2</strong></td>
</tr>
<tr>
<td>Erlang</td>
<td style="text-align: right;">419,700</td>
<td style="text-align: right;">13</td>
<td style="text-align: right;">-2</td>
</tr>
<tr>
<td>&nbsp;</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Lua</td>
<td style="text-align: right;">367,100</td>
<td style="text-align: right;">18</td>
<td style="text-align: right;"><strong>2</strong></td>
</tr>
<tr>
<td>ML Family<sup>2</sup></td>
<td style="text-align: right;">348,400</td>
<td style="text-align: right;">17</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td>COBOL</td>
<td style="text-align: right;">308,270</td>
<td style="text-align: right;">15</td>
<td style="text-align: right;">-3</td>
</tr>
<tr>
<td>Common Lisp</td>
<td style="text-align: right;">254,900</td>
<td style="text-align: right;">19</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td>OCaml</td>
<td style="text-align: right;">240,300</td>
<td style="text-align: right;">21</td>
<td style="text-align: right;"><strong>1</strong></td>
</tr>
<tr>
<td>&nbsp;</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Prolog</td>
<td style="text-align: right;">224,000</td>
<td style="text-align: right;">20</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>Scala</td>
<td style="text-align: right;">203,400</td>
<td style="text-align: right;">23</td>
<td style="text-align: right;"><strong>1</strong></td>
</tr>
<tr>
<td>Scheme</td>
<td style="text-align: right;">184,700</td>
<td style="text-align: right;">22</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>Smalltalk</td>
<td style="text-align: right;">129,700</td>
<td style="text-align: right;">24</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td>Clojure</td>
<td style="text-align: right;">84,600</td>
<td style="text-align: right;">27</td>
<td style="text-align: right;"><strong>2</strong></td>
</tr>
<tr>
<td>&nbsp;</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>(S)ML<sup>3</sup></td>
<td style="text-align: right;">83,630</td>
<td style="text-align: right;">25</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>Forth</td>
<td style="text-align: right;">69,980</td>
<td style="text-align: right;">26</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>Caml</td>
<td style="text-align: right;">24,470</td>
<td style="text-align: right;">28</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td>Io</td>
<td style="text-align: right;">17,700</td>
<td style="text-align: right;">30</td>
<td style="text-align: right;"><strong>1</strong></td>
</tr>
<tr>
<td>Arc</td>
<td style="text-align: right;">12,670</td>
<td style="text-align: right;">29</td>
<td style="text-align: right;">-1</td>
</tr>
</tbody>
</table>
<p><sup>1</sup> combines Lisp, Scheme, Common Lisp, Arc &amp; Clojure<br />
<sup>2</sup> combines OCaml, (S)ML, Caml<br />
<sup>3</sup> summed separate searches for sml and ml</p>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2011/09/22/programming-language-popularity-part-four/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Find Longest Substring Palindrome in Haskell</title>
		<link>http://lojic.com/blog/2011/03/13/find-longest-substring-palindrome-in-haskell/</link>
		<comments>http://lojic.com/blog/2011/03/13/find-longest-substring-palindrome-in-haskell/#comments</comments>
		<pubDate>Sun, 13 Mar 2011 06:37:46 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=836</guid>
		<description><![CDATA[I stumbled upon a programming challenge a company was using for recruitment purposes and thought I&#8217;d create a Haskell solution as a learning exercise. The first problem was to find the longest palindrome embedded in a text string. 
The following Haskell solution seems very readable to me, but it&#8217;s a naive solution that&#8217;s inefficient. It [...]]]></description>
			<content:encoded><![CDATA[<p>I stumbled upon a programming challenge a company was using for recruitment purposes and thought I&#8217;d create a Haskell solution as a learning exercise. The first problem was to find the longest palindrome embedded in a text string. </p>
<p>The following Haskell solution seems very readable to me, but it&#8217;s a naive solution that&#8217;s inefficient. It computes an answer on my 2.6 year old Macbook Pro in under 4 seconds, but a 2x increase in text requires a 7x increase in CPU time.</p>
<p>I believe there are algorithms to find the longest embedded palindrome in linear time, so I may post a refinement later.</p>
<pre>
-- Find the longest palindrome in a text string.

module Main where
import Char

text = "I'll just type in some example text here and embed a little \
\palindrome - A man, a plan, a canal, Panama! - I expect that will be \
\the longest palindrome found in this text.\
\Lorem ipsum dolor sit amet, consectetur adipiscing elit.\
\Integer volutpat lorem imperdiet ante bibendum ullamcorper. Mauris \
\tempor hendrerit justo at elementum. Vivamus elit magna, accumsan id \
\condimentum a, luctus a ipsum. Donec fermentum, lectus at posuere \
\ullamcorper, mauris lectus tincidunt nulla, ut placerat justo odio sed\
\ odio. Nulla blandit lorem sit amet odio varius nec vestibulum ante \
\ornare. Aliquam feugiat, velit a rhoncus rutrum, turpis metus pretium \
\dolor, et mattis leo turpis non est. Sed aliquet, sapien quis \
\consequat condimentum, sem magna ornare ligula, id blandit odio nisl \
\vitae erat. Nam vulputate tincidunt quam, non lacinia risus tincidunt \
\lacinia. Aenean fermentum tristique porttitor. Nam id dolor a eros \
\accumsan imperdiet. Aliquam quis nibh et dui ultricies cursus. Nunc \
\et ante non sapien vehicula rutrum. Duis posuere dictum blandit. Nunc \
\vitae tempus purus."

clean = map toLower . filter isAlpha

palindrome str = str == reverse str

substrings []     = []
substrings (x:xs) = substrings' (x:xs) ++ substrings xs where
  substrings' []     = []
  substrings' (y:ys) = [y] : [ (y:s) | s <- substrings' ys ]

longest []     = []
longest (x:xs) = if length x &gt; length max then x else max
  where max = longest xs

longest_palindrome xs =
  longest (filter palindrome (substrings (clean text)))

main = print (longest_palindrome text)
</pre>
<p>As a comparison, I translated the program into Ruby. I program predominantly in Ruby these days, and I like it, but the Ruby version is 25 times slower (98 sec. vs. 4 sec.), and it&#8217;s 2.4 times more lines of code (31 vs. 13 &#8211; excluding the text).</p>
<p>A gain in runtime efficiency, expressive power and multi-core capability is very attractive!</p>
<p>I&#8217;m using Ruby 1.9.2 and GHC 6.12.3 on Mac OS X 10.5.8 on a 2.4 GHz Core 2 Duo w/ 4 GB RAM.</p>
<p>ruby 1.9.2p0 (2010-08-18 revision 29036) [i386-darwin9.8.0]<br />
Glasgow Haskell Compiler, Version 6.12.3, for Haskell 98, stage 2 booted by GHC version 6.12.2</p>
<pre>
TEXT = &lt;&lt;END
I'll just type in some example text here and embed a little
palindrome - A man, a plan, a canal, Panama! - I expect that will be
the longest palindrome found in this text.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Integer volutpat lorem imperdiet ante bibendum ullamcorper. Mauris
tempor hendrerit justo at elementum. Vivamus elit magna, accumsan id
condimentum a, luctus a ipsum. Donec fermentum, lectus at posuere
ullamcorper, mauris lectus tincidunt nulla, ut placerat justo odio sed
 odio. Nulla blandit lorem sit amet odio varius nec vestibulum ante
ornare. Aliquam feugiat, velit a rhoncus rutrum, turpis metus pretium
dolor, et mattis leo turpis non est. Sed aliquet, sapien quis
consequat condimentum, sem magna ornare ligula, id blandit odio nisl
vitae erat. Nam vulputate tincidunt quam, non lacinia risus tincidunt
lacinia. Aenean fermentum tristique porttitor. Nam id dolor a eros
accumsan imperdiet. Aliquam quis nibh et dui ultricies cursus. Nunc
et ante non sapien vehicula rutrum. Duis posuere dictum blandit. Nunc
vitae tempus purus.
END

def clean str
  str.gsub(/[^A-Za-z]/,'').downcase
end

def palindrome? str
  str == str.reverse
end

def subs str
  return [] if str.empty?
  y = str[0,1]
  subs(str[1..-1]).inject([y]) do |result, s|
    result &lt;&lt; y + s
    result
  end
end

def substrings str
  return [] if str.empty?
  subs(str) + substrings(str[1..-1])
end

def longest strs
  strs.inject("") do |max, str|
    max = str if str.length &gt; max.length
    max
  end
end

def longest_palindrome str
  longest(substrings(clean(str)).inject([]) {|result, str|
            result &lt;&lt; str if palindrome?(str)
            result
          })
end

puts longest_palindrome(TEXT)
</pre>
<p><strong>Update 3/13/11 19:30</strong><br />
Rick&#8217;s comment (see his blog post linked to in his comment) regarding the importance of algorithm choice is certainly a valid one &#8211; a better algorithm in a slower language may win over an inferior algorithm in a faster language (for large enough datasets). However, what I&#8217;m becoming interested in is the fact that one may gain both productivity/power <strong>and</strong> runtime speed by making wise programming language choices.</p>
<p>In the case of an interpreted language such as Ruby, it&#8217;s helpful to &#8220;stay in C code&#8221; as much as possible. In other words, to favor built-in library routines that have been implemented in C over hand written Ruby code. As much as I like Ruby, this is one of the things that bothers me &#8211; the fact that the Ruby code written by the programmer is vastly inferior in performance to the built-in library routines.</p>
<p>I wasn&#8217;t planning on refining the Haskell version this soon, but after seeing Rick&#8217;s blog post response, I couldn&#8217;t resist :)</p>
<p>I should first provide some background info for context. When I wrote the original Haskell version above, I was in the middle of an online programming challenge, and my goal was simply to compute the answer in a reasonable amount of time to move on to the next challenge, so the brief, easily understandable, Haskell version worked great. Hence, my disclaimers in the post regarding the naivity and inefficiency of the solution. The Ruby code in this post was an afterthought simply to see a comparison between <strong>identical algorithms</strong>. Given that apple &amp; apple comparison, I&#8217;m impressed with the brevity and speed of the Haskell version.</p>
<p>Since I&#8217;m still very much a Haskell newbie, and short on time, I found an <strong>incredible</strong> solution by <a rel="nofollow" href="http://johanjeuring.blogspot.com/2007/08/finding-palindromes.html">Johan Jeuring</a>. It&#8217;s a little bit longer than the Ruby version, but much, <strong>much</strong> faster. It&#8217;s so fast, I had to increase the input quite a bit to get a reasonable comparison &#8211; I replicated the original text 23 times and reversed one of the replications to make a fairly long palindrome.</p>
<p>Rick&#8217;s <strong>Ruby</strong> version took <strong>169.4</strong> seconds, Johan&#8217;s <strong>Haskell</strong> version took <strong>0.032</strong> seconds. In other words, Ruby takes over 5,000 times as long to compute the result. Clearly this is an apples and oranges comparison, but I fully expect that a Ruby version using an identical algorithm will take 100 times as long (or longer) to run and would be less concise. Giving up runtime performance to gain programmer power is one thing, but giving up runtime performance <strong>and</strong> power is a tough pill to swallow.</p>
<p>Here is a slightly modified version of Johan Jeuring&#8217;s code. He was also kind enough to provide his code <a rel="nofollow" href="http://people.cs.uu.nl/johanj/homepage/palindromes/">here</a>:</p>
<pre>
-- Reorganized from Johan Jeuring's solution:
module Main where
import Data.List (maximumBy,intersperse)
import Data.Char
import Data.Array 

text = "I'll just type in some example text here and embed a little \
\palindrome - A man, a plan, a canal, Panama! - I expect that will be \
\the longest palindrome found in this text.\
\Lorem ipsum dolor sit amet, consectetur adipiscing elit.\
\Integer volutpat lorem imperdiet ante bibendum ullamcorper. Mauris \
\tempor hendrerit justo at elementum. Vivamus elit magna, accumsan id \
\condimentum a, luctus a ipsum. Donec fermentum, lectus at posuere \
\ullamcorper, mauris lectus tincidunt nulla, ut placerat justo odio sed\
\ odio. Nulla blandit lorem sit amet odio varius nec vestibulum ante \
\ornare. Aliquam feugiat, velit a rhoncus rutrum, turpis metus pretium \
\dolor, et mattis leo turpis non est. Sed aliquet, sapien quis \
\consequat condimentum, sem magna ornare ligula, id blandit odio nisl \
\vitae erat. Nam vulputate tincidunt quam, non lacinia risus tincidunt \
\lacinia. Aenean fermentum tristique porttitor. Nam id dolor a eros \
\accumsan imperdiet. Aliquam quis nibh et dui ultricies cursus. Nunc \
\et ante non sapien vehicula rutrum. Duis posuere dictum blandit. Nunc \
\vitae tempus purus."

clean = map toLower . filter isAlpha

longestPalindrome input =
  let inputArray      =  listArrayl0 input
      (maxLength,pos) =  maximumBy
                            (\(l,_) (l',_) -> compare l l')
                            (zip (palindromesAroundCentres inputArray) [0..])
  in showPalindrome inputArray (maxLength,pos)

longestPalindromes m input =
  let inputArray =  listArrayl0 input
  in concat $ intersperse "\n"
            $ map (showPalindrome inputArray)
            $ filter ((m<=) . fst)
            $ zip (palindromesAroundCentres inputArray) [0..]

lengthLongestPalindrome :: String -> String
lengthLongestPalindrome = show . maximum . palindromesAroundCentres . listArrayl0

lengthLongestPalindromes :: String -> String
lengthLongestPalindromes = show . palindromesAroundCentres . listArrayl0

palindromesAroundCentres a =
  let (afirst,_) = bounds a
  in reverse $ extendTail a afirst 0 []

extendTail a n currentTail centres
  | n > alast = finalCentres currentTail centres
                   (currentTail:centres)
  | n-currentTail == afirst =
      extendCentres a n (currentTail:centres)
                    centres currentTail
  | a!n == a!(n-currentTail-1) =
      extendTail a (n+1) (currentTail+2) centres
  | otherwise =
      extendCentres a n (currentTail:centres)
                    centres currentTail
  where  (afirst,alast)  =  bounds a

extendCentres a n centres tcentres centreDistance
  | centreDistance == 0 =
      extendTail a (n+1) 1 centres
  | centreDistance-1 == head tcentres  =
      extendTail a n (head tcentres) centres
  | otherwise =
      extendCentres a n (min (head tcentres)
                    (centreDistance-1):centres)
                    (tail tcentres) (centreDistance-1)

finalCentres 0     _        centres  =  centres
finalCentres (n+1) tcentres centres  =
  finalCentres n
               (tail tcentres)
               (min (head tcentres) n:centres)
finalCentres _     _        _        =  error "finalCentres: input < 0"               

showPalindrome a (len,pos) =
  let startpos = pos `div` 2 - len `div` 2
      endpos   = if odd len
                 then pos `div` 2 + len `div` 2
                 else pos `div` 2 + len `div` 2 - 1
  in show [a!n|n <- [startpos .. endpos]]

listArrayl0 string  = listArray (0,length string - 1) string

sampleText s = concat (replicate 8 s ++ [ "x" ] ++ [ reverse s ] ++ replicate 14 s)

main = print (longestPalindrome (clean (sampleText text)))
</pre>
<p>Here's the relevant change to Rick's Ruby version:</p>
<pre>

def sample_text str
  str * 8 + 'x' + str.reverse + str * 14
end

puts clean(sample_text(TEXT)).longest_palindrome
</pre>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2011/03/13/find-longest-substring-palindrome-in-haskell/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Cracker Barrel Peg Board Puzzle in Haskell</title>
		<link>http://lojic.com/blog/2011/03/10/cracker-barrel-peg-board-puzzle-in-haskell/</link>
		<comments>http://lojic.com/blog/2011/03/10/cracker-barrel-peg-board-puzzle-in-haskell/#comments</comments>
		<pubDate>Thu, 10 Mar 2011 19:24:55 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[haskell]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=831</guid>
		<description><![CDATA[I first wrote a program to solve the Cracker Barrel peg board puzzle (15 holes arranged in a triangle with 14 golf tees) many years ago as youth using the BASIC language. I wish I still had the source to that, because I&#8217;m pretty sure this Haskell version would kick its butt :)
I&#8217;m still trying [...]]]></description>
			<content:encoded><![CDATA[<p>I first wrote a program to solve the Cracker Barrel peg board puzzle (15 holes arranged in a triangle with 14 golf tees) many years ago as youth using the BASIC language. I wish I still had the source to that, because I&#8217;m pretty sure this Haskell version would kick its butt :)</p>
<p>I&#8217;m still trying to get my head around Haskell, so I expect there are <strong>many</strong> possible improvements to this program, but even so, I&#8217;m pleased with how Haskell allows me to express logic.</p>
<pre>
-- Solve the Cracker Barrel Peg Board Puzzle

module Main where

type Pos = (Int, Int)
type Move = (Pos, Pos)
type Board = [ Pos ]

isOccupied b p = elem p b
isEmpty b p    = not (isOccupied b p)
isPos (r,c)    = elem r [0..4] &#038;&#038; elem c [0..r]

-- Possible moves for one position
positionMoves b p = [ (p, dst) | (neighbor, dst) <- pairs,
                      isOccupied b neighbor &#038;&#038;
                      isEmpty b dst ]
  where (r, c) = p
        pairs  = filter (\(p1,p2) -> isPos p1 &#038;&#038; isPos p2)
                   [ ((r + or `div` 2, c + oc `div` 2),(r + or, c + oc)) |
                     (or, oc) <- [ (-2,0), (0,2), (2,2), (2,0), (0,-2), (-2,-2) ] ]

-- Possible moves for all positions on the board
possibleMoves b = concat [ positionMoves b pos | pos <- b ]

-- Make a move and return the new board
move b (src,dst) = dst:filter pred b
  where ((sr,sc),(dr,dc)) = (src,dst)
        neighbor = (div (sr+dr) 2, div (sc+dc) 2)
        pred     = \pos -> (pos /= src) &#038;&#038; (pos /= neighbor)

-- Make moves until the goal position is met
play b p moves =
  if null nextMoves then
    if length b == 1 &#038;&#038; head b == p then reverse moves else []
  else
    tryMoves nextMoves
  where
    nextMoves       = possibleMoves b
    tryMoves []     = []
    tryMoves (m:ms) =
      let result = play (move b m) p (m:moves)
      in if null result then tryMoves ms else result

-- Compute the initial empty position to know the goal, then solve the puzzle
solve b = let emptyPos = head [ (r,c) | r <- [0..4], c <- [0..r], isEmpty b (r,c) ]
          in play b emptyPos []

-- A sample board with the topmost hole empty
board :: Board
board = [ (1,0), (1,1),
          (2,0), (2,1), (2,2),
          (3,0), (3,1), (3,2), (3,3),
          (4,0), (4,1), (4,2), (4,3), (4,4) ]

main = print (solve board)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2011/03/10/cracker-barrel-peg-board-puzzle-in-haskell/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Programming Language Popularity – Part Three</title>
		<link>http://lojic.com/blog/2010/10/08/programming-language-popularity-%e2%80%93-part-three/</link>
		<comments>http://lojic.com/blog/2010/10/08/programming-language-popularity-%e2%80%93-part-three/#comments</comments>
		<pubDate>Fri, 08 Oct 2010 20:30:00 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[arc]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[scheme]]></category>
		<category><![CDATA[sml]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=823</guid>
		<description><![CDATA[I compiled some programming language popularity statistics in April 2009 and October 2009 . Here&#8217;s an update for October 2010:
I made a number of Google searches of the forms below and averaged the results:
"implemented in &#60;language&#62;"
  "written in &#60;language&#62;"
Naturally this is of very limited utility, and the numbers are only useful when comparing relatively [...]]]></description>
			<content:encoded><![CDATA[<p>I compiled some programming language popularity statistics in <a href="http://lojic.com/blog/2009/04/21/programming-language-popularity/">April 2009</a> and <a href="http://lojic.com/blog/2009/10/24/programming-language-popularity-part-two/">October 2009</a> . Here&#8217;s an update for October 2010:</p>
<p>I made a number of Google searches of the forms below and averaged the results:</p>
<pre class="code">"implemented in &lt;language&gt;"
  "written in &lt;language&gt;"</pre>
<p>Naturally this is of very limited utility, and the numbers are only useful when comparing relatively within one column since the number of results Google returns can vary greatly over time.<br />
<!-- use ML and SML --></p>
<table border="0">
<tbody>
<tr>
<th>Language</th>
<th style="text-align: right;">Apr 2009</th>
<th style="text-align: right;">Oct 2009</th>
<th style="text-align: right;">Oct 2010</th>
<th style="text-align: right;"> Position Delta</th>
</tr>
<tr>
<td>PHP</td>
<td style="text-align: right;">680,000</td>
<td style="text-align: right;">5,083,500</td>
<td style="text-align: right;">14,096,000</td>
<td style="text-align: right;">+3</td>
</tr>
<tr>
<td>C</td>
<td style="text-align: right;">1,905,500</td>
<td style="text-align: right;">16,975,000</td>
<td style="text-align: right;">9,675,000</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>C++</td>
<td style="text-align: right;">699,000</td>
<td style="text-align: right;">6,270,000</td>
<td style="text-align: right;">6,510,000</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td><strong>C#</strong></td>
<td style="text-align: right;">349,700</td>
<td style="text-align: right;">2,125,000</td>
<td style="text-align: right;">5,132,000</td>
<td style="text-align: right;"><strong>+4</strong></td>
</tr>
<tr>
<td>Python</td>
<td style="text-align: right;">396,000</td>
<td style="text-align: right;">3,407,000</td>
<td style="text-align: right;">5,114,500</td>
<td style="text-align: right;">+1</td>
</tr>
<tr>
<td>Perl</td>
<td style="text-align: right;">365,500</td>
<td style="text-align: right;">3,132,500</td>
<td style="text-align: right;">4,675,000</td>
<td style="text-align: right;">+1</td>
</tr>
<tr>
<td><strong>JavaScript</strong></td>
<td style="text-align: right;">102,700</td>
<td style="text-align: right;">1,163,000</td>
<td style="text-align: right;">2,120,000</td>
<td style="text-align: right;"><strong>+4</strong></td>
</tr>
<tr>
<td>Java</td>
<td style="text-align: right;">850,000</td>
<td style="text-align: right;">5,118,000</td>
<td style="text-align: right;">1,495,500</td>
<td style="text-align: right;">-5</td>
</tr>
<tr>
<td><strong>Ruby</strong></td>
<td style="text-align: right;">99,650</td>
<td style="text-align: right;">227,000</td>
<td style="text-align: right;">1,426,000</td>
<td style="text-align: right;"><strong>+13</strong></td>
</tr>
<tr>
<td>FORTRAN</td>
<td style="text-align: right;"></td>
<td style="text-align: right;">1,621,000</td>
<td style="text-align: right;">770,850</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td>Lisp Family<sup>1</sup></td>
<td style="text-align: right;">176,507</td>
<td style="text-align: right;">3,489,650</td>
<td style="text-align: right;">399,685</td>
<td style="text-align: right;">-6</td>
</tr>
<tr>
<td><strong>Tcl</strong></td>
<td style="text-align: right;">44,800</td>
<td style="text-align: right;">382,000</td>
<td style="text-align: right;">313,400</td>
<td style="text-align: right;"><strong>+5</strong></td>
</tr>
<tr>
<td><strong>Erlang</strong></td>
<td style="text-align: right;">22,285</td>
<td style="text-align: right;">161,700</td>
<td style="text-align: right;">188,800</td>
<td style="text-align: right;"><strong>+12</strong></td>
</tr>
<tr>
<td>Lisp</td>
<td style="text-align: right;">61,900</td>
<td style="text-align: right;">486,500</td>
<td style="text-align: right;">174,050</td>
<td style="text-align: right;">+1</td>
</tr>
<tr>
<td><strong>COBOL</strong></td>
<td style="text-align: right;"></td>
<td style="text-align: right;">247,300</td>
<td style="text-align: right;">166,435</td>
<td style="text-align: right;"><strong>+6</strong></td>
</tr>
<tr>
<td><strong>Haskell</strong></td>
<td style="text-align: right;">22,550</td>
<td style="text-align: right;">280,500</td>
<td style="text-align: right;">157,150</td>
<td style="text-align: right;"><strong>+4</strong></td>
</tr>
<tr>
<td>ML Family<sup>2</sup></td>
<td style="text-align: right;">29,062</td>
<td style="text-align: right;">1,003,800</td>
<td style="text-align: right;">149,005</td>
<td style="text-align: right;">-5</td>
</tr>
<tr>
<td><strong>Lua</strong></td>
<td style="text-align: right;">13,065</td>
<td style="text-align: right;">131,800</td>
<td style="text-align: right;">128,150</td>
<td style="text-align: right;"><strong>+9</strong></td>
</tr>
<tr>
<td>Common Lisp</td>
<td style="text-align: right;">20,600</td>
<td style="text-align: right;">554,500</td>
<td style="text-align: right;">112,750</td>
<td style="text-align: right;">-5</td>
</tr>
<tr>
<td>Prolog</td>
<td style="text-align: right;">17,750</td>
<td style="text-align: right;">390,500</td>
<td style="text-align: right;">100,000</td>
<td style="text-align: right;">-4</td>
</tr>
<tr>
<td>OCaml</td>
<td style="text-align: right;">22,000</td>
<td style="text-align: right;">343,500</td>
<td style="text-align: right;">99,050</td>
<td style="text-align: right;">-3</td>
</tr>
<tr>
<td>Scheme</td>
<td style="text-align: right;">86,450</td>
<td style="text-align: right;">2,100,000</td>
<td style="text-align: right;">82,650</td>
<td style="text-align: right;">-13</td>
</tr>
<tr>
<td><strong>Scala</strong></td>
<td style="text-align: right;">3,570</td>
<td style="text-align: right;">66,250</td>
<td style="text-align: right;">65,950</td>
<td style="text-align: right;"><strong>+6</strong></td>
</tr>
<tr>
<td>Smalltalk</td>
<td style="text-align: right;">9,105</td>
<td style="text-align: right;">187,500</td>
<td style="text-align: right;">56,950</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td>(S)ML<sup>3</sup></td>
<td style="text-align: right;">5,173</td>
<td style="text-align: right;">590,700</td>
<td style="text-align: right;">42,130</td>
<td style="text-align: right;">-12</td>
</tr>
<tr>
<td>Forth</td>
<td style="text-align: right;">6,465</td>
<td style="text-align: right;">146,450</td>
<td style="text-align: right;">25,880</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td>Clojure</td>
<td style="text-align: right;">782</td>
<td style="text-align: right;">62,200</td>
<td style="text-align: right;">23,525</td>
<td style="text-align: right;">+3</td>
</tr>
<tr>
<td>Caml</td>
<td style="text-align: right;">1,889</td>
<td style="text-align: right;">69,600</td>
<td style="text-align: right;">7,825</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td>Arc</td>
<td style="text-align: right;">6,775</td>
<td style="text-align: right;">286,500</td>
<td style="text-align: right;">6,710</td>
<td style="text-align: right;">-10</td>
</tr>
<tr>
<td>Io</td>
<td style="text-align: right;">1,760</td>
<td style="text-align: right;">198,500</td>
<td style="text-align: right;">3,025</td>
<td style="text-align: right;">-7</td>
</tr>
</tbody>
</table>
<p><sup>1</sup> combines Lisp, Scheme, Common Lisp, Arc &amp; Clojure<br />
<sup>2</sup> combines OCaml, (S)ML, Caml<br />
<sup>3</sup> summed separate searches for sml and ml</p>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2010/10/08/programming-language-popularity-%e2%80%93-part-three/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Git commit message style</title>
		<link>http://lojic.com/blog/2010/08/30/git-commit-message-style/</link>
		<comments>http://lojic.com/blog/2010/08/30/git-commit-message-style/#comments</comments>
		<pubDate>Mon, 30 Aug 2010 17:15:25 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=818</guid>
		<description><![CDATA[I just learned something about how git handles multi-line commit messages. If a commit message has a blank second line, git will treat the first line as the &#8220;subject&#8221; and the 3rd and following lines as the &#8220;body&#8221;. This will allow some nice things to be done with the git log command.
For example, the following [...]]]></description>
			<content:encoded><![CDATA[<p>I just learned something about how git handles multi-line commit messages. If a commit message has a blank second line, git will treat the first line as the &#8220;subject&#8221; and the 3rd and following lines as the &#8220;body&#8221;. This will allow some nice things to be done with the git log command.</p>
<p>For example, the following command:</p>
<pre>
git log --pretty=format:"%ai %an: %s%n%n%b%n"
</pre>
<p>Will produce output such as this:</p>
<pre>
2010-08-30 13:10:51 -0400 Brian Adkins: This is my second commit for this example.

And this is the body for the second commit.
Second line of the body.

2010-08-30 13:07:23 -0400 Brian Adkins: This text will be treated as the subject.

This text will be treated as the body. The subject should be
a short summary of the commit since you may want to show just
the subject on some git log invocations.
</pre>
<p>If you just want to see the &#8220;subject&#8221;, use:</p>
<pre>
git log --pretty=format:"%ai %an: %s%n"
</pre>
<p>Which will display as follows:</p>
<pre>
2010-08-30 13:10:51 -0400 Brian Adkins: This is my second commit for this example.

2010-08-30 13:07:23 -0400 Brian Adkins: This text will be treated as the subject.
</pre>
<p>See &#8220;git log &#8211;help&#8221; for various formatting specifications.</p>
<p>Thanks to Nathaniel Talbott for the chat message that prompted me to look into this.</p>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2010/08/30/git-commit-message-style/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Switching from CarbonEmacs to Emacs.app</title>
		<link>http://lojic.com/blog/2010/03/17/switching-from-carbonemacs-to-emacs-app/</link>
		<comments>http://lojic.com/blog/2010/03/17/switching-from-carbonemacs-to-emacs-app/#comments</comments>
		<pubDate>Wed, 17 Mar 2010 05:42:42 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[osx]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=796</guid>
		<description><![CDATA[Thanks to a tip from David Joyner, I discovered that the current version of Emacs will easily build an Emacs.app application for Mac OSX i.e. I no longer need to install the CarbonEmacs application. I&#8217;m thankful to Seiji Zenitani for creating CarbonEmacs, but I&#8217;m glad to be able to build the app directly from the [...]]]></description>
			<content:encoded><![CDATA[<p>Thanks to a tip from David Joyner, I discovered that the current version of Emacs will easily build an Emacs.app application for Mac OSX i.e. I no longer need to install the CarbonEmacs application. I&#8217;m thankful to Seiji Zenitani for creating CarbonEmacs, but I&#8217;m glad to be able to build the app directly from the latest Emacs source code.</p>
<p>Here&#8217;s what I did:</p>
<h1>Get the source code and build it</h1>
<pre>
git clone git://git.savannah.gnu.org/emacs.git
cd emacs
./configure --with-ns
make install
</pre>
<h1>Copy Emacs.app to Applications</h1>
<p>Drag nextstep/Emacs.app to Applications</p>
<h2>Modify Emacs config files</h2>
<p>I had several configuration items I needed to adjust.</p>
<h3>carbon-emacs-package-add-to-path no longer exists</h2>
<p>I used the above command to set the path to allow running programs via shell-command as follows:</p>
<pre>
(carbon-emacs-package-add-to-path "/Users/badkins/sync/bin")
(defun my-fun ()
  (interactive)
  (shell-command "my_ruby_script.rb"))
</pre>
<p>I found a comment by Alex Payne on Ola Bini&#8217;s blog that provided an equivalent for Emacs.app:</p>
<pre>
(setq path "/Users/badkins/sync/bin")
(setenv "PATH" path)
</pre>
<h3>Use command for meta instead of alt/option</h3>
<p>The newly built Emacs.app used the alt/option key for meta instead of the command key that I was used to with CarbonEmacs. The following (found on Hacker News) took care of that:</p>
<pre>
(setq ns-command-modifier 'meta)
</pre>
<p>Prior to the above, I had tried the following. It worked, but was more verbose:</p>
<pre>
(setq mac-option-key-is-meta nil)
(setq mac-command-key-is-meta t)
(setq mac-command-modifier 'meta)
(setq mac-option-modifier nil)
</pre>
<h3>Allow use of command-h to minimize Emacs</h3>
<p>After the above fix for the command key, I could no longer minimize Emacs via command-h because Emacs mapped M-h to a command. The following key binding allowed using M-h to minimize again:</p>
<pre>
(global-set-key (kbd "M-h") 'ns-do-hide-emacs)
</pre>
<h3>Customize exec-path variable</h3>
<p>I was having difficulty using the built-in vc git support. It turns out that Emacs wasn&#8217;t able to find the git command because it wasn&#8217;t in the exec-path. I customized the exec-path variable to include /opt/local/bin where git resides as follows (it&#8217;s within the custom-set-variables invocation):</p>
<pre>
 '(exec-path (quote ("/usr/bin" "/bin" "/usr/sbin" "/sbin" "/Applications/Emacs.app/Contents/MacOS/bin" "/opt/local/bin")))
</pre>
<h2>Emacs is Awesome</h2>
<p>That was all it took to get the latest Emacs up and running equivalently to CarbonEmacs for me. I&#8217;m more pleased with Emacs today than when I started using it in earnest in 2008. I&#8217;m continually learning new things to be more productive. There are just so many things that it does very well, and it&#8217;s so extensible and introspective.</p>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2010/03/17/switching-from-carbonemacs-to-emacs-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Programming Language Popularity &#8211; Part Two</title>
		<link>http://lojic.com/blog/2009/10/24/programming-language-popularity-part-two/</link>
		<comments>http://lojic.com/blog/2009/10/24/programming-language-popularity-part-two/#comments</comments>
		<pubDate>Sat, 24 Oct 2009 15:23:23 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[arc]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[forth]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[io]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[lua]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[scala]]></category>
		<category><![CDATA[scheme]]></category>
		<category><![CDATA[smalltalk]]></category>
		<category><![CDATA[sml]]></category>
		<category><![CDATA[tcl]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=781</guid>
		<description><![CDATA[I compiled some programming language popularity statistics in April and mentioned I&#8217;d update the results in 6 months, so here they are:
I made a number of Google searches of the forms below and averaged the results:
"implemented in &#60;language&#62;"
"written in &#60;language&#62;"



Language
# Results
Apr 09
# Results
Oct 09
Position
Delta


C
1,905,500
16,975,000
0


C++
699,000
6,270,000
+1


Java
850,000
5,118,000
-1


PHP
680,000
5,083,500
0


Lisp Family1
176,507
3,489,650
+3


Python
396,000
3,407,000
-1


Perl
365,500
3,132,500
-1


C#
349,700
2,125,000
-1


Scheme
86,450
2,100,000
+2


FORTRAN

1,621,000
N/A


JavaScript
102,700
1,163,000
-1


ML Family2
29,062
1,003,800
+3



(S)ML3
5,173
590,700
+12


Common Lisp
20,600
554,500
+5


Lisp
61,900
486,500
-2


Prolog
17,750
390,500
+4


Tcl
44,800
382,000
-3


OCaml
22,000
343,500
0


Arc
6,775
286,500
+4


Haskell
22,550
280,500
-4


COBOL

247,300
N/A


Ruby
99,650
227,000
-10


Io
1,760
198,500
+6


Smalltalk
9,105
187,500
-1


Erlang
22,285
161,700
-7


Forth
6,465
146,450
-1


Lua
13,065
131,800
-5


Caml
1,889
69,600
0


Scala
3,570
66,250
-2


Clojure
782
62,200
0



1 combines Lisp, Scheme, Common Lisp, Arc &#38; Clojure
2 [...]]]></description>
			<content:encoded><![CDATA[<p>I compiled some <a href="http://lojic.com/blog/2009/04/21/programming-language-popularity/">programming language popularity</a> statistics in April and mentioned I&#8217;d update the results in 6 months, so here they are:</p>
<p>I made a number of Google searches of the forms below and averaged the results:</p>
<pre class="code">"implemented in &lt;language&gt;"
"written in &lt;language&gt;"</pre>
<table border="0">
<tbody>
<tr>
<th>Language</th>
<th style="text-align: right;"># Results<br />
Apr 09</th>
<th style="text-align: right;"># Results<br />
Oct 09</th>
<th style="text-align: right;">Position<br />
Delta</th>
</tr>
<tr>
<td>C</td>
<td style="text-align: right;">1,905,500</td>
<td style="text-align: right;">16,975,000</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td><strong>C++</strong></td>
<td style="text-align: right;">699,000</td>
<td style="text-align: right;">6,270,000</td>
<td style="text-align: right;"><strong>+1</strong></td>
</tr>
<tr>
<td>Java</td>
<td style="text-align: right;">850,000</td>
<td style="text-align: right;">5,118,000</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>PHP</td>
<td style="text-align: right;">680,000</td>
<td style="text-align: right;">5,083,500</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td><strong>Lisp Family<sup>1</sup></strong></td>
<td style="text-align: right;">176,507</td>
<td style="text-align: right;">3,489,650</td>
<td style="text-align: right;"><strong>+3</strong></td>
</tr>
<tr>
<td>Python</td>
<td style="text-align: right;">396,000</td>
<td style="text-align: right;">3,407,000</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>Perl</td>
<td style="text-align: right;">365,500</td>
<td style="text-align: right;">3,132,500</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>C#</td>
<td style="text-align: right;">349,700</td>
<td style="text-align: right;">2,125,000</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td><strong>Scheme</strong></td>
<td style="text-align: right;">86,450</td>
<td style="text-align: right;">2,100,000</td>
<td style="text-align: right;"><strong>+2</strong></td>
</tr>
<tr>
<td>FORTRAN</td>
<td style="text-align: right;"></td>
<td style="text-align: right;">1,621,000</td>
<td style="text-align: right;">N/A</td>
</tr>
<tr>
<td>JavaScript</td>
<td style="text-align: right;">102,700</td>
<td style="text-align: right;">1,163,000</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td><strong>ML Family<sup>2</sup></strong></td>
<td style="text-align: right;">29,062</td>
<td style="text-align: right;">1,003,800</td>
<td style="text-align: right;"><strong>+3</strong></td>
</tr>
<p><!-- use ML and SML --></p>
<tr>
<td><strong>(S)ML<sup>3</sup></strong></td>
<td style="text-align: right;">5,173</td>
<td style="text-align: right;">590,700</td>
<td style="text-align: right;"><strong>+12</strong></td>
</tr>
<tr>
<td><strong>Common Lisp</strong></td>
<td style="text-align: right;">20,600</td>
<td style="text-align: right;">554,500</td>
<td style="text-align: right;"><strong>+5</strong></td>
</tr>
<tr>
<td>Lisp</td>
<td style="text-align: right;">61,900</td>
<td style="text-align: right;">486,500</td>
<td style="text-align: right;">-2</td>
</tr>
<tr>
<td><strong>Prolog</strong></td>
<td style="text-align: right;">17,750</td>
<td style="text-align: right;">390,500</td>
<td style="text-align: right;"><strong>+4</strong></td>
</tr>
<tr>
<td>Tcl</td>
<td style="text-align: right;">44,800</td>
<td style="text-align: right;">382,000</td>
<td style="text-align: right;">-3</td>
</tr>
<tr>
<td>OCaml</td>
<td style="text-align: right;">22,000</td>
<td style="text-align: right;">343,500</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td><strong>Arc</strong></td>
<td style="text-align: right;">6,775</td>
<td style="text-align: right;">286,500</td>
<td style="text-align: right;"><strong>+4</strong></td>
</tr>
<tr>
<td>Haskell</td>
<td style="text-align: right;">22,550</td>
<td style="text-align: right;">280,500</td>
<td style="text-align: right;">-4</td>
</tr>
<tr>
<td>COBOL</td>
<td style="text-align: right;"></td>
<td style="text-align: right;">247,300</td>
<td style="text-align: right;">N/A</td>
</tr>
<tr>
<td>Ruby</td>
<td style="text-align: right;">99,650</td>
<td style="text-align: right;">227,000</td>
<td style="text-align: right;">-10</td>
</tr>
<tr>
<td><strong>Io</strong></td>
<td style="text-align: right;">1,760</td>
<td style="text-align: right;">198,500</td>
<td style="text-align: right;"><strong>+6</strong></td>
</tr>
<tr>
<td>Smalltalk</td>
<td style="text-align: right;">9,105</td>
<td style="text-align: right;">187,500</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>Erlang</td>
<td style="text-align: right;">22,285</td>
<td style="text-align: right;">161,700</td>
<td style="text-align: right;">-7</td>
</tr>
<tr>
<td>Forth</td>
<td style="text-align: right;">6,465</td>
<td style="text-align: right;">146,450</td>
<td style="text-align: right;">-1</td>
</tr>
<tr>
<td>Lua</td>
<td style="text-align: right;">13,065</td>
<td style="text-align: right;">131,800</td>
<td style="text-align: right;">-5</td>
</tr>
<tr>
<td>Caml</td>
<td style="text-align: right;">1,889</td>
<td style="text-align: right;">69,600</td>
<td style="text-align: right;">0</td>
</tr>
<tr>
<td>Scala</td>
<td style="text-align: right;">3,570</td>
<td style="text-align: right;">66,250</td>
<td style="text-align: right;">-2</td>
</tr>
<tr>
<td>Clojure</td>
<td style="text-align: right;">782</td>
<td style="text-align: right;">62,200</td>
<td style="text-align: right;">0</td>
</tr>
</tbody>
</table>
<p><sup>1</sup> combines Lisp, Scheme, Common Lisp, Arc &amp; Clojure<br />
<sup>2</sup> combines OCaml, (S)ML, Caml<br />
<sup>3</sup> summed separate searches for sml and ml</p>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2009/10/24/programming-language-popularity-part-two/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Daniel Weinreb re: Lisp use at ITA</title>
		<link>http://lojic.com/blog/2009/08/29/daniel-weinreb-re-lisp-use-at-ita/</link>
		<comments>http://lojic.com/blog/2009/08/29/daniel-weinreb-re-lisp-use-at-ita/#comments</comments>
		<pubDate>Sat, 29 Aug 2009 18:31:17 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[business]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[lisp]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=770</guid>
		<description><![CDATA[Some random notes:

650 KLOC plus 150 KLOC of open source code
100 people on the team, 70 programmers
SBCL for the QPX product
Clozure CL for the reservations product
Availability requirement: four 9&#8217;s => less than 53 minutes downtime per year

Latency agreement

90% of requests w/in 300 ms
5% of requests w/in 600 ms
5% of requests w/in 1,200 ms


Java presentation layer, [...]]]></description>
			<content:encoded><![CDATA[<p>Some random notes:</p>
<ul>
<li>650 KLOC plus 150 KLOC of open source code</li>
<li>100 people on the team, 70 programmers</li>
<li>SBCL for the QPX product</li>
<li>Clozure CL for the reservations product</li>
<li>Availability requirement: four 9&#8217;s => less than 53 minutes downtime per year</li>
<li>
Latency agreement</p>
<ul>
<li>90% of requests w/in 300 ms</li>
<li>5% of requests w/in 600 ms</li>
<li>5% of requests w/in 1,200 ms</li>
</ul>
</li>
<li>Java presentation layer, Common Lisp stateless business layer, Oracle data layer</li>
<li>Daniel is very positive about Clojure</li>
<li>Some links from the talk:
<ul>
<li><a href="http://common-lisp.net/~dlw/LispSurvey.html">Survey of Common Lisp Implementations</a></li>
<li><a href="http://ilc2009.scheming.org/">International Lisp Conference 2009 Discusison Forum</a></li>
<li><a href="http://danweinreb.org/blog">Dan Weinreb&#8217;s Blog</a></li>
</ul>
</li>
</ul>
<p><br/><br />
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/xquJvmHF3S8&#038;hl=en&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/xquJvmHF3S8&#038;hl=en&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2009/08/29/daniel-weinreb-re-lisp-use-at-ita/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Haskell In The Finals</title>
		<link>http://lojic.com/blog/2009/08/18/haskell-in-the-finals/</link>
		<comments>http://lojic.com/blog/2009/08/18/haskell-in-the-finals/#comments</comments>
		<pubDate>Tue, 18 Aug 2009 16:36:16 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[haskell]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=717</guid>
		<description><![CDATA[As I explain in 2009 Programming Language Plan, I&#8217;ve been in the process of evaluating programming languages to determine their suitability for use in my work. I&#8217;ve been proceeding on two fronts &#8211; statically typed functional programming languages and the venerated Lisp family.
Haskell The Hope Of The Statically Typed Family
After many hours of research and [...]]]></description>
			<content:encoded><![CDATA[<p>As I explain in <a href="http://lojic.com/blog/2009/04/27/2009-programming-language-plan/">2009 Programming Language Plan</a>, I&#8217;ve been in the process of evaluating programming languages to determine their suitability for use in my work. I&#8217;ve been proceeding on two fronts &#8211; statically typed functional programming languages and the venerated Lisp family.</p>
<p><strong>Haskell The Hope Of The Statically Typed Family</strong></p>
<p>After many hours of research and a brief dive into Standard ML, I&#8217;ve selected Haskell as <em>the</em> best candidate for me to evaluate statically typed functional programming languages. At this point, I&#8217;m subjectively biased against <em>statically typed</em> functional programming languages because of the enjoyment and productivity I&#8217;ve found in Ruby &amp; Lisp, but my only experience with statically typed languages (C, C++, Java) has not been representative of <em>good</em> statically typed languages, so I&#8217;m reluctant to form a strong opinion of static typing before I&#8217;ve become proficient in a <em>good</em> statically typed language. </p>
<p>There are, of course, a number of respected statically typed functional programming languages, but I think Haskell provides me with the best opportunity to make a personal assessment regarding the benefits of static typing for my particular situation, and I think someone would be hard pressed to convince me that it&#8217;s a poor choice objectively.</p>
<p><strong>There Can Be Only One</strong></p>
<p>After working halfway through <em>Programming in Standard ML</em> by Robert Harper, I realized that I enjoy the language and it seems <em>simpler</em> &amp; <em>cleaner</em> than Haskell, but I also realized that I only have time to become truly <em>proficient</em> in one statically typed functional programming language in the near future. I feel that a reasonable level of proficiency is required to evaluate a language well. I have seen many examples of someone, with only a little knowledge of a programming language, making an unfounded criticism of a programming language, or a particular feature, only to be corrected with an accurate, elegant and convincing counter argument by someone who is experienced with the language. </p>
<p>A quick survey of a language won&#8217;t be enough for me to make a decision on some key points such as static vs. dynamic, nonstrict vs. strict, pure vs. impure, etc. as well as important peripheral issues such as existing libraries, tools, etc. &#8211; it&#8217;s going to require understanding some of the subtleties of the language and writing enough code to get a feel for the language, so I felt I needed to limit my choice to one statically typed FPL.</p>
<p><strong>Static vs. Dynamic</strong></p>
<p>Clearly <em>both</em> static and dynamic typing work well for large numbers of people. One of my goals is simply to answer the static vs. dynamic question for <em>myself</em> given my preferences and the type of software I want to develop. I&#8217;d previously decided to learn <em>both</em> Standard ML and Haskell, so my reasons below for choosing Haskell are primarily with respect to comparing the two languages:</p>
<h3>Haskell Is Pure And Lazy</h3>
<p>I&#8217;m already familiar with <em>impure</em>, or multi-paradigm, programming languages that offer some functional features but allow imperative programming, so being forced to program in a purely functional manner and abandon my comfort zone of imperative patterns is an advantage for me. I have no experience with lazy languages, so Haskell offers an opportunity to gain more experience with laziness :). </p>
<p>In some respects, Haskell is <em>more</em> different than Lisp compared to other statically typed functional programming languages, so it&#8217;s a good point of comparison. It may end up being the ultimate <em>death match</em> :)</p>
<ul>
<li>Static vs. Dynamic</li>
<li>Nonstrict vs. Strict</li>
<li>Rich/Complex Syntax vs. Simpler Syntax</li>
<li>Pure vs. Impure/Multi-paradigm</li>
</ul>
<h3>Active Community</h3>
<p>Haskell has a very active community. Although I&#8217;m skeptical about whether a statically typed functional programming language will be suitable for the type of work I want to do with it, it makes sense to choose one that has a reasonable shot, and I don&#8217;t personally feel that Standard ML does &#8211; it was mainly to be an introduction to functional programming and a stepping stone to another FPL.</p>
<p>Part of the reason I don&#8217;t feel that Standard ML has a reasonable shot is that it feels dated and somewhat abandoned. Functional programming languages are niche languages to begin with, but it seems that Haskell and OCaml both have fairly strong communities.</p>
<h3>Cool Features</h3>
<p>Although I think Haskell&#8217;s custom of continuing to add cutting edge research features into the language may have some disadvantages if not done well, i.e. making the language messier and complicated, for my primary purpose of evaluating the benefits of statically typed languages, I think having more advanced features is an advantage over Standard ML. If a language with such an active research community as Haskell fails to convince me of the benefits of static typing, then it may just not be for me.</p>
<p><em>Monads</em> and <em>type classes</em> seem interesting, and Haskell provides an opportunity to learn them. Monads seem useful outside of Haskell, so the time spent learning about them can be leveraged. I already like <em>list comprehensions</em>, so it&#8217;s nice to have them available again.</p>
<p>Learning some of the advanced features of Haskell will be beneficial to me regardless of whether I continue programming in Haskell or decide to go with the Lisp family.</p>
<h3>Textual Resources</h3>
<p>Standard ML actually has a surprising number of good texts available, so I don&#8217;t think Haskell offers a big advantage here, but in my particular case, I already own two Haskell texts &#8211; <em>Programming in Haskell</em> by Graham Hutton and <em>The Craft of Functional Programming</em> by Simon Thompson. Also, Chris Okasaki&#8217;s <em>Purely Functional Data Structures</em> provides Haskell examples as does Richard Bird&#8217;s <em>Introduction to Functional Programming using Haskell (2nd ed.)</em>. Lastly, I think <em>Real World Haskell</em> may be very helpful.</p>
<p><strong>Haskell Crash Course</strong></p>
<p>My goal now on the statically typed front is to become as proficient in Haskell as I can in a very short period of time. There seem to be plenty of resources available, but if you&#8217;re aware of any particularly helpful resources or tips, feel free to add a comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2009/08/18/haskell-in-the-finals/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

