Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Journal of markjugg (792)

Thursday December 27, 2007
08:40 AM

grokking Haskell

I spent some time today learning some Haskell.

Here's an example of how I defined a function to perform addition in Haskell, and a second function that builds on the first to increment a number by one:


  add x y = x + y
  inc = add 1

The Haskell syntax here is especially compact and readable. In Perl, the same exercise would be much longer and noisier, as commonly written:


    sub add {
            my ($x,$y) = @_;
            return $x + $y;
    }

    sub inc {
            my $y = shift;
            return add(1,$y);
    }

(Yes, Perl could more even more terse, at the expense of readability)

Haskell provides further invisible benefits. If you give 'inc' too many arguments, or try to increment a character instead of a number, Haskell
helpfully dies with an error to tell you that you are attempting something that
doesn't make sense.

Perl will less helpfully ignore too many arguments, or pretend it can usefully
increment the character 'b'. In both cases, Perl "successfully" returns answers
of little use.

Keep in mind in that Pugs, an implementation of Perl 6, was written in Haskell, so I dare say Perl 6 shows some influence from Haskell.

Perhaps someone fluent in Perl 6 could leave a comment illustrating how Perl 6 could more elegantly these two simple functions. (Without using the built-in increment operator, of course! )

Thursday November 15, 2007
11:36 PM

mod_perlite: worth a look

mod_perlite hopes to offer some of the performance benefits of mod_perl with the ease-of-use of PHP's model. Check it out.
Saturday August 11, 2007
10:14 AM

Increasing the visibility of journals in search engines

use.perl.org journals currently have very unfortunate <title> tags. Every journal entry I create has an <title> like

"journal of markjugg (123)".

It should really be something like:

"Witty Journal Title | markjugg's use.perl blog"

The current state of things reduces search engine rankings by not having the key words from the title in the tag, and produces pitiful entries in search engine results when you do find them, as seen here:

Even though the results are for specific journal entries, you just see:

Journal of sam (123)
Journal of mark (456)
Journal of foo (765)

Ugh. I've submitted a bug to Slashcode, if anyone is able to fix this.

10:03 AM

HTML::FillInForm patched for do-what-i-man syntax.

I've now submitted a patch to T.J. Mather for HTML::FillInForm which overhauls the interface and docs to be simpler.

It boils down to two things:

1. You can skip the call to new().

2. You no longer have to declare what format your HTML or data is in, the module just figures it out. Gone are the days of trying to remember whether you needed "fdat" or "fdata", "fobj" or "fobject", "scalaref" or "scalarref"... you don't need any of them!

        In summary, this:

        my $fif = HTML::FillInForm->new;
        $fif->fill( scalarref => \$html, fdat => \%data );

        Has become:

        HTML::FillInForm->fill( \$html, \%data );

All the original syntax remains supported for backwards compatibility.

I'll try post another update once the final release happens.
i

Saturday August 04, 2007
09:24 AM

Welcome, Data::FormValidator::Constraints::MethodFactory

A new module has been released for Data::FormValidator, Data::FormValidator::Constraints::MethodsFactory

For a quick overview, when I inherited maintenance of Data::FormValidator, it came with a ConstraintsFactory module. It has always seemed unwieldy, and I have hardly ever used and it mostly ignored it, despite being the current official maintainer of it.

For example, to express that you would like one constraint or another to be used, you would use:

make_or_constraint( $c1, $c2)

Where $c1 and $c2 are constraints.

Graham TerMarsch upgraded this whole system in two important ways with his module release. First, all of these factory methods are now "constraint methods", meaning that the constraint now has access to the Data::FormValidator object, allowing much greater flexibility.

Second, he fixed the unwieldy names that bothered me so much. So the above example would be expressed more directly as:

FV_or( $c1, $c2)

If you mean "or", you should just able to say "or"!. It's sort of a wart that it includes the "FV_" prefix, but that's consistent with other parts of DFV, so I think that's for the best.

Enjoy this new form validation tool!

        Mark

Sunday July 22, 2007
09:14 PM

auto-restart HTTP::Server::Simple when modules change

This weekend I worked on making a feature I liked in Catalyst available to other Perl projects. That feature is the ability to have a simple Pure-Perl web server for development, and have it automatically restart itself when application files changes.

By looking at the guts of Catalyst, I found not one, but two modules that could be easily refactored out of Catalyst for shared use. Those are now File::Monitor::Simple, to monitor the application directory for changes, and HTTP::Server::Restarter to handle controlling that process and actually restarting the web server.

I also needed to patch HTTP::Server::Simple to have better signaling handling. But the result is that this now works:

    HTTP::Server::Restarter->monitor;
    HTTP::Server::Simple->new->run;

While there are options you can give to monitor(), the defaults should work fine for Catalyst and possibly others as well.

I'm currently in discussions with catalyst-dev to see about the best way to get this code published and the possibility of Catalyst being refactored to use the extracted modules as well.

The way that Catalyst currently handles this is a bit novel. Instead of sending and receiving a HUP signal, Catalyst sends a (non-standard) RESTART HTTP request from a user-agent to the server, with some some protection that this command comes from the localhost.

Saturday July 21, 2007
03:13 PM

offline website development with Catalyst and CGI::App

Catalyst brought into my field of the view an easy way to do Perl website development offline. Catalyst generates ./script/myapp_server.pl as part of the project setup. Run the script, connect to http://localhost:3000 in the browser, and there I go.

CGI::Application now has related tools as well, which builds on the work done by the Catalyst team. See CGI::Application::Dispatch::Server and Test::WWW::Mechanize::CGIApp, which both provide enough of a real web server to let you work on your CGI::Application project.

Jesse was just blogging offline web applications. For applications where it's feasible to share the web-code with the client, Perl's solution with Catalyst and CGI::Application has largely solved the problem, leaving only the database sync'ing issue to remain. Some kinds of database sync'ing are simply not practical-- Think of incrementing the a sequence value in both locations and trying to reconcile!-- but for other applications like PDAs, and groupware clients, we know from example there are feasible solutions.

I foresee more web developers using these techniques to deploy desktop applications that are really locally run websites with built-in webservers. It's not too difficult to envision a browser toolkit that provides an interface that looks more like a standalone application than a web browser.

I'm glad Catalyst has helped these tools evolved, but just as I was playing with these offline web servers, as I was reminded why I prefer CGI::Application: The default Catalyst application benchmarked with a virtual memory footprint of 17.4 megs, while an empty application with CGI::Application::Dispatch::Server application benchmarked at 8.8 megs-- almost half the memory usage! Now, that's not a "real world" comparison, but it does illustrate the different philosophies: CGI::Application is the center of more an à la carte framework, while Catalyst has more functionality built-in.

Sunday July 15, 2007
09:04 PM

New HTML::ReplaceForm helps with quick web-to-email forms

I uploaded HTML::ReplaceForm today.

Here's the use case for it:

The task is to whip up a web-to-email form with sub-degree of complexity. I'm a fan of making the resulting email look as much like the original form to avoid confusion. But, maintaining two similar versions of the same HTML form for the web and the email variations is a drag.

Enter HTML::ReplaceForm. It provides one function, replace_form() which replaces all the HTML form elements with corresponding values.

So, you can serve the HTML directly on the web, and run it through this function to generate the corresponding HTML e-mail, without "forking" the form to maintain another copy of it.

Time saved.

      Mark

Friday July 06, 2007
11:32 PM

SQL::Interp 1.00 released as a SQL::Abstract alternative

Perl hashes are natural representation of name/value pairs, and there should be an easy way to translate them in the name/value pairs SQL expects in INSERT and UPDATE statements, as well as WHERE clauses.

Also, for best security practices, bind variable should be used. This further complicates the problem space, because names and values need to be split up in the resulting SQL.

SQL::Abstract is a popular solution for addressing these problems, and I one I used myself for some time. To its credit, it has a fairly intuitive API, and focuses just on SQL generation, not getting involved the actual query execution.

However, as SQL::Abstract grew over time, it tried to handle more and more complex cases of SQL, and the design failed to scale up well. Here's an example bit of SQL, straight from the SQL::Abstract docs.

The goal is to generate SQL that looks like this:

    WHERE ( user = ? AND
                 ( ( workhrs > ? AND geo = ? )
                OR ( workhrs < ? AND geo = ? ) ) )
   

The SQL abstract solution looks like this:

  my @where = (
             -and => [
                user => &#8217;nwiger&#8217;,
                -nest => [
                    -and => [workhrs => {&#8217;>&#8217;, 20}, geo => &#8217;ASIA&#8217; ],
                    -and => [workhrs => {&#8217;<&#8217;, 50}, geo => &#8217;EURO&#8217; ]
                ],
            ],
  );
 

Now, to generate that structure, you would have to know exactly the SQL structure you wanted, plus you would have to know the special syntax that goes with "-and", "-nest" and the especially cumbersome syntax that translated " > 20 " into " => {'>', 20}, ". The resulting Perl is actually more cumbersome and ugly to write than the original SQL!

With SQL::Interp, there is nothing special to learn to handle this case. You just write out the SQL like you want, and drop in the Perl variables you need as references:

    "WHERE ( user = ",\$user,"  AND
    ( ( workhrs > ",\$asia_hrs," AND geo = ",\$asia," )
                OR ( workhrs < ",\$euro_hrs," AND geo = ",\$euro," ) ) )"
   

The result is easy to develop, easy to read, and neatly takes care of managing bind variables for you.

And, yes, there are shortcuts for managing the common insert and update cases, similar to those offered by SQL::Abstract:

Insert

    SQL::Abstract
        my ($sql, @bind) = $o->insert('table',\%data)
        $dbh->do($sql,{},@bind);

    SQL::Interpolate
        my ($sql, @bind) = sql_interp("INSERT INTO table",\%data);
        $dbh->do($sql,{},@bind);

    DBIx::Interpolate
        $dbh->do_i("INSERT INTO table",\%data);
       

Update

    SQL::Abstract
        my ($sql, @bind) = $o->update('table',\%data,\%where);
        $dbh->do($sql,{},@bind);

    SQL::Interpolate
        my ($sql, @bind) = sql_interp("UPDATE table SET", \%data, "WHERE", \%where );
        $dbh->do($sql,{},@bind);

    DBIx::Interpolate
        $dbh->do_i("UPDATE table SET", \%data, "WHERE", \%where )

Friday May 11, 2007
10:11 AM

WWW::Mechanize::Plugin::Display released

WWW::Mechanize is great, but it can be tedious to debug why a Mech script fails, because you can't easily "see" what was on the page at the time of failure.

At least, until now. I made a small plugin, which connects Mech with the great HTML::Display package, which is makes it easy to display a Mech HTML page in a local browser.

I usually use Mech over an 'ssh' connection, so what's "local" to Mechanize is usually not my desktop where there's a graphical browser running. So in the example, I show how to use the great console browser, w3m, for display. It (sort of) renders tables, which is usually enough to at least give me an idea of what went wrong. Here's how I might use it with Test::WWW::Mechanize:

  $mech->get_ok($url) || $mech->display();

If this test fails, I'll see the result in the browser. I don't always leave the calls to "display()" in the code when I'm done, since this wouldn't make sense in the content of a smokebot.

See WWW::Mechanize::Plugin::Display on CPAN.