<?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/tag/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>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>Programming in Standard ML &#8211; Part 3</title>
		<link>http://lojic.com/blog/2009/08/15/programming-in-standard-ml-part-3/</link>
		<comments>http://lojic.com/blog/2009/08/15/programming-in-standard-ml-part-3/#comments</comments>
		<pubDate>Sat, 15 Aug 2009 19:43:30 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[sml]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=603</guid>
		<description><![CDATA[Table of Contents
Chapter 6 &#8211; Case Analysis
Tuple types are homogeneous e.g. all values of type int*real are pairs containing an int and a real. Match failures occur at compile time. Types that have more than one form, such as int, are heterogeneous. Pattern matches fail at run time as a bind failure.
ML defines functions over [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://lojic.com/blog/2009/05/02/programming-in-standard-ml-part-1/">Table of Contents</a></p>
<h2>Chapter 6 &#8211; Case Analysis</h2>
<p>Tuple types are <em>homogeneous</em> e.g. all values of type int*real are pairs containing an int and a real. Match failures occur at compile time. Types that have more than one form, such as int, are <em>heterogeneous</em>. Pattern matches fail at run time as a bind failure.</p>
<p>ML defines functions over heterogeneous types using <em>clausal function expressions</em>. For example:</p>
<pre class="code">
fn pat1 => exp1
 | pat2 => exp2
 | ...
 | patn => expn
</pre>
<p>Each component <em>pat => exp</em> is called a <em>clause</em>, or a <em>rule</em>. The entire assembly of rules is a called a <em>match</em>. For example:</p>
<pre class="code">
val recip : int -> int =
    fn 0 => 0 | n:int => 1 div n
</pre>
<p>The <code>fun</code> notation is generalized so we can be more concise:</p>
<pre class="code">
fun recip 0 = 0
  | recip (n:int) = 1 div n
</pre>
<p>Case analysis on the values of a heterogeneous type is performed by application of a clausally-defined function. The notation:</p>
<pre class="code">
case exp
  of pat1 => exp1
   | ...
   | patn => expn
</pre>
<p>is short for the application:</p>
<pre class="code">
(fn pat1 => exp1
  | ...
  | patn => expn)
exp
</pre>
<p>Matches are subject to two forms of &#8220;sanity check&#8221; &#8211; <em>exhaustiveness checking</em> and <em>redundancy checking</em>.</p>
<h2>Chapter 7 &#8211; Recursive Functions</h2>
<p>For a function to be able to call itself, it needs a name. For example:</p>
<pre class="code">
val rec factorial : int->int =
    fn 0 => 1 | n:int => n * factorial (n-1)
</pre>
<p>or using fun notation:</p>
<pre class="code">
fun factorial 0 = 1
  | factorial (n:int) = n * factorial (n-1)
</pre>
<h3>Iteration</h3>
<p>If we define a helper function that accepts an <em>accumulator</em> we can reduce the storage needed:</p>
<pre class="code">
fun helper (0,r:int) = r
  | helper (n:int,r:int) = helper (n-1,n*r)
fun factorial (n:int) = helper (n,1)
</pre>
<p>It&#8217;s better programming style to hide the helper function w/in a local declaration:</p>
<pre class="code">
local
    fun helper (0,r:int) = r
      | helper (n:int,r:int) = helper (n-1,n*r)
in
    fun factorial (n:int) = helper (n,1)
end
</pre>
<p><em>Tail recursive</em> functions are analogous to loops in imperative languages &#8211; they iterate the computation w/o needing auxiliary storage.</p>
<h3>Mutual Recursion</h3>
<p>Definitions which are <em>mutually recursive</em> can be joined together with the and keyword to indicate they are defined simultaneously by mutual recursion:</p>
<pre class="code">
fun even 0 = true
  | even n = odd (n-1)
and odd 0 = false
  | odd n = even (n-1)
</pre>
<h2>Chapter 8 &#8211; Type Inference and Polymorphism</h2>
<p>Standard ML allows you to omit type information whenever it can be determined from context. Consider the following:</p>
<pre class="code">
fn s:string => s ^ "\n"
</pre>
<p>There is no need to declare the type of s since it can be inferred from the context, so we may write:</p>
<pre class="code">
fn s => s ^ "\n"
</pre>
<p>A <em>type scheme</em> is a type expression involving one or more <em>type variables</em> standing for an unknown, but arbitrary type expression. Type variables are written &#8216;a (pronounced alpha), &#8216;b (pronounced beta), etc. For example, the type scheme  &#8216;a->&#8217;a has instances int->int, string->string, (int*int)->(int*int), and (&#8217;b->&#8217;b)->(&#8217;b->&#8217;b), etc. It does <em>not</em> have the type int->string.</p>
<p>We may bind an identity function to the variable I as follows:</p>
<pre class="code">
val I : 'a->'a = fn x=>x
</pre>
<p>We may also write:</p>
<pre class="code">
fun I(x:'a) : 'a = x
</pre>
<p>Standard ML eliminates the need to ascribe a type scheme to the variable:</p>
<pre class="code">
val I = fn x=>x

or

fun I(x) = x
</pre>
<h2>Chapter 9 &#8211; Programming with Lists</h2>
<p>The values of type <em>type</em> list are the finite lists of values of type <em>type</em>:</p>
<pre class="code">
1. nil is a value of type typ list.
2. if h is a value of type typ, and t is a value of type typ list,
   then h::t is a value of type typ list.
3. Nothing else is a value of type typ list.
</pre>
<p>The type expression <em>typ</em> list is a postfix notation for the application of the type constructor list to the type typ.</p>
<p>A value <em>val</em> of type <em>typ</em> list has the form:<br />
val1 :: (val2 :: (&#8230; :: (valn :: nil) &#8230; ))</p>
<p>The :: operator is <em>right-associative</em>, so we may omit parentheses:<br />
val1 :: val2 :: &#8230; :: valn :: nil</p>
<p>Or, we may use list notation:<br />
[ val1, val2, ..., valn ]</p>
<h3>Computing With Lists</h3>
<p>Some examples:</p>
<pre class="code">
fun length nil = 0
  | length (_::t) = 1 + length t
</pre>
<p>Note we do not give a name to the head of the list, instead we use a wildcard _</p>
<pre class="code">
fun append (nil, l) = l
  | append (h::t, l) = h :: append (t, l)
</pre>
<p>The latter is built into Standard ML and is written using infix as: exp1 @ exp2</p>
<pre class="code">
fun rev nil = nil
  | rev (h::t) = rev t @ [h]
</pre>
<p>The running time of the latter is O(<em>n</em><sup>2</sup>). The following definition makes use of an accumulator and has a running time of O(<em>n</em>):</p>
<pre class="code">
local
    fun helper (nil, a) = a
      | helper (h::t, a) = helper (t, h::a)
in
    fun rev' l = helper (l, nil)
end
</pre>
<h2>Chapter 10 &#8211; Concrete Data Types</h2>
<h3>Non-Recursive Datatypes</h3>
<p>Example of <em>nullary</em> i.e. zero argument, constructors:</p>
<pre class="code">
datatype suit = Spades | Hearts | Diamonds | Clubs
</pre>
<p>It is conventional to capitalize the names of value constructors, but this is not required by the language.</p>
<p>Datatypes may be <em>parameterized</em> by a type:</p>
<pre class="code">
datatype 'a option = NONE | SOME of 'a
</pre>
<p>The values are NONE or Some <em>val</em>, where <em>val</em> is a value of type <em>typ</em>. The option type constructor is pre-defined in Standard ML.</p>
<p>Option types can also be used in aggregate data structures:</p>
<pre class="code">
type entry = { name:string, spouse string option }
</pre>
<p>An entry for an unmarried person would have a spouse field with a value of NONE.</p>
<h3>Recursive Datatypes</h3>
<pre class="code">
datatype 'a tree =
  Empty |
  Node of 'a tree * 'a * 'a tree
</pre>
<p>1. The empty tree Empty is a binary tree.<br />
2. If tree_1 and tree_2 are binary trees, and val is a value of type type, then Node (tree_1, val, tree_2) is a binary tree.<br />
3. Nothing else is a binary tree.<br />
A function to compute the <em>height</em> of a binary tree, and one to compute the number of nodes:</p>
<pre class="code">
fun height Empty = 0
  | height (Node (lft, _, rht)) = 1 + max (height lft, height rht)

fun size Empty = 0
  | size (Node (lft, _, rht)) = 1 + size lft + size rht
</pre>
<h3>Heterogeneous Data Structures</h3>
<p>The tree data type above requires that the type of the data items at the nodes must be the same for every node of the tree. To represent a heterogeneous tree, the data item must be labelled with enough info to determine the type at run-time.</p>
<pre class="code">
datatype int_or_string =
  Int of int |
  String of string

type int_or_string =
  int_or_string tree
</pre>
<p>Datatype declarations and pattern matching can be useful for manipulating the abstract syntax of a language. Consider an example representing arithmetic expressions:</p>
<pre class="code">
datatype expr =
  Numeral of int |
  Plus of expr * expr |
  Times of expr * expr

fun eval (Numeral n) = Numeral n
  | eval (Plus (e1, e2)) =
    let
        val Numeral n1 = eval e1
        val Numeral n2 = eval e2
    in
        Numeral (n1+n2)
    end
  | eval (Times (e1, e2)) =
    let
        val Numeral n1 = eval e1
        val Numeral n2 = eval e2
    in
        Numeral (n1*n2)
    end
</pre>
<p>If we extend the expr datatype as follows:</p>
<pre class="code">
datatype expr =
  Numeral of int |
  Plus of expr * expr |
  Times of expr * expr
  Recip of expr
</pre>
<p>The compiler will complain about eval being incompatible with the new version of expr. Recompiling eval will produce an inexhaustive match warning since eval lacks a case for Recip. This is one of the benefits of static typing provided in Standard ML.</p>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2009/08/15/programming-in-standard-ml-part-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Send Growl Notifications From Carbon Emacs On OSX</title>
		<link>http://lojic.com/blog/2009/08/06/send-growl-notifications-from-carbon-emacs-on-osx/</link>
		<comments>http://lojic.com/blog/2009/08/06/send-growl-notifications-from-carbon-emacs-on-osx/#comments</comments>
		<pubDate>Thu, 06 Aug 2009 11:42:52 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[applescript]]></category>
		<category><![CDATA[emacs]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=666</guid>
		<description><![CDATA[I found a handy article for sending growl notifications from Emacs and made some modifications for my particular setup.
Step One: Register Emacs with Growl
We need to register Carbon Emacs with Growl. This is a one time setup task. The following AppleScript script can be run in Script Editor.

tell application "GrowlHelperApp"
	-- Declare a list of notification [...]]]></description>
			<content:encoded><![CDATA[<p>I found <a href="http://alexott.blogspot.com/2008/11/working-with-growl-from-emacs.html">a handy article</a> for sending <a href="http://growl.info/">growl notifications</a> from <a href="http://homepage.mac.com/zenitani/emacs-e.html">Emacs</a> and made some modifications for my particular setup.</p>
<p><strong>Step One: Register Emacs with Growl</strong><br />
We need to register Carbon Emacs with Growl. This is a one time setup task. The following AppleScript script can be run in Script Editor.</p>
<pre class="code">
tell application "GrowlHelperApp"
	-- Declare a list of notification types
	set the allNotificationsList to {"Emacs Notification"}

	-- Declare list of active notifications.  If some of them
	-- isn't activated, user can do this later via preferences
	set the enabledNotificationsList to {"Emacs Notification"}

	-- Register our application in Growl.
	register as application "Emacs.app" all notifications allNotificationsList default notifications enabledNotificationsList icon of application "Emacs.app"
end tell
</pre>
<p><strong>Step Two: Create Growl Notification Script</strong><br />
This is a template of the AppleScript that will be used in the Emacs Lisp function. It can be tested by executing it in the Script Editor.</p>
<pre class="code">
tell application "GrowlHelperApp"
	notify with name "Emacs Notification" title "Emacs alert" description "Message!!!" application name "Emacs.app"
end tell
</pre>
<p><strong>Step Three: Emacs Lisp Function</strong><br />
Create an Emacs Lisp function that can be invoked with a title and message.</p>
<pre class="code">
(defun bja-growl-notification (title message &#038;optional sticky)
  "Send a Growl notification"
  (do-applescript
   (format "tell application \"GrowlHelperApp\"
              notify with name \"Emacs Notification\" title \"%s\" description \"%s\" application name \"Emacs.app\" sticky %s
           end tell"
           title
           (replace-regexp-in-string "\"" "''" message)
           (if sticky "yes" "no"))))
</pre>
<p>This can be tested with the following function which sends two growl notifications. The &#8220;sticky&#8221; one requires an explicit dismissal.</p>
<pre class="code">
(defun bja-growl-test ()
  (interactive)
  (bja-growl-notification "Emacs Notification" "This is my message")
  (bja-growl-notification "Emacs Notification" "This is my sticky message" t))
</pre>
<p><strong>UPDATE:</strong> I noticed bja-growl-notification was failing if the message had embedded double quotes, so I added a call to replace-regexp-in-string to replace them with two apostrophes.</p>
<p><strong>UPDATE 2:</strong> My main motivation for setting this up was to be able to generate growl notifications from ERC (Emacs IRC client). However, I quickly realized that having a generic reminder that I can easily fire up from within Emacs is very handy. Here&#8217;s the code:</p>
<pre class="code">
(defun bja-growl-timer (minutes message)
  "Issue a Growl notification after specified minutes"
  (interactive (list (read-from-minibuffer "Minutes: " "10")
                     (read-from-minibuffer "Message: " "Reminder") ))
  (run-at-time (* (string-to-number minutes) 60)
               nil
               (lambda (minutes, message)
                 (bja-growl-notification "Emacs Reminder" message t))
               minutes
               message))
</pre>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2009/08/06/send-growl-notifications-from-carbon-emacs-on-osx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TriFunc.org</title>
		<link>http://lojic.com/blog/2009/07/22/trifuncorg/</link>
		<comments>http://lojic.com/blog/2009/07/22/trifuncorg/#comments</comments>
		<pubDate>Wed, 22 Jul 2009 14:15:42 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[arc]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[logo]]></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=635</guid>
		<description><![CDATA[I first became interested in functional programming when I was exposed to Python, Ruby &#038; JavaScript a number of years ago. Since then I&#8217;ve looked into Arc, Clojure, Common Lisp, Haskell, Logo, ML &#038; Scheme. I haven&#8217;t yet determined whether I&#8217;ll be more productive in any of them than I am with Ruby for developing [...]]]></description>
			<content:encoded><![CDATA[<p>I first became interested in functional programming when I was exposed to Python, Ruby &#038; JavaScript a number of years ago. Since then I&#8217;ve looked into Arc, Clojure, Common Lisp, Haskell, Logo, ML &#038; Scheme. I haven&#8217;t yet determined whether I&#8217;ll be more productive in any of them than I am with Ruby for developing web applications, but I do find them quite interesting.</p>
<p>After bumping into a number of local programmers who expressed an interest in functional programming, I thought it might be a good time to start a local group that focused on functional programming languages, so I did a couple days ago.</p>
<p><a rel="nofollow" href="http://TriFunc.org">TriFunc.org</a> is a group for programmers who are interested in functional programming languages and live near the Research Triangle area of North Carolina.</p>
<p>If you live in the area and have an interest in functional programming languages, feel free to dive in and start participating in the Google Group discussions. Once we reach a critical mass, I expect we&#8217;ll produce a meeting schedule, etc., but that will depend on where the group wants to take this.</p>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2009/07/22/trifuncorg/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Use Ruby to parse NMEA sentences from your GPS</title>
		<link>http://lojic.com/blog/2009/04/08/use-ruby-to-parse-nmea-sentences-from-your-gps/</link>
		<comments>http://lojic.com/blog/2009/04/08/use-ruby-to-parse-nmea-sentences-from-your-gps/#comments</comments>
		<pubDate>Wed, 08 Apr 2009 16:07:00 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[gadgets]]></category>
		<category><![CDATA[gps]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=457</guid>
		<description><![CDATA[I recently obtained a mobile broadband device that has a built in GPS receiver and can emit NMEA sentences. My old Garmin portable GPS can emit NMEA also, but it&#8217;s a pain to hookup to the laptop. Combining a GPS unit in a mobile broadband device is a great idea.
Update: it appears that the accuracy [...]]]></description>
			<content:encoded><![CDATA[<p>I recently obtained a mobile broadband device that has a built in GPS receiver and can emit NMEA sentences. My old Garmin portable GPS can emit NMEA also, but it&#8217;s a pain to hookup to the laptop. Combining a GPS unit in a mobile broadband device is a great idea.</p>
<p><strong>Update</strong>: it appears that the accuracy radius of the wireless card is quite a bit larger than my old Garmin unit. The Garmin is usually between 15 and 30 feet, but the Sierra Wireless 598U ranges from 100 to 1,000 feet or more. </p>
<p>After installing the ruby-serialport gem, I was able to write a simple Ruby program to read GPS information from the device and update a remote file on my web server to allow real time location tracking.</p>
<p>Add a simple server side script to read the file and update an iframed Google Map and you&#8217;re all set.</p>
<p>The code is also in the Ruby section of my <a href="http://github.com/lojic/sample_code/tree/master">sample code repository</a> on Github.</p>
<pre class="code">
sudo gem install ruby-serialport
</pre>
<pre class="code">
#!/usr/local/bin/ruby
# Author: Brian Adkins
# Date:   2009/04/08
# Copyright 2009 Brian Adkins - All Rights Reserved
#
# Ruby program to retrieve and parse GPS information (via NMEA sentences)
# from a Sprint Sierra Wireless 598U device.
#
# ruby gps-nmea.rb                # prints latititude/longitude info
# ruby gps-nmea.rb update-remote  # scp a file of location info to a remote server
#
# This program depends on the ruby-serialport gem:
# sudo gem install ruby-serialport
#
# From: http://www.gpsinformation.org/dale/nmea.htm#GGA
#  $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
# Where:
#      GGA          Global Positioning System Fix Data
#      123519       Fix taken at 12:35:19 UTC
#      4807.038,N   Latitude 48 deg 07.038' N
#      01131.000,E  Longitude 11 deg 31.000' E
#      1            Fix quality: 0 = invalid
#                                1 = GPS fix (SPS)
#                                2 = DGPS fix
#                                3 = PPS fix
#              4 = Real Time Kinematic
#              5 = Float RTK
#                                6 = estimated (dead reckoning) (2.3 feature)
#              7 = Manual input mode
#              8 = Simulation mode
#      08           Number of satellites being tracked
#      0.9          Horizontal dilution of position
#      545.4,M      Altitude, Meters, above mean sea level
#      46.9,M       Height of geoid (mean sea level) above WGS84
#                       ellipsoid
#      (empty field) time in seconds since last DGPS update
#      (empty field) DGPS station ID number
#      *47          the checksum data, always begins with *

require 'rubygems'
require 'serialport'

# Emacs macro to reset user modified values (highlight, then: M-x eval-region )
# ((lambda (&#038;optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ("USERNAME
\"
\372\"HOSTNAME
\"
\372\"REMOTE_DIR
\"
\372\"" 0 "%d")) arg)))

# --- MODIFY THESE -- #
USERNAME   = ""  # Username for remote host
HOSTNAME   = ""  # Remote host name e.g. foo.com
REMOTE_DIR = ""  # Remote directory e.g. /var/www/bar
# --- MODIFY THESE -- #

port_str  = '/dev/cu.sierra05'
baud_rate = 9600
data_bits = 8
stop_bits = 1
parity    = SerialPort::NONE

sp = SerialPort.new(port_str, baud_rate, data_bits, stop_bits, parity)

# lat is of the form 4807.038 where the first 2 digits are degrees and
#   the remainder is minutes.
# dir is either 'N' or 'S'
def convert_lat lat, dir
  degrees = lat[0,2].to_f + (lat[2,lat.length-2].to_f / 60.0)
  dir == 'N' ? degrees : -degrees
end

# lon is of the form 01131.000 where the first 3 digits are degrees and
#   the remainder is minutes.
# dir is either 'E', or 'W'
def convert_lon lon, dir
  degrees = lon[0,3].to_f + (lon[3,lon.length-2].to_f / 60.0)
  dir == 'E' ? degrees : -degrees
end

TEMP_PATH = '/tmp'
TEMP_FILE = 'location.txt'

def update_remote_info lat, lon
  File.open("#{TEMP_PATH}/#{TEMP_FILE}", 'w') do |tf|
    tf.puts Time.now.to_s
    tf.puts "#{lat},#{lon}"
  end
  puts 'Updating remote location info'
  `scp #{TEMP_PATH}/#{TEMP_FILE} #{USERNAME}@#{HOSTNAME}:#{REMOTE_DIR}/#{TEMP_FILE}`
  File.delete("#{TEMP_PATH}/#{TEMP_FILE}")
end

# 99 requests should be sufficient to find a $GPGGA sentence
99.times do
  if (str = sp.gets) =~ /^\$GPGGA/
    fix = str.split(',')
    if fix[6] == '1'
      lat = convert_lat(fix[2], fix[3])
      lon = convert_lon(fix[4], fix[5])
      if ARGV[0] == 'update-remote'
        update_remote_info(lat,lon)
      elsif
        puts "#{lat}, #{lon}"
      end
      exit 0
    end
  end
end

puts "Invalid data - GPS coordinates not found"
</pre>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2009/04/08/use-ruby-to-parse-nmea-sentences-from-your-gps/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Retrieve Sunrise, Sunset &amp; Twilight Info in Ruby</title>
		<link>http://lojic.com/blog/2009/03/11/retrieve-sunrise-sunset-twilight-in-ruby/</link>
		<comments>http://lojic.com/blog/2009/03/11/retrieve-sunrise-sunset-twilight-in-ruby/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 05:41:54 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[internet]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[science]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[astronomy]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[usno]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=418</guid>
		<description><![CDATA[Sunrise, Sunset &#38; Twilight
I was curious about the exact time of sunrise &#38; sunset at my location, so I found this US Naval Observatory site. In the process, I learned a more precise definition of  twilight. I wanted to be able to automate the process of retrieving the information, so my first attempt was [...]]]></description>
			<content:encoded><![CDATA[<h2>Sunrise, Sunset &amp; Twilight</h2>
<p><a href="http://lojic.com/blog/wp-content/uploads/2009/03/seascape_after_sunset_900x600.jpg"><img class="alignleft size-medium wp-image-441" title="Twilight" src="http://lojic.com/blog/wp-content/uploads/2009/03/seascape_after_sunset_900x600-300x200.jpg" alt="Twilight" width="300" height="200" /></a>I was curious about the exact time of sunrise &amp; sunset at my location, so I found this <a href="http://aa.usno.navy.mil/data/docs/RS_OneDay.php">US Naval Observatory</a> site. In the process, I learned a more precise definition of  <a href="http://aa.usno.navy.mil/faq/docs/RST_defs.php#top"><em>twilight</em></a>. I wanted to be able to automate the process of retrieving the information, so my first attempt was to simply put the query parameters used in the form in the URL as an HTTP GET request, but the server wouldn&#8217;t accept that, so I needed to issue an HTTP POST request.<br />
<br style="clear: left;" /></p>
<h2>Ruby Code</h2>
<p>Ruby is a great language for this sort of task, so I put together the following simple program:</p>
<pre>require 'net/http'

YOUR_ID    = ''    # A unique ID per comment above
YOUR_CITY  = ''    # The name of your city
YOUR_STATE = ''    # Two letter state abbreviation

now   = Time.now
month = now.month
day   = now.day + 1 # Tomorrow
year  = now.year

Net::HTTP.start('aa.usno.navy.mil') do |query|
  response = query.post('/cgi-bin/aa_pap.pl',
    "FFX=1&amp;amp;amp;amp;ID=#{YOUR_ID}&amp;amp;amp;amp;xxy=#{year}&amp;amp;amp;amp;xxm=#{month}&amp;amp;amp;amp;xxd=#{day}&amp;amp;amp;amp;st=#{YOUR_STATE}&amp;amp;amp;amp;place=#{YOUR_CITY}&amp;amp;amp;amp;ZZZ=END")
  if response.body =~ /Begin civil twilight[^0-9]*(\d+:\d{2} [ap].m.).*Sunrise[^0-9]*(\d+:\d{2} [ap].m.).*Sunset[^0-9]*(\d+:\d{2} [ap].m.).*End civil twilight[^0-9]*(\d+:\d{2} [ap].m.)/m
    puts "#{month}/#{day}/#{year}"
    puts "Begin Twilight: #{$1}"
    puts "Sunrise       : #{$2}"
    puts "Sunset        : #{$3}"
    puts "End Twilight  : #{$4}"
  end
end</pre>
<p>You just need to edit the three constants that begin with YOUR_. The id used on the Navy web form is &#8216;AA&#8217;, but they have a comment in the HTML that requests you use a unique id of your own up to 8 characters to help them with tracking. You can find a more complete version of <a href="http://github.com/lojic/sample_code/blob/7b41e88adefd84154a54c97de86924f8517dca2c/ruby/sunrise_http_post.rb">the code</a> in my <a href="http://github.com/lojic">github profile</a>.</p>
<h2>Emacs Goodness</h2>
<p>After writing the above Ruby script, I made it executable, &#8216;chmod +x sunrise.rb&#8217;, and placed it in my path so I could write a simple Emacs function to invoke it.</p>
<pre>(defun bja-sunrise ()
  "Display sunrise, sunset &amp;amp; twilight information."
  (interactive)
  (shell-command "sunrise.rb"))</pre>
<p>Imagine my surprise when I invoked the Emacs apropos help &#8216;C-h a&#8217; to see my newly defined function and discovered that Emacs, naturally, already has several commands to display sunrise/sunset information!</p>
<dl>
<dt>calendar-mouse-sunrise/sunset</dt>
<dd>Show sunrise/sunset times for mouse-selected date.</dd>
<dt>calendar-sunrise-sunset</dt>
<dd>Local time of sunrise and sunset for date under cursor.</dd>
<dt>sunrise-sunset</dt>
<dd>Local time of sunrise and sunset for today.  Accurate to a few seconds.</dd>
</dl>
<p>It doesn&#8217;t, however, display <strong>twilight</strong> information, so my simple function still has a purpose in life. Emacs is awesome :)</p>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2009/03/11/retrieve-sunrise-sunset-twilight-in-ruby/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Digest Tag Population in Ruby</title>
		<link>http://lojic.com/blog/2009/03/01/digest-tag-population-in-ruby/</link>
		<comments>http://lojic.com/blog/2009/03/01/digest-tag-population-in-ruby/#comments</comments>
		<pubDate>Sun, 01 Mar 2009 05:47:04 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=258</guid>
		<description><![CDATA[I saw a post on comp.lang.lisp demonstrating the suitability of Common Lisp for functional programming. The poster asked to see versions in other languages including Ruby, so I thought I&#8217;d whip something up. Here&#8217;s the original post with description of the problem:
This one was too much fun for words in re how cool it is [...]]]></description>
			<content:encoded><![CDATA[<p>I saw a post on <a href="http://groups.google.com/group/comp.lang.lisp/browse_frm/thread/296ea591d79ae7f5?hl=en#">comp.lang.lisp</a> demonstrating the suitability of Common Lisp for functional programming. The poster asked to see versions in other languages including Ruby, so I thought I&#8217;d whip something up. Here&#8217;s the original post with description of the problem:</p>
<pre>This one was too much fun for words in re how cool it is programming
with Lisp. I would like to see this in Ruby, Clojure, Qi, and
Scheme. The precise fun part tho is typing it all in in the final form
versus dividing the thing up into steps to get intermediate results,
ie, a test of one's mastery of one's language. Non-functional
languages I guess have no choice but to stop and assign temporaries.

Given:

(defparameter *pets*
  '((dog ((blab 12)(glab 17)(cbret 82)(dober 42)(gshep 25)))
    (cat ((pers 22)(siam 7)(tibet 52)(russ 92)(meow 35)))
    (snake ((garter 10)(cobra 37)(python 77)(adder 24)(rattle 40)))
    (cow ((jersey 200)(heiffer 300)(moo 400)))))

Write:

(defun digest-tag-population (tag-population pick-tags count)...)

Such that:

(digest-tag-population *pets* '(dog cat snake) 5)

=&gt; ((DOG CBRET 82) (DOG DOBER 42) (CAT RUSS 92) (CAT TIBET 52) (SNAKE
PYTHON 77))

...the rules being:

- consider only the populations of tags (the first symbol in each
sublist) found in the parameter pick-tags, a list

- take only the  most populous of the union of the populations

- return (tag name population) of the most populous in this order:

    firstly, by position of the tag in pick-tags
    second, ie within a tag, in descending order of population

(defun subseq-ex (st e s)
  (subseq s st (min e (length s))))

(defun digest-tag-population (tag-population pick-tags count)
  (flet ((tagpos (tag) (position tag pick-tags)))
    (stable-sort (subseq-ex 0 count
                   (sort (loop for (tag population) in tag-population
                             when (tagpos tag)
                             append (loop for pop in population
                                        collecting (list* tag pop)))
                     '&gt; :key (lambda (x)
                               (caddr x))))
      '&lt; :key (lambda (x) (tagpos (car x))))))

(defparameter *pets*
  '((dog ((blab 12)(glab 17)(cbret 82)(dober 42)(gshep 25)))
    (cat ((pers 22)(siam 7)(tibet 52)(russ 92)(meow 35)))
    (snake ((garter 10)(cobra 37)(python 77)(adder 24)(rattle 40)))
    (cow ((jersey 200)(heiffer 300)(moo 400)))))

#+test
(digest-tag-population *pets* '(dog cat snake) 5)</pre>
<p>And here is my Ruby version:</p>
<pre>PETS = [
  [:dog, [[:blab, 12], [:glab, 17], [:cbret, 82], [:dober, 42], [:gshep, 25]]],
  [:cat, [[:pers, 22], [:siam, 7], [:tibet, 52], [:russ, 92], [:meow, 35]]],
  [:snake, [[:garter, 10], [:cobra, 37], [:python, 77], [:adder, 24], [:rattle, 40]]],
  [:cow, [[:jersey, 200], [:heiffer, 300], [:moo, 400]]]
]

def digest_tag_population tag_population, pick_tags, count
  tag_population.select {|e| pick_tags.include?(e[0]) }.
    inject([]) {|memo,obj| obj[1].each {|e| memo &lt;&lt; [obj[0], e[0], e[1]] }; memo }.
    sort {|a,b| b[2] &lt;=&gt; a[2] }[0,count].
    sort_by {|e| [ tag_population.map{|p| p[0]}.rindex(e[0]), e[2] * -1] }
end

digest_tag_population(PETS, [:dog, :cat, :snake], 5)</pre>
<p>Within the function:<br />
Line  1: select elements that match the pick tags<br />
Line  2: map to a list of tuples of the form [:dog, :blab, 12]<br />
Line  3: sort the list of tuples by population and select the first count of them<br />
Line  4: sort by tag position, population</p>
<p>Output:</p>
<p>[[:dog, :cbret, 82],<br />
[:dog, :dober, 42],<br />
[:cat, :russ, 92],<br />
[:cat, :tibet, 52],<br />
[:snake, :python, 77]]</p>
<p>I think Ruby compares very favorably. What do you think? Feel free to submit a version in another language.</p>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2009/03/01/digest-tag-population-in-ruby/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>jQuery in Action</title>
		<link>http://lojic.com/blog/2009/01/20/jquery-in-action/</link>
		<comments>http://lojic.com/blog/2009/01/20/jquery-in-action/#comments</comments>
		<pubDate>Tue, 20 Jan 2009 21:49:58 +0000</pubDate>
		<dc:creator>Brian Adkins</dc:creator>
				<category><![CDATA[books]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[book]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://lojic.com/blog/?p=163</guid>
		<description><![CDATA[ I just finished &#8220;jQuery in Action&#8221; by Bear Bibeault and Yehuda Katz. It&#8217;s an excellent book on the jQuery JavaScript library. The book comes with a number of example labs to try out various jQuery/JavaScript techniques w/o having to write a lot of code.
There&#8217;s plenty of jQuery information online, but &#8220;jQuery in Action&#8221; easily [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.amazon.com/gp/product/1933988355?ie=UTF8&#038;tag=lojiccom-20&#038;linkCode=as2&#038;camp=1789&#038;creative=9325&#038;creativeASIN=1933988355"><img src="http://lojic.com/blog/wp-content/uploads/2009/01/jquery_in_action.jpg" alt="jQuery in Action cover image" title="jquery_in_action" width="128" height="160" style="margin-bottom: 3px; margin-right: 11px; border-bottom: 1px solid #444; border-right: 1px solid #444;" align="left" /></a> I just finished <a href="http://www.amazon.com/gp/product/1933988355?ie=UTF8&#038;tag=lojiccom-20&#038;linkCode=as2&#038;camp=1789&#038;creative=9325&#038;creativeASIN=1933988355">&#8220;jQuery in Action&#8221;</a> by Bear Bibeault and Yehuda Katz. It&#8217;s an excellent book on the <a href="http://jquery.com/">jQuery</a> JavaScript library. The book comes with a number of example labs to try out various jQuery/JavaScript techniques w/o having to write a lot of code.</p>
<p>There&#8217;s plenty of jQuery information online, but &#8220;jQuery in Action&#8221; easily paid for itself in saved time in getting me up to speed quickly. It&#8217;s nicely organized, well written and the editing/quality control seems to be higher than many tech books (although that bar isn&#8217;t very high!). It also has a brief, 20 page, tutorial on JavaScript that you may find helpful.</p>
<p>jQuery may not satisfy the zealots on comp.lang.javascript, but I&#8217;ve found it to be an excellent JavaScript library thus far, and I think this book was the fastest way to becoming proficient.</p>
]]></content:encoded>
			<wfw:commentRss>http://lojic.com/blog/2009/01/20/jquery-in-action/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

