in reply to Re^4: Removing AUTOLOAD from CGI.pm
in thread Removing AUTOLOAD from CGI.pm

> Not sure why AUTOLOAD is needed in CGI anyway, the allowed HTML-tags seem to be exported from CGI to the local namespace, but only spring into existence within the stash of %CGI:: after first use! Speed can't be that relevant, CGI doesn't do any syntax validation, so the same generic function could be installed at import time for all html-tags, maybe with a closed over $tag_name if necessary.

I believe the original reason was to defer the compilation so the majority of functions, not just html functions, were wrapped in quotes and then eval'd and added to the namespace when called. Or you could pass -compile (or call ->compile) to force them to compile at import time. It was kind of a way to fix the God object problem when compiling a 4000+ line module was slow. An added side effect was the ability to call CGI with arbitrary tags not included in the module... it was future proofed! You could call CGI->wibble and get a <wibble> tag.

Anyway it's all gone now, or soon will be.

Replies are listed 'Best First'.
Re^6: Removing AUTOLOAD from CGI.pm
by LanX (Saint) on Feb 24, 2015 at 13:01 UTC
    Hi

    I wasn't criticizing CGI but trying to analyze the conditions for a new HTML DSL module. :)

    I'm sure compilation speed shouldn't matter when generating closures. (I will add a benchmark later this day)

    But CGI was designed for Perl 4 and I suppose Perl 4 wasn't able to closure... IIRC it didn't even have lexical variables.

    Your wibble-tag is implemented as a method call, so it wouldn't depend on exporting and pre declaration anyway.

    But DSLs are at the very least just syntactic sugar to avoid method calls.

    > Anyway it's all gone now, or soon will be

    Thanks for your work! :)

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)

    PS: Je suis Charlie!

      > I'm sure compilation speed shouldn't matter when generating closures. (I will add a benchmark later this day)

      Here a simplified example which showed that installing subs with closures¹ is 5 times faster than eval.

      That's less dramatic than I thought, but eval performance also heavily depends on the length of code.

      So adding 10 no-ops already made eval 10 times slower while closure didn't change.

      use strict; use warnings; use Time::HiRes qw/time/; BEGIN { $\="\n"; my $count=1000; sub noop { }; my $start=time; sub tag_gen { my ($tag)=@_; sub { noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); "<$tag>",@_,"</$tag>"; } } { no strict 'refs'; for my $x (1..$count) { my $tag="h$x"; *{$tag}=tag_gen($tag); } } print "Closure: ",time-$start; $start = time; for my $x (1..$count) { my $tag="H$x"; eval sprintf <<'__CODE__', $tag; sub %1$s { noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); noop("Ipse Lorum"); "<%1$s>",@_,"</%1$s>"; } __CODE__ } print "Eval: ",time-$start; } print h1 h2 "closure"; print H1 H2 "eval";

      output:

      Closure: 0.0279860496520996 Eval: 0.343567132949829 <h1><h2>closure</h2></h1> <H1><H2>eval</H2></H1>

      One has to keep in mind that 15-20 years ago machines were factor 1000 slower, i.e. auto loading was relevant.

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)

      PS: Je suis Charlie!

      update

      fixed bug with no-ops.

      ¹) currying to be precise

Re^6: Removing AUTOLOAD from CGI.pm (flexibility?)
by LanX (Saint) on Feb 24, 2015 at 16:42 UTC
    > it was future proofed! You could call CGI->wibble and get a <wibble> tag.

    I wasn't able to reproduce this without explicitly importing "wibble"

    DB<100> use CGI qw(:all wibble) DB<101> wibble => "<wibble />"

    but

    DB<100> use CGI ':all' DB<101> $x=CGI->new() DB<102> $x->wibble() Undefined subroutine CGI::wibble at (eval 24)[multi_perl5db.pl:644] line 2

    So autoloading makes not much sense in this case.

    It doesn't make the code more flexible it only delays the installation, which could already happen in the importer.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)

    PS: Je suis Charlie!

      You had to use :any to get this behaviour:

      $ pmvers CGI 3.59 $ perl -E 'use CGI qw/:any/; say CGI->new->wibble({foo=>"bar"},"baz")' <wibble foo="bar">baz</wibble>

        > You had to use :any to get this behaviour:

        Didn't see this, because :any is not documented in CGI , though -any is as a "pragma" (and mentioned in your blog-post)

        There is also a mention of -compile , which means AUTOLOAD isn't needed to create the HTML-DSL.

        IOW you could¹ get rid of AUTOLOAD without deprecating HTML-subs, just by making -compile the default.

        But if you meant to deprecate the -autoload pragma, this seems to be a good idea.

        Installing an AUTOLOAD into the importing namespace sounds like a very hazardous hack.

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)

        PS: Je suis Charlie!

        ¹) I don't say "should" :)

        update

        After reading your blog-post again (>4th time) I'm puzzled. You only say you are disabling AUTOLOAD but not that you are deprecating precompiled HTML-subs in general.

        Did I misunderstand you? Maybe you could clarify.