<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Of course I still use Perl</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/" />
    <link rel="self" type="application/atom+xml" href="http://blogs.perl.org/users/steven_haryanto/atom.xml" />
    <id>tag:blogs.perl.org,2009-11-03:/users/steven_haryanto//197</id>
    <updated>2013-05-01T13:25:04Z</updated>
    <subtitle>Adventures in Perl, which I have been in love-hate-love relationship with for more than a decade. A language that is dead, undead, alive, and above all: damn useful.</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.38</generator>

<entry>
    <title>Introducing Text::ANSITable</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2013/05/introducing-textansitable.html" />
    <id>tag:blogs.perl.org,2013:/users/steven_haryanto//197.4634</id>

    <published>2013-05-01T11:46:10Z</published>
    <updated>2013-05-01T13:25:04Z</updated>

    <summary>Even in the good old days of DOS, we already had color tables and extended ASCII characters to draw various border styles. So why limit ourselves with something like Text::ASCIITable? Introducing Text::ANSITable to make your text tables look pretty in...</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>Even in the good old days of DOS, we already had color tables and extended ASCII characters to draw various border styles. So why limit ourselves with something like Text::ASCIITable? Introducing <a href="http://metacpan.org/module/Text::ANSITable">Text::ANSITable</a> to make your text tables look pretty in terminals. See pictures for some examples:</p>

<p><img src="/users/steven_haryanto/ansitable1.png" /></p>

<p><img src="/users/steven_haryanto/ansitable2.png" /></p>

<p><img src="/users/steven_haryanto/ansitable3.png" /></p>

<p><img src="/users/steven_haryanto/ansitable4.png" /></p>

<p><img src="/users/steven_haryanto/ansitable5.png" /></p>

<p>Features:</p>

<ul>
<li>Drawing borders with box-drawing and Unicode characters.
<li>Border styles. You can select and even create your own border styles. Border styles support things like custom characters, etc.
<li>Full color support (256 on any xterm-256color terminal emulators, and true color on Konsole/Yakuake). Graceful degradation (autoreduce colors) on terminals that do not support higher color depth.
<li>Color themes. You can select and even create your own color themes. Color themes support things like random/custom/gradation colors, etc.
<li>Wide character support. Your tables will still be aligned even if your text contains wide characters.
<li>ANSI support. Your tables will still be aligned even if your text contains ANSI escape codes.
<li>Modular and flexible formatting system for things like text wrapping, highlighting, number formatting (thousands, scientific, kilo/kibi formatting), sprintf-style formatting, etc).
<li>Per-column/per-row/per-cell styling
<li>Row/column filtering
<li>Column reordering.
</ul>

<p>Compared to Text::ASCIITable, Text::ANSITable uses lowercase_with_underscore for method names instead of CamelCase. I know a lot of Perl programmers, me included, prefer the former.</p>

<p>It's an early release so there are bound to be some quirks and bugs, but the basic features are already there. Enjoy!<br />
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Ruby&apos;s share drops on github, Perl&apos;s stays</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2013/04/rubys-share-drops-on-github-perls-stays.html" />
    <id>tag:blogs.perl.org,2013:/users/steven_haryanto//197.4588</id>

    <published>2013-04-19T00:40:39Z</published>
    <updated>2013-04-19T07:42:28Z</updated>

    <summary>Source: https://github.com/languages Oct 4, 2012: JavaScript 21% Ruby 14% Python 8% Java 8% Shell 8% PHP 7% C 6% C++ 4% Perl 4% Objective-C 3% Apr 19, 2012: JavaScript 21% Ruby 12% Java 8% Python 8% Shell 8% PHP 7%...</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>Source: <a href="https://github.com/languages">https://github.com/languages</a></p>

<div>Oct 4, 2012:</div>

<pre>JavaScript 21%
Ruby 14%
Python 8%
Java 8%
Shell 8%
PHP 7%
C 6%
C++ 4%
Perl 4%
Objective-C 3%</pre>

<div>Apr 19, 2012:</div>

<pre>JavaScript 21%
Ruby 12%
Java 8%
Python 8%
Shell 8%
PHP 7%
C 6%
C++ 5%
Perl 4%
Objective-C 3%</pre>

<p>Java moves to 3rd position to replace Python which is now in the 4th. Perl's place stays the same at the 9th, as well as its share at 4%. Ruby's share drops pretty significantly from 14% to 12%. More precise numbers are not provided.</p>

<p>I guess this is just a normalization process as Ruby projects were the early adopters at github. Kind of reminds me about the current normalization process where other languages replace Perl for web applications, because Perl used to dominate and was the early language during the pre-dotcom-boom/bust era.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Hacktivity report (Jan-Mar 2013)</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2013/04/hacktivity-report-jan-mar-2013.html" />
    <id>tag:blogs.perl.org,2013:/users/steven_haryanto//197.4555</id>

    <published>2013-04-12T10:45:18Z</published>
    <updated>2013-04-12T16:46:25Z</updated>

    <summary>Previous reports: 2012 year-end, Apr-Jul 2012, ... Data::Sah. All through January I mostly worked on Data::Sah. In the second week of February, I completed what I call the first stage: some core set of clauses which I use regularly and...</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>Previous reports: <a href="http://blogs.perl.org/users/steven_haryanto/2012/12/personal-end-of-year-report-for-2012.html">2012 year-end</a>, <a href="http://blogs.perl.org/users/steven_haryanto/2012/08/hacktivity-report-apr-jul-2012.html">Apr-Jul 2012</a>, ...</p>

<p><b>Data::Sah</b>. All through January I mostly worked on <a href="http://metacpan.org/module/Data::Sah">Data::Sah</a>. In the second week of February, I completed what I call the first stage: some core set of clauses which I use regularly and a working Perl and JavaScript compiler. I can already compile most of the schemas which I use in my programs. It's been deployed in several productions already, e.g. an API service for a license server and report email processing system. There are obviously many things missing, the usual 10% hard part. But I haven't seen the need for another rewrite so far, which means the current implementation (the second, or third IIRC) is not so hackish after all.</p>

<p><b>SHARYANTO::SQL::Schema and Postgres</b>. Most of February was spent on coding for $work, related to processing <a href="http://www.spamexperts.com">SpamExperts</a> report emails. During this period I became fed up with two of SQLite's main drawbacks: very limited ALTER TABLE functionality and its poor concurrency. I decided to ditch it altogether and migrated to the rich data type world of Postgres. It's a breath of fresh air, even when compared to MySQL, mainly as I can do proper date arithmetics and have true boolean type. <a href="http://metacpan.org/module/SHARYANTO::SQL::Schema">SHARYANTO::SQL::Schema</a> got written during this time (while I hope to use something like <a href="http://sqitch.org">Sqitch</a> someday, what I needed was something quick and simple, where everything is included in a single script, and no fancy features yet like per-branch/per-feature SQL sets). Postgres' transactional DDL <i>really</i> helps when doing schema upgrades, which can fail in the middle due to typos in SQL commands. Now I can freely and frequently evolve database schema without pain.</p>

<p><b>CPAN Lists</b>. Right after Data::Sah, the original plan was to continue the design of my form processing framework (which will integrate Sah and its JavaScript validator generating capability). Eventually I got distracted before going very far. This time with <a href="https://cpanlists.org/">CPAN Lists</a> which is inspired by <a href="http://blogs.perl.org/users/neilb/2013/03/the-cpan-unknown-usage-problem.html">own comment to a Neil Bowers' blog post</a> to create something in the spirit of Amazon's List Mania!: creating personal lists of CPAN modules and letting people commenting on them. I got the API part almost complete (will be described in a separate blog post) but haven't got around to creating the web interface yet. Have I mentioned that I suck at creating web/HTML interfaces? However, I managed to learn some <a href="http://metacpan.org/module/Mojolicious">Mojolicious</a>, Bootstrap, and Bitcard API along the way. BTW, I chose <a href="http://metacpan.org/module/Dancer">Dancer</a> for a very trivial web application last year, but somehow got tipped over to Mojolicious this time.</p>

<p><b>Text::ANSI::Util</b>. The other thing that distracts me is <a href="http://metacpan.org/module/Text::ANSI::Util">Text::ANSI::Util</a> which will be required by my upcoming Text::ANSITable (previously Text::PrettyTable) to replace the venerable <a href="http://metacpan.org/module/Text::ASCIITable">Text::ASCIITable</a> due to the desire to look prettier on the terminal.</p>

<p><b>Others</b>. Some other modules that got some love during this period: <a href="http://metacpan.org/module/dux">dux</a>, <a href="http://metacpan.org/module/Perinci::Access::HTTP::Server">Perinci::Access::HTTP::Server</a>. Some other new modules that got created during this period: <a href="http://metacpan.org/module/App::ListPrereqs">App::ListPrereqs</a>, <a href="http://metacpan.org/module/App::smtpstatus">App::smtpstatus</a>, <a href="http://metacpan.org/module/SyntaxHighlight::Any">SyntaxHighlight::Any</a>, <a href="http://metacpan.org/module/Carp::Always::SyntaxHighlightSource">Carp::Always::SyntaxHighlightSource</a>, <a href="http://metacpan.org/module/App::cal::id">App::cal::id</a>.</p>]]>
        
    </content>
</entry>

<entry>
    <title>::NonOO suffix for non-OO version of a module</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2013/04/nonoo-suffix-for-non-oo-version-of-a-module.html" />
    <id>tag:blogs.perl.org,2013:/users/steven_haryanto//197.4552</id>

    <published>2013-04-12T00:31:44Z</published>
    <updated>2013-04-12T00:37:04Z</updated>

    <summary>I wrote one this morning: Number::Closest::NonOO is the non-OO version of Number::Closest (plus with some additional features). Is there an existing convention for this? Or can you suggest a better candidate? Can&apos;t seem to find or be able to come...</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    <category term="cpan" label="cpan" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>I wrote one this morning: <a href="http://metacpan.org/module/Number::Closest::NonOO">Number::Closest::NonOO</a> is the non-OO version of <a href="http://metacpan.org/module/Number::Closest">Number::Closest</a> (plus with some additional features).</p>

<p>Is there an existing convention for this? Or can you suggest a better candidate? Can't seem to find or be able to come up with any. <i>::Simple</i> is too vague (and a bit misleading). <i>::Functional</i>? <i>::Function</i>? <i>::Procedural</i>? <i>::NonMoose</i> implies an OO version but without using Moose. <i>NOO</i> is not immediately obvious.</p>]]>
        
    </content>
</entry>

<entry>
    <title>By all means, try out $LANG, but also give Perl a real chance (a.k.a.: Good tools)</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2013/04/by-all-means-try-out-lang-but-also-give-perl-a-real-chance-aka-good-tools.html" />
    <id>tag:blogs.perl.org,2013:/users/steven_haryanto//197.4512</id>

    <published>2013-04-09T18:03:11Z</published>
    <updated>2013-04-09T18:20:39Z</updated>

    <summary>A lot of things mentioned about Emacs in this short essay (via Reddit) also ring true about Perl to me. Good tools are investments. Learning Perl to a sufficiently advanced level is not easy. Like any aged tool, Perl has...</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    <category term="fluffpiece" label="fluff-piece" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>A lot of things mentioned about Emacs in <a href="http://www.b-list.org/weblog/2013/apr/05/good-tools/">this short essay</a> (<a href="http://www.reddit.com/r/programming/comments/1bq2oo/by_all_means_try_out_sublime_text_but_also_give/">via Reddit</a>) also ring true about Perl to me.</p>

<p><b>Good tools are investments</b>. Learning Perl to a sufficiently advanced level is not easy. Like any aged tool, Perl has quite a bit of idiosyncrasies and quirks that still exist due to maintaining backward compatibility. But there's not a single working day that I don't benefit from knowing Perl. Learning Perl has also introduced me to regexes (to a level deeper than it would have been if I had learned other languages) and various other technologies.</p>

<p><b>Good tools give confidence</b>. I certainly feel that whenever it comes to most text manipulation or automation tasks, I can rely on Perl and CPAN.</p>

<p><b>Good tools are timeless</b>. Sometimes I can't believe that it has been 17 years since I first knew Perl. Other languages come and go, and other tools even more so, but Perl sticks. Virtually all of the Perl scripts that I wrote back then can still run on my current system's Perl. The same cannot be said with some other languages (even shells). Isn't that amazing?</p>

<p><b>Good tools grow with you</b>. Perl still surprises and amazes me to this day. CPAN delights me constantly.</p>

<p>Give the original article a read. You'll probably enjoy it (and perhaps be intrigued to learn Perl and/or Emacs).</p>]]>
        
    </content>
</entry>

<entry>
    <title>OI::M::Finally({IO::All})</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2013/04/oimfinallyioall.html" />
    <id>tag:blogs.perl.org,2013:/users/steven_haryanto//197.4502</id>

    <published>2013-04-06T02:35:14Z</published>
    <updated>2013-04-06T02:38:57Z</updated>

    <summary>Get it? (Meant to post this to perlmonks, but the site&apos;s submission form is missing the [Add] button right now). Anyway, as a long time user of File::Slurp who utilizes both idioms below often: # slurp into a scalar $content...</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>Get it?</p>

<p>(Meant to post this to perlmonks, but the site's submission form is missing the [Add] button right now).</p>

<p>Anyway, as a long time user of <a href="https://metacpan.org/module/File::Slurp">File::Slurp</a> who utilizes both idioms below often:</p>

<pre><code># slurp into a scalar
$content = slurp("file.txt");

<p># slurp into an array<br />
@lines = slurp("file.txt");</code></pre></p>

<p>I'm willing to switch to <a href="https://metacpan.org/module/IO::All">IO::All</a>'s:</p></p>

<pre><code># slurp into a scalar
io("file.txt") > $content;</code></pre>

<p>But there's no array counterpart:</p>

<pre><code># slurp into an array
io("file.txt") > @lines;</code></pre>

<p>I've hopelessly tried several variants:</p>

<pre><code>io("file.txt") > \@lines;
io("file.txt") >> @lines;
io("file.txt") >> \@lines;
@lines = @{ io("file.txt") };
@lines = &lt;io("file.txt")&gt;;
</code></pre>

<p>None of them works. Do I really have to settle with:</p>

<pre><code>@lines = io("file.txt")->slurp;</code></pre>

<p>But where's the coolness of using IO::All in this case?</p>

<p>I'm loving the other features of IO::All though, like append, tie, copy, path, dir, etc. Yes, it's totally mad.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Emacs (c)perl-mode for Python-oriented people?</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2013/04/emacs-cperl-mode-for-python-oriented-people.html" />
    <id>tag:blogs.perl.org,2013:/users/steven_haryanto//197.4501</id>

    <published>2013-04-06T01:45:44Z</published>
    <updated>2013-04-06T02:04:57Z</updated>

    <summary>In the middle of reading the surprisingly rather good blog post on a very old topic (hey, didn&apos;t know wordpress.com offers HTTPS URLs, nice), I wonder about whether people would think such a mode (or a minor mode for cperl-mode)...</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>In the middle of reading the surprisingly rather good <a href="https://coosoft.wordpress.com/2013/02/24/the-perl-vs-python-debate/">blog post on a very old topic</a> (hey, didn't know wordpress.com offers HTTPS URLs, nice), I wonder about whether people would think such a mode (or a minor mode for cperl-mode) would be interesting, or not too silly. (BTW why can't I stop doing parentheses?)</p>

<p>The mode's main task is to reduce visual "clutter" for people who has less tolerance for such.</p>

<ul>
<li>Change the appearance of sigiled variables <tt>$foo</tt> into <tt><i> foo</i></tt> (that is, a space followed by an italicized/emboldened/underlined/differently-visually-marked foo).
<li>Conceal or reduce the visibility of semicolons at the end of lines.
<li>Reduce the visibility of block-delimiter braces (some challenge here, remember that braces <a href="http://blogs.perl.org/users/shawnhcorey/2012/09/a-look-at-braces.html">has over 9 uses</a>).
</ul>
]]>
        
    </content>
</entry>

<entry>
    <title>A couple of ideas for improving commenting/reviewing CPAN modules</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2013/03/a-couple-of-ideas-for-improving-commentingreviewing-cpan-modules.html" />
    <id>tag:blogs.perl.org,2013:/users/steven_haryanto//197.4419</id>

    <published>2013-03-12T18:00:27Z</published>
    <updated>2013-03-12T18:11:25Z</updated>

    <summary>I love browsing and/or buying books on Amazon.com. Part of the reason is that there are no lack of ratings/reviews on the books, helping me decide on which books to choose on a certain topic. On CPAN however, despite cpanratings.perl.org...</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>I love browsing and/or buying books on Amazon.com. Part of the reason is that there are no lack of ratings/reviews on the books, helping me decide on which books to choose on a certain topic. On CPAN however, despite <a href="http://cpanratings.perl.org">cpanratings.perl.org</a> having been online for more than a decade, most modules have no reviews.</p>

<p>I've done my share of commenting/reviewing modules, but some things could be improved.</p>

<p>First, whenever some other modules are mentioned in a review, it should perhaps be shown as reviews/mentions for that module. For example, just minutes ago I added four reviews each for <a href="http://metacpan.org/module/Text::ASCIITable::TW">Text::ASCIITable::TW</a>, <a href="http://metacpan.org/module/Text::CharWidth">Text::CharWidth</a>, <a href="http://metacpan.org/module/Text::VisualWidth">Text::VisualWidth</a>, and <a href="http://metacpan.org/module/Text::VisualWidth::PP">Text::VisualWidth::PP</a>. Basically I just wanted to say that Text::CharWidth is my preferred way. I should've been able to enter just one review article, which mentions all 4 modules, which cpanratings could show for all those 4 modules.</p>

<p>Second, there should perhaps be an indexing service to index blog/web articles which mention Perl modules. <a href="http://neilb.org/reviews/">Neil's articles</a>, for example. All in all, those articles could translate to hundreds of module reviews/comments.</p>]]>
        
    </content>
</entry>

<entry>
    <title>CPAN as {ISBN authority, book publisher, bookstore, ...}</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2013/03/cpan-as-isbn-authority-book-publisher-bookstore.html" />
    <id>tag:blogs.perl.org,2013:/users/steven_haryanto//197.4417</id>

    <published>2013-03-12T17:09:15Z</published>
    <updated>2013-03-12T17:21:10Z</updated>

    <summary>Suppose we use books as analogies for Perl (CPAN) modules. Do we want CPAN to be some sort of an ISBN authority, where we merely dole out namespaces and unique IDs? There should be no requirements of content or any...</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>Suppose we use books as analogies for Perl (CPAN) modules.

<p>Do we want CPAN to be some sort of an ISBN authority, where we merely dole out namespaces and unique IDs? There should be no requirements of content or any editorial activity on the modules. We should not discourage (nor encourage?) experimental modules or implemetations, modules for personal or semi-private use, etc.

<p>Do we want CPAN to be some sort of a publisher? There would be some editors in charge to determine which modules are worthy of publishing and which are not (yet). The question is, who? There can hardly be a consensus and "CPAN publisher" will be forked into several publishers with differing guidelines/missions. Not that forking is a bad thing.

<p>Do we want CPAN to be some sort of a bookstore? Where we can browse for modules or do comparison shopping, see buyer's ratings, and finally check out and bring some modules home.

<p>Do we want CPAN to be some sort of a public library?

<p>Do we want CPAN to be some sort of a personal library? Where we display our favorite collections for others to see?

<p>Yes, yes, and yes. And that's what's hard.]]>
        
    </content>
</entry>

<entry>
    <title>It will be sensible to use Perl 6 to build real-world apps in ...</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2013/03/dont-wait-for-perl-6-to-build-your-product-on.html" />
    <id>tag:blogs.perl.org,2013:/users/steven_haryanto//197.4365</id>

    <published>2013-03-07T05:33:29Z</published>
    <updated>2013-03-12T18:27:04Z</updated>

    <summary>Let&apos;s try to predict when we will be able to {conveniently,realistically,sensibly} use Perl 6 to build real-world applications. Note: this post is just the result of its author&apos;s pondering and is not meant to be negative towards Perl 6....</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>Let's try to predict when we will be able to {conveniently,realistically,sensibly} use Perl 6 to build real-world applications. Note: this post is just the result of its author's pondering and is not meant to be negative towards Perl 6.<br />
</p>]]>
        <![CDATA[<p>The big challenge is to predict when a Perl 6 implementation will be production-ready. Ironically, although Perl stands for <b>Practical</b> Extraction and Report Language, the development of Perl 6 has become an ambitious and totally impractical project with no set deadline. Its goal is to be a programming language viable for the next 50 years. That's solving tomorrow's problems, problems which might not exist yet today.</p>

<p>The spec has been developed for over 12 years. It's rather stable now, but is still missing some big parts like concurrency, threads, nonblocking I/O, advanced macros. I guess many people is already content with the current spec, so let's say that the spec is more or less done.</p>

<p>Parrot is almost 12 years old but Rakudo on Parrot is hopelessly slow and is probably being abandoned. Unfortunately, Rakudo on JVM will not be a feasible platform for many applications, so even if Rakudo on JVM is production-ready, Rakudo will still need to be available on an alternative platform for cases where JVM is not appropriate.</p>

<p>Let's say we give it 6 years, which is rather optimistic. That means in 2019 we will see something like Rakudo Star 1.0 (the current Star releases don't count, I'm just reusing the name here).</p>

<p>Before 2019, we can already attempt to test Perl 6 for our applications. But realistically, one will not fully invest one's time and energy on a platform that is not labelled production-ready. So we can say that early adopters will only start writing Perl 6 for real in 2019-2020.</p>

<p>We must also realize that Perl 6 is a big language. Mastering and becoming fluent in it requires a significant amount of time. Perl 5 veterans will probably be able to be somewhat conversant in Perl 6 in a matter of weeks, but programmers coming from other languages will take months or a year, at least.</p>

<p>Some of the major/important libraries will also need to be fully mature first so we are confident that our applications will be quite stable. Things like DBI, LWP, Log4perl/Log::Any, Dist::Zilla, Mojolicious/Dancer, and several/dozens more, depending on your application. This process will take years and will involve at least one rewrite for many of the projects. I suspect the typical scenario will be: quickly port something cool from Perl 5, then after the code and API stabilize in about 1-2 years there will be a v2 project to make it more Perl6-ish, because the first version does not utilize hyperop/junction/multiple dispatch enough, or does not have cool DSL that utilizes Perl 6 grammar capability, or whatever. An application developer will have to endure this period with some amount of pain, and will have to perform some amount of rewrite himself/herself. Let's say all of this in 4 years.</p>

<p>Another process that will take years to develop is the best practices (the equivalent of PBP for Perl 6). Unless Damian is already underway in writing this.</p>

<p>Oh, and I bet Perl 6 grammars will encourage the flourishing of many DSLs for various tools/frameworks, like in Ruby with Chef, Puppet, Cucumber, etc, except even more so because grammar-based DSLs will be so much cooler. This is not bad in itself, but all of those DSLs will have to be learnt by developers. So I'll add an extra 2 years for this.</p>

<p>All in all, I think we can start writing Perl 6 for real-world apps in about 2027 at the earliest. I can start earlier, but the thought of having to endure several rewrites during the era of library rewrites and underdeveloped best practices and lack of tools, discourages me.</p>

<p>Unfortunately, by that time, my programming career will be almost over. So I'm sorry Perl 6, I'm afraid I can't afford you.</p>]]>
    </content>
</entry>

<entry>
    <title>Introducing Sah, another data validation framework</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2013/02/introducing-sah-another-data-validation-framework.html" />
    <id>tag:blogs.perl.org,2013:/users/steven_haryanto//197.4265</id>

    <published>2013-02-07T04:47:19Z</published>
    <updated>2013-02-13T00:48:48Z</updated>

    <summary>This blog post introduces Sah, my data validation framework (or data validation language and validator generator, to be more exact). The very first work on Sah began almost 4 years ago as Data::Schema. The name change to Sah and the...</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>This blog post introduces Sah, my data validation framework (or data validation language and validator generator, to be more exact). The very first work on Sah began almost 4 years ago as Data::Schema. The name change to Sah and the first release of Data::Sah happened in late 2011.</p>

<p>To validate data, first you write a Sah schema. Sah schemas are also data structures and are very much similar to JSON schemas, except that they are more featureful and (at least to to me) more convenient to write.</p>

<p>The design and implementation principle are mostly laziness and DRY:<br />
<ul><br />
<li>I want concise syntax for common things; I don't want to have to type a lot especially if they are mostly the same things;<br />
<li>I want to use it for everything, from validating function arguments to web requests; I don't want to have to use two different validation languages (e.g. one for function arguments, another for class attributes, another for JSON data);<br />
<li>I want to generate JavaScript client-side validation code from the schema; I dont' want to have to write JavaScript code manually;<br />
<li>If someday there needs to be server-side validation performed in languages other than Perl, I want to generate that code too instead of having to write them manually; <br />
<li>I want good default error message, most of the time I don't want to have to write error messages manually;<br />
<li>I want translation of error messages;<br />
</ul><br />
</p>]]>
        <![CDATA[<p>You can easily see the above pattern of "I don't want to have to do XXX". It's my favorite mantra nowadays.</p>

<p>Some examples of Sah schemas (in Perl notation):</p>

<pre><code>
["int", {min => 1}]   # an optional integer, greater than or equal to 1
["int", {min => 1, max => 10}]   # an optional integer between 1 and 10
["int", min => 1, max => 10]   # shortcut notation for the above
["int", req=>1, min => 1, max => 10]   # a required integer between 1 and 10
["int*", min => 1, max => 10]   # * after type name is shortcut notation for req=>1
["int*"]   # a required integer, with no extra clauses
"int*"   # shortcut notation for the above
["array*", of => ["int*" => between => [0,10]]]  # a slightly more complex example
</code></pre>

<p>Sah is available on CPAN in the form of two distributions (and certainly more in the future). <a href="http://metacpan.org/release/Sah">Sah</a> contains the specification for the language/schema. <a href="http://metacpan.org/release/Data-Sah">Data::Sah</a> is the compiler. There will be plugins/extensions in the future.</p>

<h2>Speed</h2>

<p>Instead of evaluating your schema against input data directly, Data::Sah compiles your schema into some Perl code. This Perl code is the one that will be used to validate data. Compiled validator has the advantage of being one or two orders of magnitude faster than interpreted one. <a href="https://gist.github.com/sharyanto/4728834">A casual benchmarking</a> done about three months ago demonstrates this.</p>

<p>Since I want to validate function arguments, speeds in the order of thousands/sec (like that of <a href="http://metacpan.org/module/Data::Domain">Data::Domain</a> or <a href="http://metacpan.org/module/Data::Verifier">Data::Verifier</a> or even <a href="http://metacpan.org/module/Data::FormValidator">Data::FormValidator</a>) are inadequate. Functions sometimes need to be called much more often than that. <a href="http://metacpan.org/module/Data::Sah">Data::Sah</a> is faster than all other validation modules that I tested, except <a href="http://metacpan.org/module/Params::Validate">Params::Validate</a> (PV). PV is very barebones though; even for some simple testing you need to supply a callback routine. <a href="https://gist.github.com/sharyanto/4728839">This degrades performance rather quickly</a>.</p>

<p>An example of Perl code generated by Data::Sah, for schema <code>[int => min => 1, max=>100, div_by => 3]</code>:</p>

<pre><code>$ perl -MData::Sah -E'$sah = Data::Sah->new; $c = $sah->get_compiler("perl"); $res = $c->expr_validator_sub(schema => [int => min=>1, max=>100, div_by=>3]); say $res'
do {
    require Scalar::Util;
    sub {
        my($data) = @_;
        my $_sahv_res = 
        
            # skip if undef
            (!defined($data) ? 1 : 
            
            (# check type 'int'
            (Scalar::Util::looks_like_number($data) =~ /^(?:1|2|9|10|4352)$/)
            
            &&
            
            (# clause: div_by
            ($data % 3 == 0))
            
            &&
            
            (# clause: min
            ($data >= 1))
            
            &&
            
            (# clause: max
            ($data <= 100))));
        
        return($_sahv_res);
    }}
</code></pre>

<h2>JavaScript output</h2>

<p>Compilation can also produce other targets, like JavaScript. A simple demo will be provided in subsequent blog posts, as I will be writing a form rendering/processing library soon.</p>

<p>The previous example, outputing JS instead of Perl:</p>

<pre><code>$ perl -MData::Sah -E'$sah = Data::Sah->new; $c = $sah->get_compiler("js"); $res = $c->expr_validator_sub(schema => [int => min=>1, max=>100, div_by=>3]); say $res'
function(data) {
    var tmp_data = [];
    var _sahv_res = 
    
        // skip if undef
        (!!(data === undefined || data === null) ? true : 
        
        (// check type 'int'
        (typeof(data)=='number' && Math.round(data)==data || parseInt(data)==data)
        
        &&
        
        (tmp_data[0] = typeof(data)=='number' ? data : parseFloat(data), true)
        
        &&
        
        (// clause: div_by
        (tmp_data[0] % 3 == 0))
        
        &&
        
        (// clause: min
        (tmp_data[0] >= 1))
        
        &&
        
        (// clause: max
        (tmp_data[0] <= 100))
        
        &&
        
        // clause: max
        ((tmp_data).pop(), true)));
    
    return(_sahv_res);
}
</code></pre>

<h2>(Translatable) error messages</h2>

<p>Producing error message (and human language specification) from the schema is another compilation process.</p>

<pre><code>
$ perl -MData::Sah -E'$sah = Data::Sah->new; $c = $sah->get_compiler("human"); $res = $c->compile(schema => [int => min=>1, max=>100, div_by=>3]); say $res->{result}'
integer, must be divisible by 3, must be at least 1, must be at most 100
</code></pre>

<p>The Perl/JS compiler utilitizes the human compiler to produce its error message.</p>

<pre><code>
$ perl -MData::Sah -E'$sah = Data::Sah->new; $v = $sah->gen_validator([int => min=>1, max=>100, div_by=>3], {return_type=>"str"}); say "$_ => ", $v->($_) for ("x", 2, -3, 3)'
x => Input is not of type integer
2 => Must be divisible by 3
-3 => Must be at least 1
3 => 
</code></pre>

<p>Setting the output language can be done easily using the environment LANG or lang argument.</p>

<pre><code>$ LANG=id_ID perl -MData::Sah -E'$sah = Data::Sah->new; $v = $sah->gen_validator([int => min=>1, max=>100, div_by=>3], {return_type=>"str"}); say "$_ => ", $v->($_) for ("x", 2, -3, 3)'
x => Masukan tidak bertipe bilangan bulat
2 => Harus dapat dibagi oleh 3
-3 => Harus minimal 1
3 => 
</code></pre>

<p>A custom error message can also be specified in the schema to override the default message.</p>

<h2>Summary</h2>

<p>The Data::Sah module is still early in development. There are lots of clauses not yet implemented and some functionalities are still missing: schema can contain expressions, functions, and other definitions. But I'm already using it in the <a href="http://metacpan.org/module/Perinci">Perinci</a> framework. I write schemas for function arguments once, in the function metadata, then the schemas can be used to validate function arguments as well as generate usage information.</p>]]>
    </content>
</entry>

<entry>
    <title>Graphing CPAN author&apos;s number of distributions over time</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2012/12/graphing-cpan-authors-number-of-distributions-over-time.html" />
    <id>tag:blogs.perl.org,2012:/users/steven_haryanto//197.4160</id>

    <published>2012-12-28T17:52:41Z</published>
    <updated>2012-12-28T18:09:31Z</updated>

    <summary>Script: graph-cpan-dists-over-time One glaring deficiency: does not take PAUSE deletions into account (is there a MetaCPAN API for this?) Thus, the number of actual dists on the graph is monotonically increasing and might be higher than the number of actual...</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>Script: <a href="https://github.com/sharyanto/scripts/blob/master/graph-cpan-dists-over-time">graph-cpan-dists-over-time</a></p>

<p>One glaring deficiency: does not take PAUSE deletions into account (is there a MetaCPAN API for this?) Thus, the number of actual dists on the graph is monotonically increasing and might be higher than the number of actual dists on CPAN.</p>

<p>Generated graph is still rough and number of authors is limited at three because I'm too lazy to tweak the sample script from Chart::Lines.</p>

<p>Sample graph:<br />
<img src="/users/steven_haryanto/gcdot-oICwJj.png" />.</p>

<p>Enjoy and feel free to improve on it.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Personal end-of-year report for 2012</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2012/12/personal-end-of-year-report-for-2012.html" />
    <id>tag:blogs.perl.org,2012:/users/steven_haryanto//197.4154</id>

    <published>2012-12-26T02:20:49Z</published>
    <updated>2012-12-26T03:54:10Z</updated>

    <summary>Previous end-of-year report for 2011. Previous quarterly report: Apr-Jul 2012. 2012 is my most productive year yet in my &quot;CPAN career&quot;: 943 releases (compared to 495 in 2011). That&apos;s about 2.5 releases per day! So far I have about 215...</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>Previous end-of-year report for <a href="http://blogs.perl.org/users/steven_haryanto/2011/12/personal-end-of-year-report-for-2011.html">2011</a>. Previous quarterly report: <a href="http://blogs.perl.org/users/steven_haryanto/2012/08/hacktivity-report-apr-jul-2012.html">Apr-Jul 2012</a>.</p>

<p>2012 is my most productive year yet in my "CPAN career": 943 releases (compared to 495 in 2011). That's about 2.5 releases per day! So far I have about 215 distributions under my account, almost half of them (96) are new modules in 2012. The reasons the number of distributions is high include: Perinci modules family being split into many distributions (and then some, to avoid recursive dependencies problems that I seem to keep bumping into), the various Task distributions, and also the fact that releasing CPAN modules is so darn fun! A little too much fun, I'm afraid.<br />
</p>]]>
        <![CDATA[<p><br />
My data validation library, <a href="http://metacpan.org/module/Data::Sah">Data::Sah</a>, is already usable (though currently broken in the last several weeks). I am already using it to validate function arguments and get it involved in the module releasing process. The performance is very satisfactory. Being compiled into direct Perl, it surpasses every existing validation framework on CPAN that I know, from the slow ones like Validation::Class and Data::Domain, to the so-so-performing ones like Data::FormValidator, and lightweight/do-little ones like FormValidator::Lite, to Params::Validate. I expect to formally introduce it in the next month or two.</p>

<p>Haven't begun writing any significant code for my form handling library, ReForm, but expect to get at it after Data::Sah gets enough features.</p>

<p>Summary of the work I did between Jul-Dec 2012:</p>

<ul>
<li>Finally get Data::Sah to the point of usable.

<p><li><a href="http://metacpan.org/module/Rinci">Rinci</a>: rewrite transaction specification. Now everything is a bit clearer and saner. No more 'steps' nonsense or a framework just to write a simple transactional function. Implement a few modules using this: File::{Truncate,Trash,Append,Prepend,Patch}::Undoable, Setup::File::TextFragment.</p>

<p><li><a href="http://metacpan.org/module/Riap">Riap</a>: introduce schemes riap+unix and riap+pipe. Enable easy creation of API service over piped program, SSH.</p>

<p><li>Write new specifications: <a href="http://metacpan.org/module/DefHash">DefHash</a>, <a href="http://metacpan.org/module/IOD">IOD</a> (INI file format, split from Config::Ini::OnDrugs)</p>

<p><li>Make <a href="http://metacpan.org/module/Text::sprintfn">Text::sprintfn</a> twice faster, though I would really like to make it 10x faster.</p>

<p><li>Add command-line program and more options to <a href="http://metacpan.org/module/Bench">Bench</a> to make it more usable and convenient.</p>

<p><li>New modules: a couple of release tools <a href="http://metacpan.org/module/App::LintPrereqs">App::LintPrereqs</a> and <a href="http://metacpan.org/module/App::HasPrereqs">App::HasPrereqs</a>, <a href="http://metacpan.org/module/Data::Clean::JSON">Data::Clean::JSON</a> to replace slower code that uses <a href="http://metacpan.org/module/Data::Rmap">Data::Rmap</a>, <a href="http://metacpan.org/module/Unix::Passwd::File">Unix::Passwd::File</a> to replace Passwd::Unix::Alt, <a href="http://metacpan.org/module/Monkey::Patch::Action">Monkey::Patch::Action</a>, <a href="http://metacpan.org/module/Perl::Stripper">Perl::Stripper</a>, <a href="http://metacpan.org/module/Progress::Any">Progress::Any</a> (<a href="http://blogs.perl.org/users/steven_haryanto/2012/10/progressany.html">blog post</a>), <a href="http://metacpan.org/module/YAML::Tiny::Color">YAML::Tiny::Color</a>, <a href="http://metacpan.org/module/JSON::Color">JSON::Color</a>, <a href="http://metacpan.org/module/File::Write::Rotate">File::Write::Rotate</a>.</p>

<p><li>Proofs of concept: Software::Catalog.</p>

<p><li><a href="http://metacpan.org/module/HTTP::Headers::Patch::DontUseStorable">Several</a> <a href="http://metacpan.org/module/Log::Any::Adapter::Core::Patch::UseDataDump">patch</a> <a href="http://metacpan.org/module/Log::Any::Adapter::Core::Patch::SetDumperIndent">modules</a> (<a href="http://metacpan.org/module/Time::Duration::Patch::Millisecond">and</a> some more).</p>

</ul>

<p>Some reflections:</p>

<ul>

<p><li><b>The whole Rinci transaction thing</b>. I started this work because I hoped to use it in a transactional software installer and configuration management tool. And also at first because I wanted to write some command-line tools for <a href="http://www.ledger-cli.org/">ledger</a> to add transactions from the command-line. That ledger tool is not yet written until today, and I've also come to the decision that I don't want to include transactional capability to the configuration management tool. Yet I spent at least two months defining and refining the transaction protocol. All is not wasted, though, writing the specification is a nice exercise, nevertheless.</p>

<p><li><b>Releasing patches to modules as patch-modules instead of (or in addition to) submitting them to the original modules</b>. I like this approach because submitting patches to CPAN modules in my experience is a lot slower and far less deterministic process. I get less than 50% response rate from the original authors and even then the responses often come in an untimely manner (say after over 1 month). Releasing the patches as patch modules is an express publishing mechanism that allows me (and others) to use my work immediately in applications.</p>

<p>I hope to continue doing this, and even hope others might pick up the habit.</p>

</ul>

<p>To be honest, I really don't expect to release as many CPAN modules/distributions in 2013, but who knows?</p>

<p>Here's to a happy new year and a productive 2013 all year long.</p>]]>
    </content>
</entry>

<entry>
    <title>Oh Carp!</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2012/12/oh-carp.html" />
    <id>tag:blogs.perl.org,2012:/users/steven_haryanto//197.4128</id>

    <published>2012-12-14T09:15:18Z</published>
    <updated>2012-12-14T09:48:01Z</updated>

    <summary>Recently got hit with this error: Goto undefined subroutine &amp;Carp::shortmess_real at /usr/share/perl/5.10/Carp.pm line 41. What&apos;s going on?...</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>Recently got hit with this error:</p>

<pre>Goto undefined subroutine &Carp::shortmess_real at /usr/share/perl/5.10/Carp.pm line 41.</pre>

<p>What's going on?</p>]]>
        <![CDATA[<p>Older versions of Carp (like the one included with Debian Squeeze, 1.11) puts the actual implementation in Carp::Heavy. Carp::Heavy is loaded on demand when one of Carp's routines like carp() or cluck() is called.</p>

<p>Newer versions of Carp (at least since 1.22, when it first appears independently on CPAN) no longer does this. For some reason the author decides to move everything into Carp, making Carp::Heavy empty.</p>

<p>The problem arises when an older version of Carp tries to call a newer version of Carp::Heavy, hoping to find an implementation that is no longer there. And this can quite easily happen because Carp::Heavy's loading is delayed (which I reckon is the original intent, to reduce startup overhead as much as possible).</p>

<p>Our application ships its own CPAN modules and has this piece of code on its scripts:</p>

<pre><code>use FindBin;
use lib "$FindBin::Bin/../lib"; # use our version of CPAN modules
</code></pre>

<p>FindBin uses Carp, and at this point, system-wide modules are used. However, after the "use lib" statement, application-shipped path is searched first. When something carp()'s or cluck()'s, the new version of Carp::Heavy from our application's lib/ is loaded. Boom!</p>

<p>Moral of the story: delayed loading has its cons.</p>

<p>Possible stop-gap solution: add "use Carp::Heavy" before "use lib" line, to force loading old version of Carp::Heavy.</p>

<p>Possible long term solutions:</p>

<p>1) Our application ships older version of Carp.</p>

<p>2) Carp::Heavy should detect older version of Carp and do something about it (preferably making everything seamlessly working).</p>

<p>3) Carp::Heavy should just be deleted from the new distribution. What's the point of having it around if it's empty anyway? It hurts older Carp and provides no gain to newer Carp.</p>

<p>I'm torn between #2 and #3, but lean slightly towards #2. By doing #3, some users who preload Carp::Heavy explicitly will be hit. Even though users should not preload Carp::Heavy explicitly in the first place, the whole mess has been created, and backward-compatibility should be maintained.</p>]]>
    </content>
</entry>

<entry>
    <title>CGI is dead, long live CGI</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/steven_haryanto/2012/12/cgi-is-dead-long-live-cgi.html" />
    <id>tag:blogs.perl.org,2012:/users/steven_haryanto//197.4108</id>

    <published>2012-12-07T03:53:40Z</published>
    <updated>2012-12-07T04:17:49Z</updated>

    <summary>Yesterday&apos;s (not so pleasant) experience of trying to deploy Pastedance *) on an internal web server at work makes me appreciate the simplicity of CGI. CGI might be out of favor for production sites, but for personal and internal applications,...</summary>
    <author>
        <name>Steven Haryanto</name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/steven_haryanto/">
        <![CDATA[<p>Yesterday's (not so pleasant) experience of trying to deploy <a href="https://github.com/datamuc/Pastedance">Pastedance</a> *) on an internal web server at work makes me appreciate the simplicity of CGI. CGI might be out of favor for production sites, but for personal and internal applications, it's still the best choice for me. </p>

<ul>

<p><li><b>There's no daemon.</b> No slowly-but-ever-growing process that eventually gets killed or thrashes the server (thus, no need to configure ulimit/rlimit, or write another script to monitor this, or add a condition in code to exit periodically). No need to worry about memory leaks. No need to manage and monitor daemon process. No need to put startup script in cron, /etc/init.d/ or whatever. You can be as dirty or one-off as you want. (Of course, you don't always want to be dirty, but the fact that you can is great.)</p>

<p><li>Works with any webserver. Works with any standard Linux server, like a plain Debian with Apache.</p>

<p><li>Can be isolated easily. Run as each user. Run as nobody. Run as per-user nobody.</p>

<p><li>Can be upgraded to FastCGI usually with very minor modifications (with caveat).</p>

<p><li>You can run hundreds of applications/sites simultaneously on a single server. It's the shared hosting owner's dream.</p>

<p><li>Did I mention <b>there's no daemon?</b> I can't tell you how much I, and fellow sysadmins, love it.</p>

</ul>

<p>Unfortunately, <a href="http://metacpan.org/module/Dancer">Dancer</a> is too slow if deployed as CGI. Each request takes one to a few seconds and this becomes unbearably slow since every image and CSS file is routed through it.</p>

<p>I am under the impression that <a href="http://metacpan.org/module/CGI::Application">CGI::Application</a> is the only "current" web framework usable under CGI. But I understand that it's very minimal, perhaps even to my taste. If I were to write yet another web framework, one of my design goals would be to make it usable under CGI. But I really, *really* do not want to do that.</p>

<p>*) On another note, does anyone know of a pastebin webapp that you can install in 1-5 minute on a plain Debian server with Apache? Not necessarily need to be in Perl. Preferably runs under CGI and uses MySQL/PostgreSQL/plain text files.</p>]]>
        
    </content>
</entry>

</feed>
