Rabu, 28 April 2010

Module Wishlist: magical loading of module

This Module Wishlist series is meant to surprise me with the power of CPAN. I wish about or dream up some module without first checking on CPAN, and hopefully can be delighted when what I want is already there.

Don't you hate it when you have to do:

$ perl -MSome::Really::Long::Module -e'print Some::Really::Long::Module->foo'

The goal is to be able to say something very close to:

$ perl -e'print Some::Really::Long::Module->foo'

and my module is loaded automaticaly.

To die or to croak, that is the question

Lately I've been tempted to use croak() instead of die(). Somehow it seems more considerate to users. But finally in the end I'm sticking with die(). In fact, I think the Carp module should be, well, croaked.

The reasons:

1. Even though Carp has been included in Perl 5 since forever (Module::CoreList tells me: "5"), carp(), croak(), cluck(), and confess() are still not builtins, which means I still need an extra "use Carp".

2. Too many keywords! Most other languages only have "throw" or "raise".

3. Names are too weird! I understand the difficulty of coming up with a concise set of names that are similar but slightly different. But requiring these weird names might also indicate that there is something fishy about the concept itself.

4. The choice of showing a stack trace or not should not be in the individual functions. That burdens the programmer with too much thinking.

5. Even with Carp qw(verbose), what's to be done with codes that still die() and warn()? (But luckily there's Carp::Always.)

6. Showing stack trace should not be this difficult. I still think there should be a command-line switch for Carp::Always (or alias it to 'oan' :-)

7. Programmers (module writers) make mistake. They should not skip a call frame.

In short, I think Carp makes things a little bit too complicated. But what's Perl without complication? :-)

You know you're a Perl programmer when...

You know you're a Perl programmer (or a CPAN author) when...

When you're thinking of packaging every piece of code as a CPAN module.

A couple of days ago I need a subroutine that takes a nested data structure (e.g. {vol1 => {a=>{b=>{c=>10}}}, vol2 => {a2=>{b2=>{c2=>20}}}}), a Unix-like path string (e.g. "vol1:/a/b/c") and return the branch/leaf node of the data structure according to the specified path (in this example, 10).

After browsing CPAN and a few minutes of reading the POD of some modules and not finding exactly what I wanted [*], that subroutine idea quickly transformed into an idea of a full-fledged CPAN module. The next day I uploaded Data::Filesystem to CPAN, which is actually yet another Data::Walker- / Data::Path- / Data::DPath-like module.

Turns out that I really don't need that module (yet, maybe someday). What I needed is just a simple Perl subroutine, and nothing more, because I will need to create a Javascript and PHP equivalent for it. Porting a whole module is not something I even want to do.

I wonder just how many CPAN authors that (do not) start their modules this way: overengineering of a small problem after not finding exactly what they want in CPAN.

[*] Btw, not finding what you want in one of the millions of CPAN modules has got to be one of the saddest thing in the universe. :-)

Minggu, 18 April 2010

Yada Yada, Buat apa ?

Perl 5.12.0 baru saja keluar dan salah satu yang baru yaitu Yada Yada Operator.

Saya hanya bingung kapan atau situasi seperti apa yang membuat yada yada operator bisa (dan bagus) untuk digunakan ?,
Selintas saya teringat seperti pending nya RSpec.

Kamis, 15 April 2010

Tip sprintf()

Salah satu fitur sprintf() (dan printf()) yang agak jarang diketahui/dipakai orang adalah bahwa sprintf() mendukung spesifikasi posisi argumen di dalam string formatnya, menggunakan prefiks NOMOR + "$":

% perl -E'say sprintf(q[%d %d %d], 1, 2, 3)'
1 2 3

% perl -E'say sprintf(q[%2$d %3$d %1$d], 1, 2, 3)'
2 3 1

Sayangnya, sprintf() tidak mendukung binding berdasarkan nama, seperti di Python:

print 'This {food} is {adjective}.'.format(adjective='absolutely horrible', food='spam')
This spam is absolutely horrible.

Kadang-kadang binding berdasarkan nama lebih nyaman, karena jika terjadi penambahan/pengurangan argumen, kita tidak harus menggeser-geser posisi lagi. Beberapa aplikasi tertentu seperti translasi juga kadang bisa dibuat lebih enak interfacenya seandainya menggunakan binding berbasis nama.

Jadi, bagaimana solusinya di Perl? Bisa dengan modul seperti String::Formatter, atau membuat sendiri :-) (seperti yang saya lakukan baru-baru ini di Data::Schema):

# $extra = {mverb => "harus"}; # mverb juga bisa 'sebaiknya'
# $args = [1, 10];
print stringf("Data %(mverb)s di antara %(0)d sampai %(1)d", $args, $extra);
Data harus lebih kecil di antara 1 sampai 10.

Fungsi stringf() mencoba mencari nilai binding di argumen kedua dst. Argumen dapat berupa hashref maupun arrayref, jadi saya bisa menggunakan binding berdasarkan posisi maupun nama. Nyaman :-)

Rabu, 14 April 2010

Data::Dumper (Unfortunately, Part 2)

One of the first things a Perl programmer will notice when learning about Data::Dumper is: how weird and "inside out" the OO interface is. This is, I think, another unfortunate accident in the Perl history, as Data::Dumper, being the first of such modules, gets into the core in early Perl 5 and remains popular up until this day. But the interface and default settings apparently annoy a lot of people so much that alternatives and wrappers like Data::Dump, Data::Dumper::Again, Data::Dumper::Concise, among others, sprung up to life.

A loose analogy would be CVS which was popular for (too long) a time, and following it the explosion of alternative version control systems. Eventually after this phase a winner will emerge or dominate. In the version control system case it appears to be git. And in the Perl case I think it will be a builtin perl() method/function, like in Perl 6. Probably in 5.14? 5.16? 5.18? Don't you think it's about time Perl can "natively" dump its own structures in Perl, just like Python, Ruby, PHP, etc have been able to for a long time?

(Btw, lest anyone thinks otherwise: I do love DD. It has lots of options and has served its purpose well over the years.)

List::Util, List::MoreUtils, Util::Any (Unfortunately, Part 1)

The dichotomy of List::Util and List::MoreUtils is one of the unfortunate annoyances in Perl. One is without s, one is with s. Which function belongs to which? And no, you can't simply say, "f*ck it, just import everything!" as List::Util doesn't provide the usual ":all" import tag (RT).

Some thoughts (from someone who is largely ignorant on the history of both modules), all IMO:

1. Since List::Util is basically a convenient library, convenience should've been its main design goal. It should've been inclusive enough. The decision to deny the inclusion of any(), all(), none() just because they are too "trivial" to implement in one line of Perl was a bit strange, since max(), min(), etc are also trivial to implement in Perl.

2. List::MoreUtils should've included all the functionalities of List::Util, so one can use it *instead of* List::Util.

But hey, what happened happened.

Btw, we also have Perl 6's junction taking the "all", "any", "none" keyword.

And we'll see whether solutions like Util::Any will catch on, as it's another syntax to learn, another module to download and install. As with many annoyances, they are actually not that big of a deal. One can just spend a few seconds looking up the documentation to find the functions he/she wants, and after about tens of uses should remember which ones are in which.

Just when I'm warming to 5.10, comes 5.12!

Perl is far from dead/dying nowadays, with 5.12 being released recently, and the yearly timed-based release plan and all. In fact, just after I start to be comfortable using some of the 5.10 niceties, here comes a whole new version with even more niceties waiting to be explored!

Features in 5.10 I'm using regularly.

Defined-or (if there's only one feature I can have in 5.10, I pick this one).

State variables (love it!).

Features in 5.10 I'm starting to use.

-E switch (but my reflex still says -e all the time).

Recursive pattern in regex (e.g., via Regexp::Grammars).

say() (maybe if I say it often enough I'll start to say say more).

Features in 5.10 I rarely/ever touch.

Smart match (I know it's a godsend, but strangely I never feel the need for it so far).

given/when (I'm sticking with if/elsif/else, especially since given/when cannot be used as an expression yet).

Named capture in regex (yeah, old habits die hard).

5.10 and 5.12. IMO, 5.10 contains more "significant" visible new features for end users (i.e. Perl programmers), especially in the area of new syntax addition. It's 5 years in the making and delivers many features borrowed from Perl 6. But that is not meant to belittle 5.12 which also packs some major goodies, especially pluggable keywords. This one promises to usher us into a world of new syntaxes and mini languages, though it also confirms Perl as being a language that is "impossible to parse" and it surely will pose a challenge/headache for PPI and syntax highlight/Intellisense writers. I look forward to something like a better embedded SQL and templates (using pluggable keywords instead of treating everything as strings all the time).

Rabu, 07 April 2010

Data::Dump::PHP

I actually don't believe there isn't something like this in CPAN yet. Well, actually there is PHP::Var, but it has bugs, doesn't handle scalars, and doesn't do recursive structure. But then I am equally surprised to be able to hack Data::Dump::PHP in just a couple of hours, by blatanly copying from Gisle Aas' Data::Dump and just modifying only what's necessary.

And another note, PHP's var_export() currently can't dump recursive structures, which Data::Dump::PHP can.

Kamis, 01 April 2010

Bahasa yang buruk vs programer yang buruk

Apakah kita seharusnya menangisi kenyataan bahwa Perl tidak lagi menjadi bahasa primadona untuk Web? Rasanya sulit bisa mengejar popularitas PHP, atau Ruby dan Python saat ini di domain pemrograman Web. Dulu pertengahan 1990-an Perl dipilih karena belum banyak bahasa lain yang tersedia default di server-server Unix. Alternatifnya saat itu hanyalah C, shell, atau Tcl. Kini persaingan amat ketat/banyak. Perl termasuk salah satu yang lebih sulit/lama dipelajari dan selain itu memiliki imej "tua" (padahal umurnya gak beda jauh dengan rekan2nya, hanya sekitar 1-2 tahun dengan Python dan hanya 5 tahunan lebih dengan Ruby; semua bahasa2x ini sudah hampir atau lebih tua dari 20 tahun).

Di satu sisi kehilangan pamor/momentum/posisi jawara/apalah tentu gak mengenakkan. Tapi di sisi lain, ada manfaatnya. Para "programer" web yang cenderung lebih banyak menghasilkan kode-kode yang buruk jadi meninggalkan Perl. Saya ingat dulu saat Perl popular, betapa komunitas Perl dianggap elitist, eksklusivist, sombong, angkuh, tidak ramah terhadap pemula. Dan bahasa-bahasa lain mulai mendapat tempat di hati khalayak ramai karena menawarkan komunitas yang lebih ramah pemula. (Belakangan, komunitas Perl pun mulai melunak dan menginisiasi effort2x untuk lebih merangkul pemula, seperti membuat milis beginners@, dsb. Tapi mungkin sudah terlambat).

Salah satu alasan mengapa komunitas Perl "benci" pemula adalah: karena begitu banyak niubi yang jadi programer karbitan/jadi2xan berbondong2x mempelajari Perl, kadang setengah2x (atau seperempat2x!), dan selalu mencampurkan konsep Perl dan CGI. Selalu menulis Perl dengan PERL. Selalu mendecode parameter CGI sendiri (karena mengikuti instruksi buku2x Perl tak bermutu), padahal di Perl 4 pun sudah ada cgi-lib.pl. Selalu menanyakan persoalan sepele yang sudah sejak lama ada di FAQ. Selalu mengkopi paste kode dan menulis skrip yang begitu hancur2xan jeleknya.

Sekarang rupanya mayoritas dari mereka sudah berpindah ke PHP. Sebagai pengurus server hosting Linux, sudah sering saya harus mengecek aplikasi PHP milik klien hosting yang bermasalah. Dan tiap kali saya mengintip kode sumbernya, kadang saya tersenyum pahit, kadang mengelus dada, kadang geleng2x kepala. Program2x jelek dan berantakan ternyata tidak pernah punah. Dulu di Perl, sekarang di PHP. Kalau dulu Matt's Script Archive jadi biang hole, kini ada phpBB, WordPress, Joomla sebagai penerusnya.

Apakah Rails atau Django akan kebal dari para programer buruk? Don't underestimate the power of stupid people :)

Maaf, saya tidak bermaksud berarogan ria di sini. Ada berbagai macam alasan mengapa seseorang bisa disebut programer buruk, seringkali itu bukan karena dia bodoh. Deadline yang terlalu singkat menyebabkan harus kopi paste kode. Pengetahuan yang minim karena pengalaman kurang menyebabkan desain yang naif. Peran bahasa untuk melakukan "nudging" dan manajemen insentif untuk memperbaiki kebiasaan-kebiasaan yang salah memang berpengaruh, tapi selalu ada ruang untuk beginner's mistakes. Dan selalu harus ada refactoring. Programer yang buruk tidak pernah melakukan refactoring.

Jadi, bersyukurlah karena nanti 10 tahun lagi para generasi programer baru tidak lagi banyak mengutuk Perl karena harus memaintain kode lama CGI yang sudah membusuk. Melainkan mengutuk PHP karena diwarisi segunung kode spageti busuk bercampur HTML. Atau mengutuk Ruby karena peninggalan kode-kode busuk Rails dengan desain objek yang terbalik-balik dan pattern-pattern salah kaprah.

Programer yang buruk selalu ada sepanjang masa. Bahasa yang saat itu banyak dipakai yang akan jadi kambing hitamnya. :-)