<?xml version='1.0' encoding='utf-8' ?>
<!--  If you are running a bot please visit this policy page outlining rules you must respect. http://www.livejournal.com/bots/  -->
<rss version='2.0' xmlns:lj='http://www.livejournal.org/rss/lj/1.0/' xmlns:media='http://search.yahoo.com/mrss/'>
<channel>
  <title>Tigers, and lions, and bears, oh my!</title>
  <link>http://community.livejournal.com/en_dmitriid/</link>
  <description>Tigers, and lions, and bears, oh my! - LiveJournal.com</description>
  <lastBuildDate>Fri, 26 Dec 2008 07:57:15 GMT</lastBuildDate>
  <generator>LiveJournal / LiveJournal.com</generator>
  <lj:journal>en_dmitriid</lj:journal>
  <lj:journalid>10276497</lj:journalid>
  <lj:journaltype>community</lj:journaltype>
  <image>
    <url>http://l-userpic.livejournal.com/51941952/10276497</url>
    <title>Tigers, and lions, and bears, oh my!</title>
    <link>http://community.livejournal.com/en_dmitriid/</link>
    <width>100</width>
    <height>100</height>
  </image>

<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/7776.html</guid>
  <pubDate>Fri, 26 Dec 2008 07:57:15 GMT</pubDate>
  <title>Shame on me</title>
  <link>http://community.livejournal.com/en_dmitriid/7776.html</link>
  <description>Shame on me. I had a mistake in my previous pos. Thanks to &lt;span class=&apos;ljuser&apos; lj:user=&apos;xaprb&apos; style=&apos;white-space: nowrap;&apos;&gt;&lt;a href=&apos;http://xaprb.livejournal.com/profile&apos;&gt;&lt;img src=&apos;http://l-stat.livejournal.com/img/userinfo.gif&apos; alt=&apos;[info]&apos; width=&apos;17&apos; height=&apos;17&apos; style=&apos;vertical-align: bottom; border: 0; padding-right: 1px;&apos; /&gt;&lt;/a&gt;&lt;a href=&apos;http://xaprb.livejournal.com/&apos;&gt;&lt;b&gt;xaprb&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; for &lt;a href=&quot;http://community.livejournal.com/en_dmitriid/7581.html?thread=5277#t5277&quot;&gt;pointing this out&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I misplaced quote marks in my second query.&lt;br /&gt;&lt;br /&gt;Instead of &lt;br /&gt;&lt;pre&gt;&lt;code language=&quot;sql&quot;&gt;
date BETWEEN &apos;2008-01-01 12:00:00.000&apos; AND &apos;2008-01-14 12:00:00.000&apos; AND accomodation=1
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I wrote this:&lt;br /&gt;&lt;pre&gt;&lt;code language=&quot;sql&quot;&gt;
date BETWEEN &apos;2008-01-01 12:00:00.000&apos; AND &apos;2008-01-14 12:00:00.000 AND accomodation=1&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note the last quote mark after &lt;code&gt;accomodation=1&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;:)</description>
  <comments>http://community.livejournal.com/en_dmitriid/7776.html</comments>
  <category>mysql</category>
  <category>sql</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>2</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/7581.html</guid>
  <pubDate>Wed, 24 Dec 2008 09:35:53 GMT</pubDate>
  <title>Those evening queries...</title>
  <link>http://community.livejournal.com/en_dmitriid/7581.html</link>
  <description>I&apos;m dealing with databases right now while keeping an eye on  &lt;a href=&quot;http://oreilly.com/catalog/9780596101718/&quot;&gt;«High performance MySQL»&lt;/a&gt;. Finally decided to try something out. Here we go...&lt;br /&gt;&lt;br /&gt;We have a table split into partitions be week:&lt;br /&gt;&lt;br /&gt;&lt;code language=&quot;sql&quot;&gt;&lt;br /&gt;CREATE TABLE `price_detail` (&lt;br /&gt;  `accomodation` int(11) NOT NULL,&lt;br /&gt;  `date` datetime NOT NULL,&lt;br /&gt;  `price` int(11) NOT NULL,&lt;br /&gt;  `room_id` int(11) NOT NULL,&lt;br /&gt;  KEY `idx_price_date` (`date`) USING BTREE,&lt;br /&gt;  KEY `idx_price` (`price`) USING BTREE,&lt;br /&gt;  KEY `idx_price_accomodation` (`accomodation`) USING BTREE&lt;br /&gt;) &lt;br /&gt;PARTITION BY RANGE (TO_DAYS(`date`)) (&lt;br /&gt;PARTITION p20080101 VALUES LESS THAN (733407), &lt;br /&gt;PARTITION p20080108 VALUES LESS THAN (733414),&lt;br /&gt;/* and so on — an entire years worth */&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Yep... We have indexes as well...&lt;br /&gt;&lt;br /&gt;We have 26 million rows per week in the worst case. Needless to say that we have the worst case for testing purposes .&lt;br /&gt;&lt;br /&gt;Let&apos;s see how a simple query will work on such a database:&lt;br /&gt;&lt;br /&gt;Query I:&lt;br /&gt;&lt;pre&gt;&lt;code language=&quot;sql&quot;&gt;
explain partitions 
  select 
    accomodation 
  from 
    price_detail 
  where 
    accomodation=1 and date BETWEEN &apos;2008-01-01 12:00:00.000&apos; AND &apos;2008-01-14 12:00:00.000&apos;\G;

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: price_detail
&lt;strong&gt;   partitions: p20080108,p20080115&lt;/strong&gt;
         type: ref
possible_keys: idx_price_date,idx_price_accomodation
&lt;strong&gt;          key: idx_price_accomodation&lt;/strong&gt;
      key_len: 4
          ref: const
         rows: 40292
        Extra: Using where
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Query II:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code language=&quot;sql&quot;&gt;
explain partitions 
  select 
    accomodation 
  from 
    price_detail 
  where 
    date BETWEEN &apos;2008-01-01 12:00:00.000&apos; AND &apos;2008-01-14 12:00:00.000 AND accomodation=1&apos;\G;

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: price_detail
&lt;strong&gt;   partitions: p20080108,p20080115,p20080122,p20080129,p20080205,p20080212,p20080219,
                     p20080226,p20080304,p20080311,p20080318,p20080325,p20080401,p20080408,
                     p20080415,p20080422,p20080429,p20080506,p20080513,p20080520,p20080527,
                     p20080603,p20080610,p20080617,p20080624,p20080701,p20080708,p20080715,
                     p20080722,p20080729,p20080805,p20080812,p20080819,p20080826,p20080902,
                     p20080909,p20080916,p20080923,p20080930,p20081007,p20081014,p20081021,
                     p20081028,p20081104,p20081111,p20081118,p20081125,p20081202,p20081209,
                     p20081216,p20081223,p20081230,p20090106,p20090113,p20090120,p20090127&lt;/strong&gt;
         type: ALL
possible_keys: idx_price_date
&lt;strong&gt;          key: NULL&lt;/strong&gt;
      key_len: NULL
          ref: NULL
         rows: 274845000
        Extra: Using where
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What a nasty surprise!&lt;br /&gt;&lt;br /&gt;I&apos;m off learning about covering indices...</description>
  <comments>http://community.livejournal.com/en_dmitriid/7581.html</comments>
  <category>mysql</category>
  <category>sql</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>3</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/7228.html</guid>
  <pubDate>Fri, 17 Oct 2008 08:17:00 GMT</pubDate>
  <title>For whom the headhunt tolls...</title>
  <link>http://community.livejournal.com/en_dmitriid/7228.html</link>
  <description>We&apos;re hiring now.&lt;br /&gt;&lt;br /&gt;The first line in job description reads: Good or excellent knowledge of PHP&lt;br /&gt;&lt;br /&gt;Here&apos;s what we get: &quot;I&apos;ve just started learning РНР...» &lt;br /&gt;&lt;br /&gt;Perhaps, we should&apos;ve stated our requirements more clearly... Somehow... :)</description>
  <comments>http://community.livejournal.com/en_dmitriid/7228.html</comments>
  <category>job</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/7081.html</guid>
  <pubDate>Fri, 29 Aug 2008 10:31:30 GMT</pubDate>
  <title>A hundred wise men</title>
  <link>http://community.livejournal.com/en_dmitriid/7081.html</link>
  <description>via &lt;a href=&quot;http://andrzejn.livejournal.com/1152676.html&quot;&gt;http://andrzejn.livejournal.com/1152676.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;- A hundred wise men know that something is impossible. Then a fool comes along...&lt;br /&gt;&lt;br /&gt;- And he makes a discovery?&lt;br /&gt;&lt;br /&gt;- No. However, the wise men remember him with tenderness for long afterwards.</description>
  <comments>http://community.livejournal.com/en_dmitriid/7081.html</comments>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/6675.html</guid>
  <pubDate>Thu, 24 Apr 2008 13:08:16 GMT</pubDate>
  <title>Musings</title>
  <link>http://community.livejournal.com/en_dmitriid/6675.html</link>
  <description>As I &lt;a href=&quot;http://community.livejournal.com/ru_dmitriid/8537.html&quot;&gt;promised&lt;/a&gt; here are my thoughts:&lt;br /&gt;&lt;br /&gt;1. First of all, pattern matching lets you describe what yo eed with little or no effort. For example, consider these rules:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;{field}
{field, Func}
{field, {&apos;=&apos;, field2}}
&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Frankly, I have a very vague idea how these could be matched using &lt;code&gt;if&lt;/code&gt;s only. I guess you would create a &lt;code&gt;Rule&lt;/code&gt; class and inherit a slew of classes from it. Something like &lt;code&gt;RuleField&lt;/code&gt;, &lt;code&gt;RuleFunc&lt;/code&gt;, &lt;code&gt;RuleOperator&lt;/code&gt; and so on. If you use pattern matching, however, the rules are easily parsed::&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code lang=&quot;erlang&quot;&gt;%%{field}
validate_rule({FieldName}) -&amp;gt;
    ok.

%%{field, Func}
validate_rule({FieldName, Func}) when is_function(Func) -&amp;gt;
    ok.

%%{field, {&apos;=&apos;, field2}}
validate_rule({FieldName, {Operator, FieldName2}}) -&amp;gt;
    ok.
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Such ease, however, may bring (and it does bring me) to my second thought:&lt;br /&gt;&lt;br /&gt;2. WTF-ish code. The thought that you can easily slice through complex constructs makes you write before you think.&lt;br /&gt;&lt;br /&gt;In my case I knew what I wanted to pass to the function, but I had no idea what I expected the function to return. Ok, I&apos;ve parsed the rules, what now?&lt;br /&gt;&lt;br /&gt;As a result, the first version of the function would return a deeply nested list of lists that looked something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code lang=&quot;erlang&quot;&gt;
[[Field, [Error1, Error2]], [Field2, [Error3, Error4]]]
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It took me two additional refactorings to make it return a proper&lt;code&gt;proplist&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;This same &quot;wow, look at how I handle things!&quot; approach resulted in an ugly preprocessing of results before I return these to the user:&lt;br /&gt;&lt;pre&gt;&lt;code lang=&quot;erlang&quot;&gt;
lists:filter(
    fun(Elem) -&amp;gt; 
        case 
            Elem of {} -&amp;gt; false; 
            {_, []} -&amp;gt; false;
            _ -&amp;gt; true 
        end 
    end, 
    lists:flatten(validate1(A, ValidationRules, [])))
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Yup. Get rid of those unwanted elements before the user sees them. Are you scared? I am. I m saddened as well :(&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here&apos;s where my train of thoughts stops...</description>
  <comments>http://community.livejournal.com/en_dmitriid/6675.html</comments>
  <category>erlang</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/6523.html</guid>
  <pubDate>Thu, 24 Apr 2008 07:54:44 GMT</pubDate>
  <title>Validation for erlyweb</title>
  <link>http://community.livejournal.com/en_dmitriid/6523.html</link>
  <description>I&apos;ve written a &lt;a href=&quot;http://groups.google.com/group/erlyweb/browse_frm/thread/1050b3c8024c5030&quot;&gt;validation function for Erlyweb&lt;/a&gt;. First I&apos;ll tell you how it works and then, perhaps, more thoughts on its internals.&lt;br /&gt;&lt;br /&gt;Create a form with four fields:&lt;br /&gt;- login&lt;br /&gt;- password&lt;br /&gt;- pasword_repeat&lt;br /&gt;- email&lt;br /&gt;&lt;br /&gt;This is a pretty standard registration form. Naturally we&apos;d have to validate input coming from this form:&lt;br /&gt;- login has to be 4-16 symbols in length&lt;br /&gt;- password has to be 4-16 symbols in length&lt;br /&gt;- password has to be the same as password_repeat&lt;br /&gt;- email has to be a valid email address&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://erlyweb.org/doc/erlyweb_forms.html#validate-3&quot;&gt;Erlyweb&apos;s validation functions&lt;/a&gt; cant cope with this. My function can :)&lt;br /&gt;&lt;br /&gt;Suppose you have a function called &lt;code&gt;process_signup&lt;/code&gt;, which accepts the &lt;code&gt;yaws_arg&lt;/code&gt; record. Then the validation will look like so:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code lang=&quot;erlang&quot;&gt;process_signup(A) -&amp;gt;
	F = fun(A, Field) -&amp;gt;
		{ok, Val} = yaws_api:postvar(A, Field),
		L = string:len(Val),
		if
			L &amp;lt; 4 orelse L &amp;gt; 16 -&amp;gt;
				{Field, length};
			true -&amp;gt;
				{}
			end
	end,
	EmailCheck = fun(Args, Field2) -&amp;gt;
		{ok, Email} = yaws_api:postvar(Args, Field2),
		Match = regexp:match(Email, &quot;^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+&quot;),
		Match /= nomatch
	end,

	%% magic is here:
	buktu_form:validate(A, [
		{login, F},
		{email, EmailCheck},
		{password, [{&apos;=&apos;, password_repeat}, F]}
	]).
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If we don&apos;t input any field at all, we&apos;ll get back the following list:&lt;br /&gt;&lt;pre&gt;[{login,invalid_field},
 {email,invalid_field},
 {password,[{invalid_fields,[password,password_repeat]},
            invalid_field]}]
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If we input values that don&apos;t match our criteria, we&apos;ll get:&lt;br /&gt;&lt;pre&gt;[{login,length},
 {email,invalid_value},
 {password,[{not_equal,password_repeat},
            length]}]
&lt;/pre&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;The callback function that you can pass can return the following:&lt;ul&gt;&lt;br /&gt;&lt;li&gt; a tuple &lt;code&gt;{FieldName, Error}&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;true&lt;/code&gt; if the field is validated and &lt;code&gt;false&lt;/code&gt; otherwise (then the validation function will return &lt;code&gt;{FieldName, invalid_value}&lt;/code&gt;)&lt;/li&gt;&lt;br /&gt;&lt;li&gt; any value &lt;code&gt;Value&lt;/code&gt; which will be transformed into &lt;code&gt;{FieldName, Value}&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt; if any of the fields in the rule don&apos;t exist or are empty, for each such rule the validation function will return:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;invalid_field&lt;/code&gt; if the field is compared against a value&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;{invalid_fields, [field1, field2]}&lt;/code&gt; if the field is compared against another field&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If you need to bind several rules to a field, pass a list of rules. If you just need to check if a field exists, pass in a tuple containing the field&apos;s name:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Does the field exist?&lt;br /&gt;&lt;code&gt;{field_name}&lt;/code&gt; &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Compare a field &lt;code&gt;field_name&lt;/code&gt; to field &lt;code&gt;field2_name&lt;/code&gt; (you can use &lt;code&gt;&apos;=&apos;, &apos;/=&apos;, &apos;&amp;lt;&apos;, &apos;=&amp;lt;&apos;, &apos;&amp;gt;&apos;, &apos;&amp;gt;=&apos;&lt;/code&gt; )&lt;br /&gt;&lt;code&gt;{field_name, {&apos;=&apos;, field2_name}}&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Compare a field to any value: &lt;br /&gt;&lt;code&gt;{field_name, {&apos;=&apos;, Value}}&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Use a callback function (function/2, first parameter is yaws_arg, the second is the field&apos;s name). The function can be a lambda or any function of any module in the form of &lt;code&gt;module:function/2&lt;/code&gt; or &lt;code&gt;{module, function}&lt;/code&gt;&lt;br /&gt;&lt;code&gt;{field_name, F}&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Use a callback function with an additional value (function/3,first parameter is yaws_arg, the second is the field&apos;s name, the third is the value). The function can be a lambda or any function of any module in the form of &lt;code&gt;module:function/3&lt;/code&gt; or &lt;code&gt;{module, function}&lt;/code&gt;&lt;br /&gt;&lt;code&gt;{field_name, {F, Value}}&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The validation function returns a &lt;code&gt;proplist&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;[{FieldName(), Errors()}]&lt;/pre&gt;&lt;br /&gt;where&lt;br /&gt;&lt;pre&gt;&lt;code&gt;FieldName() = atom()
Errors() = Error() | [Error()]
Error() = user_defined_values | absent | invalid_value | 
          invalid_field | {invalid_fields, [FieldName(), FieldName()]} |
          ComparisonError()
ComparisonError() = {not_equal, value_or_field} | {equal, value_or_field} |
                    {not_greater, value_or_field} | {not_less, value_or_field} |
                    {not_greater_or_equal, value_or_field} | {not_less_or_equal, value_or_field} |
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/code&gt;</description>
  <comments>http://community.livejournal.com/en_dmitriid/6523.html</comments>
  <category>erlyweb</category>
  <category>erlang</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/6383.html</guid>
  <pubDate>Thu, 06 Mar 2008 15:27:24 GMT</pubDate>
  <title>Apple...</title>
  <link>http://community.livejournal.com/en_dmitriid/6383.html</link>
  <description>&lt;a href=&quot;http://pics.livejournal.com/dmitriid/pic/000014zk/&quot;&gt;&lt;img src=&quot;http://pics.livejournal.com/dmitriid/pic/000014zk/s320x240&quot; width=&quot;320&quot; height=&quot;240&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;there it is.... quite unusual, but there is no way back...</description>
  <comments>http://community.livejournal.com/en_dmitriid/6383.html</comments>
  <category>apple</category>
  <lj:mood>accomplished</lj:mood>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/6014.html</guid>
  <pubDate>Fri, 24 Aug 2007 07:44:46 GMT</pubDate>
  <title>Somebody stop me</title>
  <link>http://community.livejournal.com/en_dmitriid/6014.html</link>
  <description>Or shoot me before I suffer too long :)&lt;br /&gt;&lt;br /&gt;I&apos;ve managed to get one of the oldest Firefox bugs going: &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=69230&quot;&gt;https://bugzilla.mozilla.org/show_bug.cgi?id=69230&lt;/a&gt; (see &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=69230#c86&quot;&gt;comment 86&lt;/a&gt;). I have know idea what to do with it now :) And there&apos;s the possibility that I will have to compile Mozilla from the source...&lt;br /&gt;&lt;br /&gt;&quot;Tell my wife and children that I love them...&quot;  :))</description>
  <comments>http://community.livejournal.com/en_dmitriid/6014.html</comments>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>2</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/5806.html</guid>
  <pubDate>Tue, 21 Aug 2007 13:39:02 GMT</pubDate>
  <title>Erlang Bit Syntax</title>
  <link>http://community.livejournal.com/en_dmitriid/5806.html</link>
  <description>I&apos;ve decided to see whether all is as well with Erlang&apos;s bit syntax as advertised..
&lt;br /&gt;&lt;br /&gt;
A friend of mine has been struggling with SOny&apos;s OMA format which is being used in Sony&apos;s players. The only feature this format has that distinguishes it from &quot;normal&quot; formats is its lack of documentation and whatever documentation there is differs significantly from whatever actual files have to offer :)&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
There are some good folk out there and they&apos;ve reverse engineered the format and wrote a Java program to maniplate it. The program is available here: &lt;a href=&quot;http://dmitriid.com/files/projects/erlang/OMA.zip&quot;&gt;http://dmitriid.com/files/projects/erlang/OMA.zip&lt;/a&gt;. The program is accompanied by documentation on Sony players&apos; directory structure and, what&apos;s more important, on OM file format as well.
&lt;br /&gt;&lt;br /&gt;
You can see the OMA header format in this file: &lt;a href=&quot;http://dmitriid.com/files/projects/erlang/OMA.html&quot;&gt;http://dmitriid.com/files/projects/erlang/OMA.html&lt;/a&gt;. It doesn&apos;t look to horrible, does it? Let&apos;s see how Erlang handles it.
&lt;br /&gt;&lt;br /&gt;
The first obstacle comes from the sample file that comes with the application (&lt;code&gt;trunk/dist/OMGAUDIO/10F00/10000001.OMA&lt;/code&gt;). The spec says it has to start with
&lt;pre style=&quot;border-left: 4px solid gray; padding: 5px;&quot;&gt;&lt;code&gt;&quot;E&quot; &quot;A&quot; &quot;3&quot; 3 0 0 0 0 17  76 &quot;T&quot; &quot;I&quot; &quot;T&quot; &quot;2&quot; 0 0
&lt;/code&gt;&lt;/pre&gt;
You wish. In reality it starts with
&lt;pre style=&quot;border-left: 4px solid gray; padding: 5px;&quot;&gt;&lt;code&gt;&quot;e&quot; &quot;a&quot; &quot;3&quot; 3 0 0 0 0 17 &quot;v&quot; &quot;G&quot; &quot;E&quot; &quot;O&quot; &quot;B&quot; 0 0
&lt;/code&gt;&lt;/pre&gt;
And there&apos;s lots of info before we reach TIT2. Oh well, hex-editor to the rescue. The files does contain the tags shown in the &lt;a href=&quot;http://dmitriid.com/files/projects/erlang/OMA.html&quot;&gt;spec&lt;/a&gt;. However, they are placed differently and there&apos;s a bunch of other, unknown tags. Whatever shall we do? I propose moving byte by byte until we reach tags that we know of or the end of the header.
&lt;br /&gt;&lt;br /&gt;
I&apos;ll tell you from the start that I cheated. I don&apos;t read the codec info from the header, I stop as soon as I reach
&lt;pre style=&quot;border-left: 4px solid gray; padding: 5px;&quot;&gt;&lt;code&gt;&quot;E&quot; &quot;A&quot; &quot;3&quot; 2 0 60 ff ff
&lt;/code&gt;&lt;/pre&gt;

&lt;strong&gt;So, the code&lt;/strong&gt;
&lt;br /&gt;&lt;br /&gt;
Open the file and read data from it
&lt;pre style=&quot;font-size: 12pt; border-left: 4px solid gray; padding: 5px;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #000000;&quot;&gt;parse_header(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;File&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;) -&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight: bold;color: #000000;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-weight: bold;color: #000000;&quot;&gt;file:open&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;File&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, [read, binary, raw]) &lt;/span&gt;&lt;span style=&quot;font-weight: bold;color: #000000;&quot;&gt;of&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;        {ok, &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;S&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;} -&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;            {ok, &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Header&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;} = &lt;/span&gt;&lt;span style=&quot;font-weight: bold;color: #000000;&quot;&gt;file:pread&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;S&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;16&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;#0c60),&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;H&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;font-weight: bold;color: #000000;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; read_header(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Header&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;font-weight: bold;color: #000000;&quot;&gt;of&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;font-weight: bold;color: #000000;&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; -&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;                    {&lt;/span&gt;&lt;span style=&quot;font-weight: bold;color: #000000;&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, invalid_header};&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Data&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; -&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Data&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;font-weight: bold;color: #000000;&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;,&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;font-weight: bold;color: #000000;&quot;&gt;file:close&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;S&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;),&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;H&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; -&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;            {&lt;/span&gt;&lt;span style=&quot;font-weight: bold;color: #000000;&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, file_cannot_be_opened}&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight: bold;color: #000000;&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
Well, that was easy. Open the file. Read it. Call internal &lt;code&gt;read_header&lt;/code&gt; function to actuall parse the header and return the value that we receive from the function.
&lt;br /&gt;&lt;br /&gt;
The &lt;code&gt;read_header&lt;/code&gt; function couldn&apos;t be simpler
&lt;pre style=&quot;font-size: 12pt; border-left: 4px solid gray; padding: 5px;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #000000;&quot;&gt;read_header(&amp;lt;&amp;lt;$e, $a, $3, &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Rest&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/binary&amp;gt;&amp;gt;) -&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Data&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; = decode_header(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Rest&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, []),&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Data&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;;&lt;/span&gt;

&lt;span style=&quot;color: #000000;&quot;&gt;read_header(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;) -&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;font-weight: bold;color: #000000;&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
It couldn&apos;t be simpler because of the pattern-match. If the chunk of data that comes in starts with
&lt;pre style=&quot;border-left: 4px solid gray; padding: 5px;&quot;&gt;&lt;code&gt;&quot;e&quot; &quot;a&quot; &quot;3&quot;
&lt;/code&gt;&lt;/pre&gt;
it&apos;s passed to the upper function. Otherwise, the lower function is called.
&lt;br /&gt;&lt;br /&gt;
The actual parsing is contained in several &lt;code&gt;decode_header&lt;/code&gt; functions which parse a single tag at a time. Here&apos; an example:
&lt;pre style=&quot;font-size: 12pt; border-left: 4px solid gray; padding: 5px;&quot;&gt;&lt;code&gt;&lt;span style=&quot;font-style: italic;color: #808080;&quot;&gt;% Title&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;decode_header(&amp;lt;&amp;lt;$&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, $&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;I&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, $&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, $2, &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/binary,&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Var&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/integer-unit:&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/binary,&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Rest&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/binary&amp;gt;&amp;gt;, &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;L&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;) -&amp;gt;&lt;/span&gt;

&lt;span style=&quot;color: #000000;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;TitleLength&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Var&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; - &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;,&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;        &amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Title&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;TitleLength&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/binary, &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Rest2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/binary&amp;gt;&amp;gt; = &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Rest&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;,&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;        decode_header(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Rest2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, [&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;L&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;|{title, &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Title&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;}]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
What happens here? Keep &lt;a href=&quot;http://dmitriid.com/files/projects/erlang/OMA.html&quot;&gt;the spec&lt;/a&gt; before your eyes.
&lt;br /&gt;&lt;br /&gt;
Here we go. The song title is stored as follows
&lt;pre style=&quot;font-size: 12pt; border-left: 4px solid gray; padding: 5px;&quot;&gt;&lt;code&gt;T I T 2 0 0 Var1 Var1 0 0 2 TitleString
&lt;/code&gt;&lt;/pre&gt;
where &lt;code&gt;TitleString&lt;/code&gt; is &lt;code&gt;[0x0 String]&lt;/code&gt;. That&apos;s exactly what we&apos;ve specified in the pattern:
&lt;pre style=&quot;font-size: 12pt; border-left: 4px solid gray; padding: 5px;&quot;&gt;&lt;code&gt;T        $&lt;span style=&quot;color: #008000;&quot;&gt;T&lt;/span&gt;
I        $&lt;span style=&quot;color: #008000;&quot;&gt;I&lt;/span&gt;
T        $&lt;span style=&quot;color: #008000;&quot;&gt;T&lt;/span&gt;
2        $&lt;span style=&quot;color: #008000;&quot;&gt;2&lt;/span&gt;
0        &lt;span style=&quot;color: #008000;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/binary&lt;/span&gt;            simply skip the two zeroes
0
Var1     &lt;span style=&quot;color: #008000;&quot;&gt;Var&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/integer-unit:&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;8&lt;/span&gt;  a number containd in two bytes
Var1
0        &lt;span style=&quot;color: #008000;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/binary&lt;/span&gt;            simply skip 0 0 2 0
0
2
0
TitleString &lt;span style=&quot;color: #008000;&quot;&gt;Rest&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/binary&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
All we have to do now is get the title from &lt;code&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Rest&lt;/span&gt;&lt;/code&gt;. Empirically I&apos;ve guessed that the length of this title in our case is &lt;code&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Var&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; - &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2&lt;/span&gt;&lt;/code&gt;. Having decided on that, we can get the title using pattern matching, again:
&lt;pre style=&quot;font-size: 12pt; border-left: 4px solid gray; padding: 5px;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #000000;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;TitleLength&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Var&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; - &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;,&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;        &amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Title&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;TitleLength&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/binary, &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Rest2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/binary&amp;gt;&amp;gt; = &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Rest&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
This way all we have to do is to parse all the remaining tags according to the rules and test them against a real file. The real file may give us a headache because it doesn&apos;t confirm to the spec (albeit informal) and adds several new and unknown tags. That is why we need to augment &lt;code&gt;decode_header&lt;/code&gt; with:
&lt;pre style=&quot;font-size: 12pt; border-left: 4px solid gray; padding: 5px;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #000000;&quot;&gt;decode_header(&amp;lt;&amp;lt;&amp;gt;&amp;gt;, &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;L&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;) -&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;L&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;;&lt;/span&gt;

&lt;span style=&quot;color: #000000;&quot;&gt;decode_header(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Bin&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;L&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;) -&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;    {&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;NewBin&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;} = &lt;/span&gt;&lt;span style=&quot;font-weight: bold;color: #000000;&quot;&gt;split_binary&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;Bin&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;),&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;    decode_header(&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;NewBin&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;L&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;).&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
We move forward byte by byte. If we match a known tag, it is caught by the corresponding &lt;code&gt;decode_header&lt;/code&gt;. If we&apos;ve reached the end of the header, this will be natched by &lt;code&gt;decode_header(&amp;lt;&amp;lt;&amp;gt;&amp;gt;, L)&lt;/code&gt;. Otherwise we move forward by one more byte and repeat the steps nce again.
&lt;br /&gt;&lt;br /&gt;
The entire file is available here: &lt;a href=&quot;http://erltag.googlecode.com/svn/trunk/src/oma.erl&quot;&gt;http://erltag.googlecode.com/svn/trunk/src/oma.erl&lt;/a&gt;. If you want to practice, download this file: &lt;a href=&quot;http://erltag.googlecode.com/files/erltag-release.zip&quot;&gt;http://erltag.googlecode.com/files/erltag-release.zip&lt;/a&gt;(6.1 MB). You can find the sample audiofile in the test folder.
&lt;br /&gt;&lt;br /&gt;
By the way. The code doesn&apos;t pretend to be the most effecient and correct way of writing Erlang code. Most likely the code is rather opposite of that :)
</description>
  <comments>http://community.livejournal.com/en_dmitriid/5806.html</comments>
  <category>erlang</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>2</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/5581.html</guid>
  <pubDate>Tue, 31 Jul 2007 11:44:38 GMT</pubDate>
  <title>Programming Erlang</title>
  <link>http://community.livejournal.com/en_dmitriid/5581.html</link>
  <description>It has finally arrived!&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://s3.amazonaws.com/mamut-site-images/1273.800x600.jpg&quot;&gt;&lt;img src=&quot;http://s3.amazonaws.com/mamut-site-images/1273.300x225.jpg&quot; alt=&quot;Programming Erlang&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://s3.amazonaws.com/mamut-site-images/1274.800x600.jpg&quot;&gt;&lt;img src=&quot;http://s3.amazonaws.com/mamut-site-images/1274.300x225.jpg&quot; alt=&quot;Programming Erlang&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://s3.amazonaws.com/mamut-site-images/1275.800x600.jpg&quot;&gt;&lt;img src=&quot;http://s3.amazonaws.com/mamut-site-images/1275.300x225.jpg&quot; alt=&quot;Programming Erlang&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It arrived at Moldova on Juky 21st. It got out of customs on July 25th. And it is only today that I finally noticed the invitation to pick it up at my local post office. :)&lt;br /&gt;&lt;br /&gt;Hurrah!&lt;br /&gt;&lt;br /&gt;Now if I only could find time to study it...</description>
  <comments>http://community.livejournal.com/en_dmitriid/5581.html</comments>
  <category>erlang</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/5342.html</guid>
  <pubDate>Wed, 18 Jul 2007 15:12:18 GMT</pubDate>
  <title>Keep&apos;em languages coming!</title>
  <link>http://community.livejournal.com/en_dmitriid/5342.html</link>
  <description>Past Friday I got myself acquainted to &lt;a href=&quot;http://python.org/&quot;&gt;Python&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
Different people view Python as &quot;nothing to learn&quot; or as &quot;if only I had time to learn&quot; or even as &quot;very difficult to learn&quot;.
&lt;br /&gt;&lt;br /&gt;
I had to learn it quick for a very simple reason. I have lots of photos taken at different resolutions. I need to resize them to different sizes (much like &lt;a href=&quot;http://flickr.com&quot;&gt;Flickr&lt;/a&gt; does), create several thumbnails of each image, upload them to a host (&lt;a href=&quot;http://s3.amazonaws.com/&quot;&gt;Amazon S3&lt;/a&gt;) and load information on uploaded images to a database.
&lt;br /&gt;&lt;br /&gt;
The process must be automated, of course.
&lt;br /&gt;&lt;br /&gt;
It all started when I convinced myself that &lt;a href=&quot;http://www.pythonware.com/products/pil/&quot;&gt;Python Imaging Library&lt;/a&gt; is the best library to manipulate images. Indeed:
&lt;br /&gt;&lt;br /&gt;
&lt;div class=&quot;python&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;kw1&quot;&gt;import&lt;/span&gt; Image&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;im = Image.&lt;span class=&quot;kw2&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&apos;path/to/image&apos;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;im.&lt;span class=&quot;me1&quot;&gt;thumbnail&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;800&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;800&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;, Image.&lt;span class=&quot;me1&quot;&gt;ANTIALIAS&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;im.&lt;span class=&quot;me1&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&apos;path/to/image&apos;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;
The line with &lt;code&gt;im.thumbnail((800, 800), Image.ANTIALIAS)&lt;/code&gt; is absolute genius. If your image is, say, 1024х768px, then what you get in the end is not a skewed 800х800px, but a proportional 800x600px.
&lt;br /&gt;&lt;br /&gt;
Combined with &lt;a href=&quot;http://mysql-python.sourceforge.net/&quot;&gt;MySQLDb&lt;/a&gt; and &lt;a href=&quot;http://code.google.com/p/boto/&quot;&gt;Boto&lt;/a&gt; this yields a very easy solution to my task. However, that&apos;s not the point.
&lt;br /&gt;&lt;br /&gt;
As it turns out, getting to know many languages (even superficially) may give you a huge head start in learning a new programming language. I&apos;ve had an overview or, sometimes, more than an overview of such languages as &lt;a href=&quot;http://en.wikipedia.org/wiki/Lisp_programming_language&quot;&gt;Lisp&lt;/a&gt;, &lt;a href=&quot;http://www.haskell.org/&quot;&gt;Haskell&lt;/a&gt;, &lt;a href=&quot;http://www.erlang.org/&quot;&gt;Erlang&lt;/a&gt;... How does that help me with Python? Well, I got an imeddiate understanding of the following:
&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;font-size: 10pt; color: gray; border: 1px solid #efefef; padding: 2px&quot;&gt;&lt;strong&gt;Note:&lt;/strong&gt; I can bear no responsibility for Haskell codes in the examples :)&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;strong&gt;Tuples and destructuring assignment&lt;/strong&gt;
&lt;br /&gt;&lt;br /&gt;
A tuple is a fixed-length list. This list may contain elements that are very different in nature:
&lt;div class=&quot;python&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# Python tuple&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;st0&quot;&gt;&apos;hello&apos;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;haskell&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;-- Haskell tuple&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;, &quot;hello&quot;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;haskell&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;%% Erlang tuple&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;br0&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;, &apos;hello&apos;&lt;span class=&quot;br0&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;
Looks similar, doesn&apos;t it? :)
&lt;br /&gt;&lt;br /&gt;
Let now get data out of our tuples:
&lt;div class=&quot;python&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# Python&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# А will contain 1&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# В will contain 2&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# С will contain &apos;hello&apos;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&lt;/span&gt;A, B, C&lt;span class=&quot;br0&quot;&gt;&lt;/span&gt; = &lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;, &apos;hello&apos;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;haskell&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;-- Haskell&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;-- a will contain 1&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;-- b will contain 2&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;-- c will contain &apos;hello&apos;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;a, b, c&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt; = &lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;, &quot;hello&quot;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;haskell&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;%% Erlang&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;%% А will contain 1&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;%% В will contain 2&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;%% С will contain &apos;hello&apos;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;br0&quot;&gt;{&lt;/span&gt;A, B, C&lt;span class=&quot;br0&quot;&gt;}&lt;/span&gt; = &lt;span class=&quot;br0&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;, &apos;hello&apos;&lt;span class=&quot;br0&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;
Certainly, the principles of theses examples are very different. Haskell and Erlang use pattern matching that Python doesn&apos;t have. However, it looks very similar and is very easy to understand once you know the other examples. PHP, by the way, has a similar thing:
&lt;div class=&quot;php-brief&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;// А will contain 1&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;// В will contain 2&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;// С will contain &apos;hello&apos;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;list&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;re0&quot;&gt;$A&lt;/span&gt;, &lt;span class=&quot;re0&quot;&gt;$B&lt;/span&gt;, &lt;span class=&quot;re0&quot;&gt;$C&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt; = &lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span class=&quot;kw3&quot;&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;st0&quot;&gt;&apos;hello&apos;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;
This, of course, is very different and the inner workings are absolutely different :) One thing about this is quite peculiar, though. Once you get used to these sorts of destructuring assignments, you start using PHP&apos;s &lt;code&gt;list&lt;/code&gt; and Python&apos;s tuples much more often. Because it&apos;s so convenient.
&lt;br /&gt;&lt;br /&gt;
&lt;strong&gt;Named parameters&lt;/strong&gt;
&lt;br /&gt;&lt;br /&gt;
I once &lt;a href=&quot;http://community.livejournal.com/en_dmitriid/2345.html&quot;&gt;talked about named parameters&lt;/a&gt;. As it turns out, Pythons has them.
&lt;div class=&quot;python&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# define a function&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;kw1&quot;&gt;def&lt;/span&gt; myfunc&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;param=&lt;span class=&quot;st0&quot;&gt;&apos;&apos;&lt;/span&gt;, another_param=&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;print&lt;/span&gt; param, another_param&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# call the function&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# will print hello 5&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;myfunc&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;another_param=&lt;span class=&quot;nu0&quot;&gt;5&lt;/span&gt;, param=&lt;span class=&quot;st0&quot;&gt;&apos;hello&apos;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# will print hello 1&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;myfunc&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;param=&lt;span class=&quot;st0&quot;&gt;&apos;hello&apos;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# will print 1&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;myfunc&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;strong&gt;Anonymous functions (lambdas)&lt;/strong&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;div class=&quot;python&quot;&gt;&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# Python&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# define a list&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;li = &lt;span class=&quot;br0&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;9&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;10&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;256&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;-3&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# get only evens out of the list&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;li_even = &lt;span class=&quot;kw2&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kw1&quot;&gt;lambda&lt;/span&gt; item: item % &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt; == &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;, li&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;
Very similar to code in other languages:
&lt;br /&gt;&lt;br /&gt;
&lt;div class=&quot;haskell&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;-- Haskell&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;-- define a list&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;li = &lt;span class=&quot;br0&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;9&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;10&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;256&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;-3&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;-- get only evens out of the list&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;li_even = &lt;a href=&quot;http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:filter&quot;&gt;&lt;span class=&quot;kw3&quot;&gt;filter&lt;/span&gt;&lt;/a&gt; &lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;\item -&amp;gt; &lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;a href=&quot;http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:mod&quot;&gt;&lt;span class=&quot;kw3&quot;&gt;mod&lt;/span&gt;&lt;/a&gt; item &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt; == &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt; li&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;haskell&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;%% Erlang&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;%% define a list&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;Li = &lt;span class=&quot;br0&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;9&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;10&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;256&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;-3&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;%% get only evens out of the list&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;Li_even = &lt;span class=&quot;kw3&quot;&gt;lists:filter&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;br1&quot;&gt;(&lt;/span&gt;Item&lt;span class=&quot;br1&quot;&gt;)&lt;/span&gt; -&amp;gt; Item rem 2 == 0 &lt;span class=&quot;kw4&quot;&gt;end&lt;/span&gt;, Li&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;strong&gt;List comprehensions&lt;/strong&gt;
&lt;br /&gt;&lt;br /&gt;
Remember how we used to define lists in mathematics? For instance:
&lt;div class=&quot;python&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;S = &lt;span class=&quot;br0&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;M = &lt;span class=&quot;br0&quot;&gt;{&lt;/span&gt;x | x in S, x even&lt;span class=&quot;br0&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;
M is all x&apos;s where x belongs to S and x is even. Nice languages have ways to define lists in a very mathematical way. This is called list comprehensions. One downside to Python&apos;s comprehensions is the syntax. Here are previous examples rewritten to use list comprehensions instead of lambdas:
&lt;br /&gt;&lt;br /&gt;
&lt;div class=&quot;python&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# Python&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# define a list&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;li = &lt;span class=&quot;br0&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;9&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;10&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;256&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;-3&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;# get only evens out of the list&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;li_even = &lt;span class=&quot;br0&quot;&gt;[&lt;/span&gt;x &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; x &lt;span class=&quot;kw1&quot;&gt;in&lt;/span&gt; li &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; x % &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt; == &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;haskell&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;-- Haskell&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;-- define a list&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;li = &lt;span class=&quot;br0&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;9&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;10&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;256&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;-3&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;-- get only evens out of the list&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;li_even = &lt;span class=&quot;br0&quot;&gt;[&lt;/span&gt;x | x &amp;lt;- li, &lt;span class=&quot;br0&quot;&gt;(&lt;/span&gt;&lt;a href=&quot;http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:mod&quot;&gt;&lt;span class=&quot;kw3&quot;&gt;mod&lt;/span&gt;&lt;/a&gt; x &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;)&lt;/span&gt; == &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;haskell&quot;&gt;
&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;%% Erlang&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;%% define a list&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;Li = &lt;span class=&quot;br0&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;9&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;10&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;256&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;-3&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;co1&quot;&gt;%% get only evens out of the list&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;Li_even = &lt;span class=&quot;br0&quot;&gt;[&lt;/span&gt;X || X &amp;lt;- Li, X &lt;span class=&quot;kw3&quot;&gt;rem&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;2&lt;/span&gt; == &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;

&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;&lt;br /&gt;
Anyhow, thanks to other languages the new language (a more or less mainstream language, not &lt;a href=&quot;http://en.wikipedia.org/wiki/K_(programming_language)#Examples&quot;&gt;K&lt;/a&gt; :)) ) is not just easy, it&apos;s extreamly easy and can be learned in, say, 15 minutes.
&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;font-size: 10pt; color: gray; border: 1px solid #efefef; padding: 2px&quot;&gt;&lt;strong&gt;Update:&lt;/strong&gt; Corrections to Haskell code. Thanks, &lt;span class=&apos;ljuser&apos; lj:user=&apos;deni_ok&apos; style=&apos;white-space: nowrap;&apos;&gt;&lt;a href=&apos;http://deni-ok.livejournal.com/profile&apos;&gt;&lt;img src=&apos;http://l-stat.livejournal.com/img/userinfo.gif&apos; alt=&apos;[info]&apos; width=&apos;17&apos; height=&apos;17&apos; style=&apos;vertical-align: bottom; border: 0; padding-right: 1px;&apos; /&gt;&lt;/a&gt;&lt;a href=&apos;http://deni-ok.livejournal.com/&apos;&gt;&lt;b&gt;deni_ok&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; &lt;/div&gt;</description>
  <comments>http://community.livejournal.com/en_dmitriid/5342.html</comments>
  <category>python</category>
  <category>haskell</category>
  <category>erlang</category>
  <category>php</category>
  <category>general</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/4916.html</guid>
  <pubDate>Mon, 28 May 2007 11:04:35 GMT</pubDate>
  <title>Pragmatic Erlang</title>
  <link>http://community.livejournal.com/en_dmitriid/4916.html</link>
  <description>Almost 60 dollars left my pocket to get &lt;a href=&quot;http://www.pragmaticprogrammer.com/titles/jaerlang/&quot;&gt;Joe Armstrong. &quot;Programming Erlang. Software for a Concurrent World&quot;&lt;/a&gt;. It&apos;s finally mine! As a PDF only so far. I&apos;ll get to reading it eventually......&lt;br /&gt;&lt;br /&gt;Yeah, baby! :)</description>
  <comments>http://community.livejournal.com/en_dmitriid/4916.html</comments>
  <category>erlang</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/4625.html</guid>
  <pubDate>Fri, 29 Dec 2006 13:39:55 GMT</pubDate>
  <title>NY</title>
  <link>http://community.livejournal.com/en_dmitriid/4625.html</link>
  <description>HAPPY NEW YEAR TO ALL FRIENDS AND ENEMIES!!!</description>
  <comments>http://community.livejournal.com/en_dmitriid/4625.html</comments>
  <category>misc</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/4599.html</guid>
  <pubDate>Sun, 08 Oct 2006 08:37:35 GMT</pubDate>
  <title>Orcas official site</title>
  <link>http://community.livejournal.com/en_dmitriid/4599.html</link>
  <description>Orcas has been moved to &lt;a href=&quot;http://orcas.dmitriid.com/&quot;&gt;http://orcas.dmitriid.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Project description etc etc can be accessed via project wiki at &lt;a href=&quot;http://orcas.dmitriid.com/wiki&quot;&gt;http://orcas.dmitriid.com/wiki&lt;/a&gt;</description>
  <comments>http://community.livejournal.com/en_dmitriid/4599.html</comments>
  <category>erlang</category>
  <category>orcas</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/4339.html</guid>
  <pubDate>Wed, 04 Oct 2006 09:01:21 GMT</pubDate>
  <title>Refactoring, pattern matching, function guards and Erlang</title>
  <link>http://community.livejournal.com/en_dmitriid/4339.html</link>
  <description>I&apos;m still late on my &lt;a href=&quot;http://community.livejournal.com/en_dmitriid/2345.html&quot;&gt;promise&lt;/a&gt; to talk about pattern matching even though today&apos;s post is related to patern matching.&lt;br /&gt;&lt;br /&gt;In brief here is what pattern matching all about. The all-knowing &lt;a href=&quot;http://en.wikipedia.org/wiki/Pattern_matching&quot;&gt;Wikipedia&lt;/a&gt; defines pattern matching as &lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;the act of checking for the presence of the constituents of rigidly specified pattern&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;What does this mean though? This means that when a function (especially in dynamically typed languages) accepts parameters of different kinds/types we can define this function like this::&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;
fun([H|T]) -&amp;gt;
    do_smth();

fun({a, tuple}) -&amp;gt;
    do_smth_else();

fun(value) -&amp;gt;
   do_a_third_thing();

fun(DefaultValue) -&amp;gt;
   do_default_thing().
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;What happens in the code above?&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;br /&gt;1. First function accepts a list/array as its parameter. The list consists of a Head and a Tail. So, if we pass [1, 2, 3, 4] to this function, the variable H will contain 1 and variable T will contain [2, 3, 4]&lt;br /&gt;&lt;br /&gt;2. The second function accepts a tuple, that consists of two immutable values, &quot;a&quot; and &quot;tuple&quot;&lt;br /&gt;&lt;br /&gt;3. The third function accepts an immutable value of &quot;value&quot;&lt;br /&gt;&lt;br /&gt;4. The fourth function accepts everything rejected by the first three functions&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;So. If we call a function like this:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;
fun([2, 5, 72]).
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;we will trigger the first function, since it accepts an array/list.&lt;br /&gt;&lt;br /&gt;However, if we call the function like so: &lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;
fun({another, tuple}).
 &lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;we will trigger the fourth function. Why? Because even though we pass a tuple, the third function accepts only one tuple, {a, tuple} whereas we pass a different tuple, {another, tuple}.&lt;br /&gt;&lt;br /&gt;So what&apos;s refactoring got to do with all this? And what&apos;s function guards?&lt;br /&gt;&lt;br /&gt;A couple of things about function guards. Consider the ubiquitous Fibonacci function. First, pattern matching:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;
fib(1) -&amp;gt; 1; 

fib(2) -&amp;gt; 1; 

fib(X) -&amp;gt; fib(X-1) + fib(X-2).
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;&lt;br /&gt;Now, function guards:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;pre&gt; 
fib(X) when X =&amp;lt; 3 -&amp;gt; 1; 

fib(X) -&amp;gt; fib(X-1) + fib(X-2).
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;The first line reads: &quot;If X is less than 3, return 1&quot;. &lt;br /&gt;&lt;br /&gt;Guards can check for a wide range of conditions, including such thnigs as is_list(X), is_tuple(X) etc. They can also be stacked using such keywords as &quot;and&quot;, &quot;or&quot; etc. More on them in forecoming topics. Back to the topic at hand.&lt;br /&gt;&lt;br /&gt;A question &lt;a href=&quot;http://gzip.rsdn.ru/Forum/Message.aspx?mid=2113522&amp;amp;only=1&quot;&gt;was raised over at RSDN&lt;/a&gt; with regard to implementation of the Factory pattern. For instance, in creating a wrapper for various database connections. The following С++ code was given as an example:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;
class Driver
{
public:
  virtual void connect() = 0;
};

class MysqlDriver : public Driver {}; //implements connect() using some mysql API calls.
class OracleDriver : public Driver {}; //implements connect() using some oracle API calls.
 &lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;&lt;br /&gt;And, finally,  &lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;
class DriverFactory
{
public:
  static Driver * createDriver( string name ) //creates necessary driver
  {
    Driver * driver = 0;
    if(&quot;mysql&quot; == name ) driver = new MysqlDriver();
    else if( &quot;oracle&quot; == name ) driver = OracleDriver();
    else throw 1;
    return driver;
  }
};
 &lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;&lt;br /&gt;The key to this factory, is of course the following:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;
if(&quot;mysql&quot; == name ) driver = new MysqlDriver();
    else if( &quot;oracle&quot; == name ) driver = OracleDriver();
    else throw 1;
 &lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;&lt;br /&gt;Ok. Let&apos;s rewrite it using Erlang.&lt;br /&gt;&lt;br /&gt;First that springs to mind is the obvious line-by-line translation of the C++ code:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;
start(Driver) -&amp;gt;
    case Driver of
        mysql -&amp;gt;
            % connection happens here
            {};
        mnesia -&amp;gt;
            % connection happens here
            {};
        odbc -&amp;gt;
            % connection happens here
            {}
    end.
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;&lt;br /&gt;It&apos;s clear that you would call the function as follows:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;
start(mysql).
start(mnesia).
start(odbc).
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;Note that the &quot;case&quot; construct in Erlang also employs pattern matching.&lt;br /&gt;&lt;br /&gt;What if connection i a bulky piece of code spanning 10-20 lines? We could employ function guards of course::&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;pre&gt; 
start(Driver) when Driver == mysql -&amp;gt;
    % connection happens here
    {};

start(Driver) when Driver == mnesia -&amp;gt;
    % connection happens here
    {};

start(Driver) when Driver == odbc -&amp;gt;
    % connection happens here
    {}.
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;This is more like it. Function call hasn&apos;t chaned a bit: &lt;code&gt;start(&lt;i&gt;driver_name&lt;/i&gt;)&lt;/code&gt;. Guards, however, are not expressive enough. You have to read the definition of the function and only after that your eye cathes the guard. Is there a better way to do this? Of course!&lt;br /&gt;&lt;br /&gt;Recall that pattern matching involves a &quot;&lt;b&gt;rigidly defined&lt;/b&gt; pattern&quot;. What&apos;s more rigid than&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;
start(mysql) -&amp;gt;
    % connection happens here
    {};

start(mnesia) -&amp;gt;
    % connection happens here
    {};

start(odbc) -&amp;gt;
    % connection happens here
    {};
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;&lt;br /&gt;We can improve on our example and introduce options that will be passed to the connection code:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;
start(Driver) -&amp;gt;
    start(Driver, []).
        
start(mysql, Options) -&amp;gt;
    % connection happens here
    {};
    
start(mnesia, Options) -&amp;gt;
    % connection happens here
    {};
    
start(odbc, Options) -&amp;gt;
    % connection happens here
    {};
    
start(_, _) -&amp;gt;
    {error, driver_not_supported}.
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;Last lines simply states that for any other type of connection we through an error. Underscore means &quot;any variable&quot;, a sort of &quot;joker&quot;.&lt;br /&gt;&lt;br /&gt;That&apos;s a part of what, to me, is the &quot;Erlang Way&quot;. Very shortly and quite inaccurately this could be defined as: focus on what you need. A slight improvement of this definition is described in the concept of &quot;aggressve programming&quot;. See. &lt;a href=&quot;http://www.erlang.se/doc/programming_rules.shtml#HDR11&quot;&gt;Erlang programming rules&lt;/a&gt; for a description. &lt;br /&gt;&lt;br /&gt;That is, a program/module/function should do only the things it&apos;s meant to do. Under all other circumstances it should fail specifying why it failed, because it really should be the problem of the person who decided to (ab)use the program/module/function in the wrong way. As a result you end up with a small number of functions/modules which only do what they are meant to do. And this is quite handy&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://www.erlang.se/doc/programming_rules.shtml&quot;&gt;The same page&lt;/a&gt; lists other things in the &quot;Erlang way&quot;, in particular:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;br /&gt;- top-down programming (you start with abstractions and work towards details), &lt;br /&gt;- &quot;make it work correctly now and worry about otimizations later&quot;, &lt;br /&gt;- principle of least astonishment (the system must behave predictably)&lt;br /&gt;- &quot;aggressive&quot; programming etc.&lt;br /&gt; &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;&lt;br /&gt;Actually, this approach can be used - and is used! - in mainstream languages such as C++, Java, C#. However, in order to employ this approach in these languages, you need experience (quite a lot of it some times - a nod to C++). Erlang, on the other hand, encourages this approach right from the start.&lt;br /&gt;&lt;br /&gt;I general, I&apos;m not going to give up on Erlang in the forseeable future :) Unless it&apos;s in favour of Ne,erle, perhaps :))</description>
  <comments>http://community.livejournal.com/en_dmitriid/4339.html</comments>
  <category>erlang</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>5</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/3973.html</guid>
  <pubDate>Mon, 25 Sep 2006 07:23:17 GMT</pubDate>
  <title>erlsoap</title>
  <link>http://community.livejournal.com/en_dmitriid/3973.html</link>
  <description>Opensource projects, eh? They make you involve in all sorts of things :) Thanks to the ever unpredictable Lady Luck, Anton Fedorov decided to bring the &lt;a href=&quot;http://community.livejournal.com/ru_dmitriid/3968.html&quot;&gt;aforementioned erlsoap library&lt;/a&gt; up to date. &lt;br /&gt;&lt;br /&gt;So the battle ensued between me and the shiny new 0.4 version of erlsoap. This version decided it didn&apos;t like &lt;a href=&quot;http://rsdn.ru/ws/JanusAT.asmx&quot;&gt;RSDN&apos;s webservice&lt;/a&gt;. After some fruitful discussion with Anton a new, 0.4.1, version of erlsoap appeared. This version, however, didn&apos;t suit &lt;a href=&quot;http://code.google.com/u/qrilka/&quot;&gt;qrilka&lt;/a&gt; in the least :)) The problem lay with the inets library distributed with Erlang and used by erlsoap. Inets, as it turned out, doesn&apos;t support proxy authentication.&lt;br /&gt;&lt;br /&gt;So what&apos;s a developer got to do? I geared up  and went to hunt... ehm... to add support for a more advanced ibrowse library. As a result, I&apos;ve officially &lt;a href=&quot;http://forum.trapexit.org/viewtopic.php?p=21672#21672&quot;&gt;added my first patch to an opensource project&lt;/a&gt; which even brought me a mention in the soapclient module in erlsoap&apos;s new &lt;a href=&quot;http://forum.trapexit.org/download.php?id=15&quot;&gt;version 0.4.2&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now I&apos;m tuly happy :)</description>
  <comments>http://community.livejournal.com/en_dmitriid/3973.html</comments>
  <category>erlang</category>
  <category>orcas</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/3825.html</guid>
  <pubDate>Tue, 19 Sep 2006 13:41:51 GMT</pubDate>
  <title>The cavalry is coming!</title>
  <link>http://community.livejournal.com/en_dmitriid/3825.html</link>
  <description>Camrade &lt;a href=&quot;http://rsdn.ru/Users/Profile.aspx?uid=1546&quot;&gt;qrilka&lt;/a&gt; has shown interest in &lt;a href=&quot;http://code.google.com/p/orcas/&quot;&gt;Orcas&lt;/a&gt;. Right now we are not quite sure as to what is the best approach to SOAP in Erlang.&lt;br /&gt;&lt;br /&gt;Since &lt;a href=&quot;http://rsdn.ru/ws/JanusAT.asmx&quot;&gt;RSDN&apos;s webservice&lt;/a&gt; is quite small, one approach would be to implement all calls and parse all responses by hand. But that&apos;s boring, isn&apos;t it? :)&lt;br /&gt;&lt;br /&gt;Today I&apos;ve braced myself and went to war with &lt;a href=&quot;http://www.erlang-projects.org/Public/news/erlsoap_0.3/view&quot;&gt;erlsoap&lt;/a&gt;, which has been stagnating for the past two years. Well, you can check out the code &lt;a href=&quot;http://code.google.com/p/orcas/source&quot;&gt;yourself&lt;/a&gt;. The file is test_soap.erl, and you run it by &lt;table&gt;&lt;tr&gt;&lt;td bgcolor=&quot;gray&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;test_soap:run().&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;br /&gt;&lt;br /&gt;qrilka suggested that we use &lt;a href=&quot;http://yarivsblog.com/articles/tag/smerl&quot;&gt;Smerl&lt;/a&gt;. This still leaves quite a lot to do by hand. Anyway, tomorrow, time permitting, we&apos;ll take a look into the matter.</description>
  <comments>http://community.livejournal.com/en_dmitriid/3825.html</comments>
  <category>erlang</category>
  <category>orcas</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/3541.html</guid>
  <pubDate>Fri, 15 Sep 2006 14:45:33 GMT</pubDate>
  <title>Orcas</title>
  <link>http://community.livejournal.com/en_dmitriid/3541.html</link>
  <description>Well, I&apos;ve slowly started working on an offline client for RSDN.ru in Erlang.&lt;br /&gt;&lt;br /&gt;Here&apos;s the project page: &lt;a href=&quot;http://code.google.com/p/orcas/&quot;&gt;Orcas&lt;/a&gt;&lt;br /&gt;Here&apos;s &lt;a href=&quot;http://rsdn.ru/Forum/Message.aspx?mid=2112572&amp;amp;only=1&quot;&gt;anouncement of the fact&lt;/a&gt; on RSDN (in Russian)</description>
  <comments>http://community.livejournal.com/en_dmitriid/3541.html</comments>
  <category>projects</category>
  <category>rsdn</category>
  <category>erlang</category>
  <category>orcas</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/3294.html</guid>
  <pubDate>Mon, 04 Sep 2006 07:35:58 GMT</pubDate>
  <link>http://community.livejournal.com/en_dmitriid/3294.html</link>
  <description>Kosma Prutkov. Fruits of thought. # 66&lt;br /&gt;&lt;br /&gt;Many a thing we do not understand not because our reasoning is weak, but because we have no notion of them</description>
  <comments>http://community.livejournal.com/en_dmitriid/3294.html</comments>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/2884.html</guid>
  <pubDate>Mon, 21 Aug 2006 14:26:22 GMT</pubDate>
  <title>Dynamic languages rule</title>
  <link>http://community.livejournal.com/en_dmitriid/2884.html</link>
  <description>It seems to me that dynamic languages...That is, languages which have more dynamics built in... That is, nice languages to put it simply :)) Well, they rule. &lt;br /&gt;&lt;br /&gt;I&apos;ve been browsing Jakarta Commons&apos; source code using &lt;a href=&quot;http://www.koders.com/&quot;&gt;http://www.koders.com/&lt;/a&gt; (I actualy only needed their WordUtils in order to rewrite them in ColdFusion). An then I see &lt;a href=&quot;http://www.koders.com/java/fid81E5DE57AF2F1EFCA3D2A15B2F1D3B36005F7336.aspx&quot;&gt;Validate.java&lt;/a&gt;:&lt;br /&gt;&lt;pre style=&quot;background-color: #efefef&quot;&gt;
    public static void isTrue(boolean expression, String message, Object value) {
        if (expression == false) {
            throw new IllegalArgumentException(message + value);
        }
    }

    public static void isTrue(boolean expression, String message, long value) {
        if (expression == false) {
            throw new IllegalArgumentException(message + value);
        }
    }

    public static void isTrue(boolean expression, String message, double value) {
        if (expression == false) {
            throw new IllegalArgumentException(message + value);
        }
    }

    public static void isTrue(boolean expression) {
        if (expression == false) {
            throw new IllegalArgumentException(&quot;The validated expression is false&quot;);
        }
    }
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;:)) Static typing is the answer to everything they say, but at what cost? :))) I wonder if this could be rewritten... ColdFusion-style:&lt;br /&gt;&lt;pre style=&quot;background-color: #efefef&quot;&gt;
&amp;lt;cffunction name=&quot;isTrue&quot;&amp;gt;
    &amp;lt;cfargument name=&quot;expression&quot; type=&quot;boolean&quot; required=&quot;yes&quot;&amp;gt;    
    &amp;lt;cfargument name=&quot;message&quot; type=&quot;string&quot; required=&quot;no&quot;&amp;gt;
    &amp;lt;cfargument name=&quot;value&quot; type=&quot;any&quot; required=&quot;no&quot;&amp;gt;  
	
	&amp;lt;cfset msg=IIF(IsDefined(&apos;arguments.message&apos;), DE(arguments.message), DE(&quot;The validated expression is false&quot;))&amp;gt;
	&amp;lt;cfset v=IIF(IsDefined(&apos;arguments.value&apos;), DE(arguments.value), DE(&quot;&quot;))&amp;gt;
	
	&amp;lt;cfif arguments.expression EQ false&amp;gt;
		&amp;lt;cfthrow type=&quot;IllegalArgumentException&quot; message=msg &amp;amp; ToString(v)&amp;gt;
    &amp;lt;/cfif&amp;gt;
&amp;lt;/cffunction&amp;gt;
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Key moments here are  &lt;i&gt;required=&quot;true|false&quot;&lt;/i&gt; in argument definitions and the IsDefined(&apos;arguments....&apos;) function which, well, defines whether optional arguments exist. Oh, and don&apos;t forget about type=&quot;any&quot; which allows you to pass arguments of any type. And the ToString function :)&lt;br /&gt;&lt;br /&gt;Function overloading - is, undoubtedly, great. But I&apos;ll trade it IsDefined most of the time (when it&apos;s uses are justified, of course :) )&lt;br /&gt;&lt;br /&gt;PS. Correct me if I&apos;m wrong, but does Java really not have access to the array of arguments passed to a function? And I&apos;m not talking about &lt;a href=&quot;http://java.sun.com/developer/JDCTechTips/2005/tt1018.html&quot;&gt;Variable arity&lt;/a&gt;.</description>
  <comments>http://community.livejournal.com/en_dmitriid/2884.html</comments>
  <category>java</category>
  <category>coldfusion</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/2602.html</guid>
  <pubDate>Thu, 17 Aug 2006 07:46:03 GMT</pubDate>
  <title>Coldfusion и XML</title>
  <link>http://community.livejournal.com/en_dmitriid/2602.html</link>
  <description>It is a major pain in the nether regions of the body to work with a language which provides reasonable tools for working with XML and provides no sane tools to modify XML. I&apos;m talking about ColdFusion.&lt;br /&gt;&lt;br /&gt;Suppose we have the following piece of XML:&lt;br /&gt;&lt;pre style=&quot;background-color: #efefef&quot;&gt;
&amp;lt;xml&amp;gt;
    &amp;lt;root&amp;gt;
        &amp;lt;elem&amp;gt;
            &amp;lt;value&amp;gt;Text&amp;lt;/value&amp;gt;
        &amp;lt;/elem&amp;gt;
    &amp;lt;/root&amp;gt;
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If we read this piece into a variable called xmlDoc, we have &lt;i&gt;immedate&lt;/i&gt; access to the value &quot;Text&quot;:&lt;br /&gt;&lt;br /&gt;&lt;pre style=&quot;background-color: #efefef&quot;&gt;
txt = xmlDoc.root.elem.value.xmlText;
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now txt contains, as you may have guessed it, a string, &quot;Text&quot;.&lt;br /&gt;&lt;br /&gt;Moreover, if we have quite a handful of such elements, we may use an extremely convenient function XMLSearch which accepts (an unspecified subset of) XPath and returns an array of found elements.&lt;br /&gt;&lt;br /&gt;A real-world example now. Here&apos;s a stripped-down localization file from the project I&apos;m working on::&lt;br /&gt;&lt;br /&gt;&lt;pre style=&quot;background-color: #efefef&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;strings&amp;gt;
	&amp;lt;nspace NAME=&quot;global&quot;&amp;gt;
		&amp;lt;string CRC=&quot;73FB418E8CCD929E219338A555AA7EA4&quot;&amp;gt;
			&amp;lt;original&amp;gt;You need to login first&amp;lt;/original&amp;gt;
			&amp;lt;localized/&amp;gt;
		&amp;lt;/string&amp;gt;
		&amp;lt;string CRC=&quot;99DEA78007133396A7B8ED70578AC6AE&quot;&amp;gt;
			&amp;lt;original&amp;gt;Login&amp;lt;/original&amp;gt;
			&amp;lt;localized/&amp;gt;
		&amp;lt;/string&amp;gt;
	&amp;lt;/nspace&amp;gt;
	&amp;lt;controller NAME=&quot;admin&quot;&amp;gt;
		&amp;lt;action NAME=&quot;cities&quot;&amp;gt;
			&amp;lt;string CRC=&quot;FD8459135F9464065B708800B0BDF6D8&quot;&amp;gt;
				&amp;lt;original&amp;gt;Add a new city&amp;lt;/original&amp;gt;
				&amp;lt;localized/&amp;gt;
			&amp;lt;/string&amp;gt;
			&amp;lt;string CRC=&quot;F67FDD86A499050E0585BCA9EA023188&quot;&amp;gt;
				&amp;lt;original&amp;gt;Add city&amp;lt;/original&amp;gt;
				&amp;lt;localized/&amp;gt;
			&amp;lt;/string&amp;gt;
			&amp;lt;string CRC=&quot;4505DE1F3D02176AA6F1403778C5ADD1&quot;&amp;gt;
				&amp;lt;original&amp;gt;Region:&amp;lt;/original&amp;gt;
				&amp;lt;localized/&amp;gt;
			&amp;lt;/string&amp;gt;
		&amp;lt;/action&amp;gt;
	&amp;lt;/controller&amp;gt;
&amp;lt;/strings&amp;gt;
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Searching across this monster of a file is trivial:&lt;br /&gt;&lt;pre style=&quot;background-color: #efefef&quot;&gt;
searchString = &quot;/strings/controller[@NAME=&quot;&quot;admin&quot;&quot;]/action[@NAME=&quot;&quot;cities&quot;&quot;]/string[@CRC=&quot;&quot;&lt;i&gt;CRC&lt;/i&gt;&quot;&quot;]&quot;;
elems = XmlSearch(xmlDoc, searchString);

/* If there&apos;s only one elems, we return it (simplified example): */

return elems[1].localized.xmlString;
&lt;/pre&gt;where CRC is calculated using obscure Vodoo rituals :)&lt;br /&gt;&lt;br /&gt;Now, the question is: what if we want to change the value oа this element? The procedure required to do that evokes an unbearable desire to nuke Macromedia offices :)&lt;br /&gt;&lt;br /&gt;Scanning thorugh the docs reveals that &lt;i&gt;the only standard procedure&lt;/i&gt; to change the desired value of a tag involves the use of ArrayAppend function on the array of &quot;value&quot; from the array of &quot;elem&quot; from the array of &quot;root&quot;...&lt;br /&gt;&lt;br /&gt;That is... You can find an element, but you cannot manipulate it directly. You have to take the root element. Then you have to take an array of first-level elements anв find the desired one. In that element you once again take an array (of second-level elements) and find the desired one. In that element you take an array of third-level elements and find the desired one. And finally, you take an array of fourth-level elements and find the desired one. If such an element does not exist, you append it to the array of fourth-level elements. Save.&lt;br /&gt;&lt;br /&gt;Anyway, here&apos;s what it looks like in the end:&lt;br /&gt;&lt;pre style=&quot;background-color: #efefef&quot;&gt;
// Add a new string
ArrayAppend(xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].XmlChildren, XMLElemNew(xmlDoc, &quot;string&quot;));

// Find its position
stringIndex = ArrayLen(xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].XmlChildren);

// Change its attribute
xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].string[stringIndex].xmlAttributes.crc = Hash(t);

// Add &quot;original&quot; to it
ArrayAppend(xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].string[stringIndex].xmlChildren, XMLElemNew(xmlDoc, &quot;original&quot;));

// Find original&apos;s position
orgIndex = ArrayLen(xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].string[stringIndex].xmlChildren);

// Add text
xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].string[stringIndex].original.xmlText = t;

// Add &quot;localized&quot;
ArrayAppend(xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].string[stringIndex].xmlChildren, XMLElemNew(xmlDoc, &quot;localized&quot;));

// Obtain its index
locIndex = ArrayLen(xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].string[stringIndex].xmlChildren);

// Add text
xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].string[stringIndex].localized.xmlText = &apos;&apos;;
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;:)))&lt;br /&gt;&lt;br /&gt;I am only grateful that I had to write this function only once. And it took me the better part of the day...</description>
  <comments>http://community.livejournal.com/en_dmitriid/2602.html</comments>
  <category>coldfusion</category>
  <category>xml</category>
  <category>wtf</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>6</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/2345.html</guid>
  <pubDate>Fri, 28 Jul 2006 07:53:00 GMT</pubDate>
  <title>Named Parameters</title>
  <link>http://community.livejournal.com/en_dmitriid/2345.html</link>
  <description>Ever since I saw Lisp I&apos;ve sorely missed named function parameters. What the heck is that? Ok, here goes...&lt;br /&gt;&lt;br /&gt;&lt;font size=&quot;1&quot;&gt;Lisp examples are quoted directly from &lt;/font&gt;&lt;a href=&quot;http://www.gigamonkeys.com/book/functions.html&quot;&gt;&lt;font size=&quot;1&quot;&gt;Practical Common Lisp&lt;/font&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Let&apos;s refresh our knowledge of WinAPI - the dearly beloved API of all Windows developers. For instance, &lt;a href=&quot;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shellexecute.asp&quot;&gt;ShellExecute&lt;/a&gt;:&lt;br /&gt;&lt;pre style=&quot;BACKGROUND-COLOR: #efefef&quot;&gt;
&lt;font color=&quot;#0000ff&quot;&gt;HINSTANCE&lt;/font&gt; ShellExecute(      
    &lt;font color=&quot;#0000ff&quot;&gt;HWND&lt;/font&gt; hwnd,
    &lt;font color=&quot;#0000ff&quot;&gt;LPCTSTR&lt;/font&gt; lpOperation,
    &lt;font color=&quot;#0000ff&quot;&gt;LPCTSTR&lt;/font&gt; lpFile,
    &lt;font color=&quot;#0000ff&quot;&gt;LPCTSTR&lt;/font&gt; lpParameters,
    &lt;font color=&quot;#0000ff&quot;&gt;LPCTSTR&lt;/font&gt; lpDirectory,
    &lt;font color=&quot;#0000ff&quot;&gt;INT&lt;/font&gt; nShowCmd
);
&lt;/pre&gt;On the whole I think I remember which parameters this function requires and why. Not too clearly though. I do remember the first three. The fourth might spring to mind while writing the function. The last too however, are quire elusive and I&apos;m never quite sure which goes where and when. The problem gets worse if you remember that som parameters, &lt;font face=&quot;Courier&quot;&gt;hwnd, lpParameters, lpDirectory&lt;/font&gt; in our case, are optional and can be replaced with NULLs. So, we would quite often invoke this function like this::&lt;br /&gt;&lt;pre style=&quot;BACKGROUND-COLOR: #efefef&quot;&gt;
&lt;font color=&quot;#0000ff&quot;&gt; &lt;font color=&quot;#000000&quot;&gt;hResult =&lt;/font&gt; &lt;/font&gt;ShellExecute(NULL, &quot;open&quot;, &quot;path/to/file&quot;, NULL, NULL, SW_SHOWDEFAULT);
&lt;/pre&gt;Scary, huh? Now imagine if we could write this function like this:&lt;br /&gt;&lt;pre style=&quot;BACKGROUND-COLOR: #efefef&quot;&gt;
&lt;font color=&quot;#0000ff&quot;&gt; &lt;font color=&quot;#000000&quot;&gt;hResult =&lt;/font&gt; &lt;/font&gt;ShellExecute(operation=&quot;open&quot;, file=&quot;path/to/file&quot;);
&lt;/pre&gt;Beautiful. Now, this is what named parameters are all about.&lt;br /&gt;&lt;br /&gt;Let&apos;s go back to Lisp. Let&apos;s consider the following function:&lt;br /&gt;&lt;pre style=&quot;BACKGROUND-COLOR: #efefef&quot;&gt;
&lt;font color=&quot;#0000ff&quot;&gt; &lt;/font&gt;&lt;font color=&quot;#ff8000&quot;&gt;(&lt;/font&gt;&lt;strong&gt;defun&lt;/strong&gt; foo &lt;font color=&quot;#ff8000&quot;&gt;(&lt;/font&gt;&lt;strong&gt;&amp;amp;key&lt;/strong&gt; a b c&lt;font color=&quot;#ff8000&quot;&gt;) (&lt;/font&gt;&lt;strong&gt;list&lt;/strong&gt; a b c&lt;font color=&quot;#ff8000&quot;&gt;))&lt;/font&gt;
&lt;/pre&gt;&lt;br /&gt;This function accepts three parameters and simply listst them in their order. This is how this function behaves when we invoke it in numerous ways:&lt;br /&gt;&lt;pre style=&quot;BACKGROUND-COLOR: #efefef&quot;&gt;
(foo)                ==&amp;gt; (NIL NIL NIL)
(foo :a 1)           ==&amp;gt; (1 NIL NIL)
(foo :b 1)           ==&amp;gt; (NIL 1 NIL)
(foo :c 1)           ==&amp;gt; (NIL NIL 1)
(foo :a 1 :c 3)      ==&amp;gt; (1 NIL 3)
(foo :a 1 :b 2 :c 3) ==&amp;gt; (1 2 3)
(foo :a 1 :c 3 :b 2) ==&amp;gt; (1 2 3)
&lt;/pre&gt;&lt;br /&gt;Note the last line. Even though the order or parameters is incorrect, the function still behaves as designed. Now, that&apos;s the beauty and power of named parameters. A developer now only needs to know &lt;strong&gt;which parameters&lt;/strong&gt; a function requires, not their &lt;strong&gt;not their order&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Unfortunately none of the mainstream languages support named parameters, not natively at least. That is why invoking a function (especially a WinApi function) is a long and tedious process whereas we could simply make do with passing a limited number of named arguments (as my example with ShellExecute shows).&lt;br /&gt;&lt;br /&gt;I am currently developing in ColdFusion and it supports named parameters natively (though you cannot honestly call it a mainstream language):&lt;br /&gt;&lt;pre style=&quot;BACKGROUND-COLOR: #efefef&quot;&gt;
&lt;font color=&quot;#800000&quot;&gt;&amp;lt;&lt;strong&gt;cffunction&lt;/strong&gt;&lt;/font&gt; &lt;font color=&quot;#800000&quot;&gt;name=&lt;/font&gt;&quot;function&quot; &lt;font color=&quot;#800000&quot;&gt;access=&lt;/font&gt;&quot;public&quot;&lt;font color=&quot;#800000&quot;&gt;&amp;gt;&lt;/font&gt;
    &lt;font color=&quot;#800000&quot;&gt;&amp;lt;&lt;strong&gt;cfargument&lt;/strong&gt; name=&lt;/font&gt;&quot;arg1&quot; &lt;font color=&quot;#800000&quot;&gt;type=&lt;/font&gt;&quot;numeric&quot; &lt;font color=&quot;#800000&quot;&gt;required=&lt;/font&gt;&quot;yes&quot;&amp;gt;
&lt;font color=&quot;#800000&quot;&gt;    &amp;lt;&lt;strong&gt;cfargument&lt;/strong&gt; name=&lt;/font&gt;&quot;arg2&quot; &lt;font color=&quot;#800000&quot;&gt;type=&lt;/font&gt;&quot;string&quot; &lt;font color=&quot;#800000&quot;&gt;required=&lt;/font&gt;&quot;no&quot;&amp;gt;
    &lt;font color=&quot;#ff8000&quot;&gt;&amp;lt;!--- и так далее ---&amp;gt;&lt;/font&gt;


&lt;font color=&quot;#800000&quot;&gt;&amp;lt;/&lt;strong&gt;cffunction&lt;/strong&gt;&amp;gt;&lt;/font&gt;
&lt;/pre&gt;This function is invoked as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre style=&quot;BACKGROUND-COLOR: #efefef&quot;&gt;
&lt;font color=&quot;#800000&quot;&gt;&amp;lt;&lt;strong&gt;cfset&lt;/strong&gt;&lt;/font&gt; &lt;font color=&quot;#800000&quot;&gt;function(arg1=1, arg2=&apos;string&apos;)&lt;/font&gt;&lt;font color=&quot;#800000&quot;&gt;&amp;gt;&lt;/font&gt;
&lt;/pre&gt;As in Lisp, the order of arguments is not important as long as they are named.&lt;br /&gt;&lt;br /&gt;Some languages (scripting languages, mostly) emulate this behaviour through the use of hashes. PHP anyone?&lt;br /&gt;&lt;br /&gt;&lt;pre style=&quot;BACKGROUND-COLOR: #efefef&quot;&gt;
&lt;strong&gt;function&lt;/strong&gt; a_func($params)
{
    &lt;strong&gt;if&lt;/strong&gt;(&lt;font color=&quot;#000080&quot;&gt;isset&lt;/font&gt;($params[&lt;font color=&quot;#800000&quot;&gt;&apos;arg1&apos;&lt;/font&gt;])) &lt;font color=&quot;#008000&quot;&gt;/* do stuff */&lt;/font&gt;
    &lt;strong&gt;if&lt;/strong&gt;(&lt;font color=&quot;#000080&quot;&gt;isset&lt;/font&gt;($params[&lt;font color=&quot;#800000&quot;&gt;&apos;arg2&apos;&lt;/font&gt;])) &lt;font color=&quot;#008000&quot;&gt;/* do stuff */&lt;/font&gt;
}
&amp;nbsp;
&lt;font color=&quot;#008000&quot;&gt;/* Calling the function */&lt;/font&gt;
$result = a_func(&lt;font color=&quot;#000080&quot;&gt;array&lt;/font&gt;(&lt;font color=&quot;#800000&quot;&gt;&apos;arg1&apos;&lt;/font&gt; =&amp;gt; &lt;font color=&quot;#0000ff&quot;&gt;123&lt;/font&gt;, &lt;font color=&quot;#800000&quot;&gt;&apos;arg2&apos;&lt;/font&gt; =&amp;gt; &lt;font color=&quot;#800000&quot;&gt;&apos;a string&apos;&lt;/font&gt;));
&lt;/pre&gt;That is, we actually pass an array, but it serves our purpose well enough. Ruby employs exactly the same technique:&lt;br /&gt;&lt;br /&gt;&lt;pre style=&quot;BACKGROUND-COLOR: #efefef&quot;&gt;
&lt;font color=&quot;#008000&quot;&gt;# find from ActiveRecord
&lt;/font&gt;      &lt;font color=&quot;#000080&quot;&gt;&lt;strong&gt;def&lt;/strong&gt;&lt;/font&gt; &lt;font color=&quot;#008080&quot;&gt;&lt;strong&gt;find&lt;/strong&gt;&lt;/font&gt;(*args)
        options = extract_options_from_args!(args)
        validate_find_options(options)
        set_readonly_option!(options)

        &lt;font color=&quot;#000080&quot;&gt;&lt;strong&gt;case&lt;/strong&gt;&lt;/font&gt; args.first
          &lt;font color=&quot;#000080&quot;&gt;&lt;strong&gt;when&lt;/strong&gt;&lt;/font&gt; &lt;font color=&quot;#808000&quot;&gt;:first&lt;/font&gt; &lt;strong&gt;&lt;font color=&quot;#000080&quot;&gt;then&lt;/font&gt;&lt;/strong&gt; find_initial(options)
          &lt;font color=&quot;#000080&quot;&gt;&lt;strong&gt;when&lt;/strong&gt;&lt;/font&gt; &lt;font color=&quot;#808000&quot;&gt;:all&lt;/font&gt;   &lt;strong&gt;&lt;font color=&quot;#000080&quot;&gt;then&lt;/font&gt;&lt;/strong&gt; find_every(options)
          &lt;font color=&quot;#000080&quot;&gt;&lt;strong&gt;else&lt;/strong&gt;&lt;/font&gt;             find_from_ids(args, options)
        &lt;font color=&quot;#000080&quot;&gt;&lt;strong&gt;end
      end
&lt;/strong&gt;&lt;font color=&quot;#008000&quot;&gt;
&amp;nbsp;
# Calling the function:&lt;/font&gt;
&lt;font color=&quot;#000000&quot;&gt;Person.&lt;font color=&quot;#000000&quot;&gt;find&lt;/font&gt;(&lt;font color=&quot;#808000&quot;&gt;:first&lt;/font&gt;, &lt;font color=&quot;#808000&quot;&gt;:order&lt;/font&gt; =&amp;gt; &lt;font color=&quot;#800080&quot;&gt;&quot;created_on DESC&quot;&lt;/font&gt;, &lt;font color=&quot;#808000&quot;&gt;:offset&lt;/font&gt; =&amp;gt; &lt;font color=&quot;#008080&quot;&gt;5&lt;/font&gt;)
Person.&lt;font color=&quot;#000000&quot;&gt;find&lt;/font&gt;(&lt;font color=&quot;#808000&quot;&gt;:all&lt;/font&gt;, &lt;font color=&quot;#808000&quot;&gt;:group&lt;/font&gt; =&amp;gt; &lt;font color=&quot;#800080&quot;&gt;&quot;category&quot;&lt;/font&gt;)
Person.&lt;font color=&quot;#000000&quot;&gt;find&lt;/font&gt;(&lt;font color=&quot;#808000&quot;&gt;:all&lt;/font&gt;, &lt;font color=&quot;#808000&quot;&gt;:offset&lt;/font&gt; =&amp;gt; &lt;font color=&quot;#008080&quot;&gt;10&lt;/font&gt;, &lt;font color=&quot;#808000&quot;&gt;:limit&lt;/font&gt; =&amp;gt; &lt;font color=&quot;#008080&quot;&gt;10&lt;/font&gt;)&lt;/font&gt;
&lt;font color=&quot;#008000&quot;&gt;# where Person is an object of type Activerecord&lt;/font&gt;
&lt;/font&gt;&lt;/pre&gt;However, none of these can even compare to Lisp&apos;s implementation. ColdFusion, for instance, doesn&apos;t accept an arbitrary number of parameters (see Lisp&apos;s &amp;rest). Hashes both in PHP and Ruby are rather cumbersome because implementation of the function may become convoluted (or you have to resort to using less-than-safe &lt;a href=&quot;http://tr.php.net/manual/en/function.extract.php&quot;&gt;extract&lt;/a&gt; or &lt;a href=&quot;http://caboo.se/doc/classes/ActiveRecord/Base.html#M005745&quot;&gt;extract_options_from_args!&lt;/a&gt; functions). I&apos;m not even talking other languages like С/С++, C# and Java :). Some languages though, like Haskell, Erlang and Nemerle, have pattern matching allows the developer to work arounв named parameters in a very elegant manner, but that is a story for another day.</description>
  <comments>http://community.livejournal.com/en_dmitriid/2345.html</comments>
  <category>ruby</category>
  <category>coldfusion</category>
  <category>lisp</category>
  <category>php</category>
  <category>general</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/2208.html</guid>
  <pubDate>Wed, 26 Jul 2006 07:29:20 GMT</pubDate>
  <title>Running along the rails</title>
  <link>http://community.livejournal.com/en_dmitriid/2208.html</link>
  <description>In July 2006 CNN Money gave a fellow named David Heinemeier Hansson the 50th place in their &lt;a href=&quot;http://money.cnn.com/magazines/business2/peoplewhomatter/index.html&quot;&gt;list of most influential people in contemporary online business&lt;/a&gt; (also known as Business 2.0).&lt;br /&gt;&lt;br /&gt;What? You don&apos;t know who this fellow is? Well, he is the creator of &lt;a href=&quot;http://www.rubyonrails.org/&quot;&gt;Ruby on Rails&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Ruby on Rails is an iPod of online technologies:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;br /&gt;    Like iPod, Rails doesn&apos;t use any new revolutionary technologies:&lt;br /&gt;    &lt;ul&gt;&lt;br /&gt;        &lt;li&gt; - Ruby itself appeared in 1995 &lt;/li&gt;&lt;br /&gt;        &lt;li&gt; - The MVC (Model-View-Controller) pattern was first described back in 1979 &lt;/li&gt;&lt;br /&gt;    &lt;/ul&gt;&lt;br /&gt;    and so on&lt;br /&gt; &lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;br /&gt;    Both iPod and Rails, when they appeared, were the cause an unprecedented buzz and discussion.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;br /&gt;    Rails&apos;s fans, much like iPod&apos;s fans, are blind to the shortcomings of their favorite toy and are ready to rip any critic to pieces (or worse).&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;br /&gt;    Rails, like iPod, has created numerous clones which are striving to duplicate the functionality without actually introducing any new ideas:&lt;br /&gt;    &lt;ul&gt;&lt;br /&gt;        &lt;li&gt; - PHP:  &lt;a href=&quot;http://cakephp.org/&quot;&gt;CakePHP&lt;/a&gt; and &lt;a href=&quot;http://framework.zend.com/&quot;&gt;Zend Framework&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;        &lt;li&gt; - ColdFusion: &lt;a href=&quot;http://cfwheels.com/&quot;&gt;ColdFusion on Wheels&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;        &lt;li&gt; - .NET: &lt;a href=&quot;http://www.castleproject.org/index.php/MonoRail&quot;&gt;MonoRail&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;        &lt;li&gt; - Perl has &lt;a href=&quot;http://www.catalystframework.org/&quot;&gt;Catalyst&lt;/a&gt;, though this framewrok isn&apos;t originally based on Rails&lt;/li&gt;&lt;br /&gt;        &lt;li&gt; - Python has &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt;, though its creator stated that this is not a Rails clone&lt;/li&gt;&lt;br /&gt;    &lt;/ul&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;So, why Rails has not only appeared, but also become very popular and eagerly cloned?&lt;br /&gt;&lt;br /&gt;I suppose this happened because Rails (and iPod, too) showed us that technology can be humane. &lt;br /&gt;&lt;br /&gt;In the case of Rails you can obtain interesting result fast - lightning fast (nonbelievers can check out &lt;a href=&quot;http://www.rubyonrails.org/screencasts&quot;&gt;Rails screencasts&lt;/a&gt;). Most of the time you spend in Rails is not fighting databases, or sessions, or files, or anything else, but actually writing the logic of your application.&lt;br /&gt;&lt;br /&gt;Additionally, Rails lowers the entry level for the MVC pattern (quite a complex pattern, actually). You simply forget about it, it comes to you naturally.&lt;br /&gt;&lt;br /&gt;Rails is, in essence, a ready and sound foundation that let&apos;s you build your own house. You may choose either a number of available blocks or just build everything brick by brick. Most other framewroks, on the contrary, have been providing you with either a finished house or with a number of raw materials and a dozer.&lt;br /&gt;&lt;br /&gt;So, this David Heinemeier Hansson fella has again proved that no &quot;designed by committee&quot; system/framework (even if this committee is a multi-billion dollar corporation) can ever compete with frameworks that people build for themselves. After all, people know better about their own needs than a committe ever will.&lt;br /&gt;&lt;br /&gt;Anyway, I can&apos;t wait to see what happens to web technologies 5 years from now. After all, too many developers have accustomed themselves to thу idea of humane technology to ever turn back. I hope.</description>
  <comments>http://community.livejournal.com/en_dmitriid/2208.html</comments>
  <category>web</category>
  <category>rails</category>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/1808.html</guid>
  <pubDate>Thu, 20 Jul 2006 09:44:14 GMT</pubDate>
  <title>Winter has come...</title>
  <link>http://community.livejournal.com/en_dmitriid/1808.html</link>
  <description>After some consideration we have decided to develop our project in ColdFusion. The reason is simple - there are some developers who can help us should the need arise. There are no Rubyists in sight, however...&lt;br /&gt;&lt;br /&gt;I have mixed feelings about ColdFusion so far. I&apos;m quite unnerved by CFML (sort of SGML-based, but not quite) and DreamWeaver&apos;s stupid-stupid-stupid wizards which break all code formatting once applied.&lt;br /&gt;&lt;br /&gt;Stay tuned for more rants...</description>
  <comments>http://community.livejournal.com/en_dmitriid/1808.html</comments>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://community.livejournal.com/en_dmitriid/1622.html</guid>
  <pubDate>Tue, 04 Jul 2006 16:13:13 GMT</pubDate>
  <title>Web programming. Revisited</title>
  <link>http://community.livejournal.com/en_dmitriid/1622.html</link>
  <description>On the heels of &lt;a href=&quot;http://community.livejournal.com/ru_dmitriid/1464.html&quot;&gt;the last post&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;Found &lt;a href=&quot;http://community.livejournal.com/en_dmitriid/1386.html&quot;&gt;here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;http://hinchcliffe.org/img/web20stratigraphic.jpg&quot; title=&quot;&quot;&gt;&lt;br /&gt;&lt;br /&gt;Where else, other than in Web programming that is, can you find such a mash-up? :)</description>
  <comments>http://community.livejournal.com/en_dmitriid/1622.html</comments>
  <lj:security>public</lj:security>
  <lj:poster>dmitriid</lj:poster>
  <lj:posterid>5101375</lj:posterid>
  <lj:reply-count>0</lj:reply-count>
</item>
</channel>
</rss>
