LesleyB has asked for the wisdom of the Perl Monks concerning the following question:

Hi

I'm working through the introductory DBI documentation and thought I'd try out a bit of code

foreach (@{ $DBI::EXPORT_TAGS{sql_types} }) { printf "%s=%d\n", $_, &{"DBI::$_"}; }

but it doesn't seem to work. It seems to pull up the sql_types tags but this code

#!/usr/bin/perl use strict; use warnings; use CGI; use DBI; use DBD::mysql; print "Content-Type: text/html\n\n"; foreach (@{ $DBI::EXPORT_TAGS{sql_types} }) { printf "%s=%d\n", $_, &{"DBI::$_"}; }

results in the error message

Content-Type: text/html Can't use string ("DBI::SQL_GUID") as a subroutine ref while "strict r +efs" in use at ./tmp.cgi line 12.

I can fix this by not using use strict; but I'd rather not. I have a Super Search on while "strict refs" in use to understand more about this error in general. However I usually fix/rewrite the code when I get this error. I'm just a bit stumped on how to get to the subroutine that returns the value of the sql_type

Is there a better way to achieve what this code sets out to do with use strict; in play?

Replies are listed 'Best First'.
Re: strict refs
by Krambambuli (Curate) on Oct 28, 2008 at 09:13 UTC
    The following works for me:
    foreach (@{ $DBI::EXPORT_TAGS{sql_types} }) { my $ref = \&{"DBI::$_"}; printf "%s=%d\n", $_, &$ref; }
    It is documented in strict:
    There is one exception to this rule: $bar = \&{’foo’}; &$bar; is allowed so that "goto &$AUTOLOAD" would not break unde +r stricture.
    Hth,

    Krambambuli
    ---

      Yes, Krambabuli, it does help and it does work for me too.

      Thank you for pointing out the documentation on it

Re: strict refs
by JavaFan (Canon) on Oct 28, 2008 at 10:52 UTC
    I can fix this by not using use strict; but I'd rather not.
    This sounds to me that you're using "use strict" because someone convinced you it was a good idea, but you don't really know what's for.

    Many people have the impression that "use strict" prevents you from writing bad code. Or preventing you to use certain "bad" constructs. That's not true. "use strict" disallows certain interpretations of code; it prevents perl to interpret your code in a certain way when that way could easily be a mistake. In your case, the use of &{"DBI::$_"} as a symbolic reference intended - so you can tell Perl that you intend it this way by disabling 'use strict "refs"' for the block:

    foreach (@{ $DBI::EXPORT_TAGS{sql_types} }) { no strict "refs"; printf "%s=%d\n", $_, &{"DBI::$_"}; }
    There's nothing wrong with that.
      Another way to think of it is like that yellow striped safety glass over top of big red buttons.
      Occasionally you really do want to launch the nukes...
      Just don't leave the cover flipped open longer than necessary, and it can continue to help to prevent accidents with disastrous consequences (like executing unknown code).

        Well, I am having a strict refs kind of day at the moment - now with the Captcha::reCAPTCHA module check_answer method.

        As it is entwined in CGI::FormBuilder and Template I guess I only have myself to blame.

      I use strict; because it helps me avoid writing poor or ambiguous code.

      While no-one else has persuaded me to use strict;, the general consensus of opinion, even in the DBI docs, is

      To use DBI, first you need to load the DBI module: use DBI; use strict; (The use strict; isn't required but is strongly recommended.)

      What I lack at the moment is the knowledge when (and sometimes how) to safely switch it off.

        Strictures are lexically scoped, so if you turn them off in a small block, you are pretty safe.

        This particular example happens in a small foreach loop, so there's your block. If you're in the middle of a longer sequence, you can say

        do_stuff(); { no strict 'refs'; printf "%s=%d\n", $_, &{"DBI::$_"}; } do_more_stuff();