in reply to References of Eternal Peril

The whole point of 'use strict' and hard refs is to get away from mixing the realm of strings and the realm of variable names. Here there be dragons.

Your code is a marvelous example of the danger of such approaches. Your code could easily break if someone were to add to the database a column that has the same name as an existing variable in your program!

I agree with the first replier: If spelling out your variable names is too tedious (and it probably would be too tedious for me), use hashes. That's what they're for. And they can have nice short names.

    -- Chip Salzenberg, Free-Floating Agent of Chaos

Replies are listed 'Best First'.
RE: You can't get there from here....
by tilly (Archbishop) on Aug 11, 2000 at 05:40 UTC
    The problem that I have with hashes is that you go through all of the work in strict to make sure you cannot mistype your variable names and then you throw it all away because there is no check for misspelled hash entries.

    I have used 2 solutions to get around that in the past. One is Class::Struct, the other is pseudo-hashes. Each has their gotchas. Now I know you had some bad luck with pseudo-hashes in the Topaz effort, which leads me to a couple of questions.

    First of all what do you suggest to this problem? (Want to use a hash or reference to one, but with only validated keys allowed.)

    And secondly is it likely that stuff I did with pseudo-hashes is going to be low priority (ie in the 5% acceptable breakage) for Perl 5.6? (I know it is early for this question, I just would like an educated guess.)

    Thanks,
    Ben

      Plan A: Put a unique prefix on the database column names, turning off strict temporarily:
      { no strict 'refs'; $sth->bind_columns( map { \${"c_$_"} @{ $sth->{NAMES_lc} } ) }
      Plan B: If you want the advantages of variables and the advantages of hashes, there is a way, but it will cost you a little in speed. There is one language construct that can see variables and can be built with strings, even with strict enabled: eval.
      local $, = ',$'; # saves on the joins eval "\$sth->bind_columns(\\( \$@{$sth->{NAMES_lc}} ))"
      However, now you're actually letting column names into the Perl parser! A saying about frying pans and fires comes to mind.... I'd much rather disable strict than make wide use of eval STRING.

      As for pseudohashes: I think they're great. The only thing about their implementation in Perl 5 that ate me alive was the fact that they weren't a distinct data type, but rather a mere access method, usable with any array at any time. If they had to be declared somehow at their creation, hey, I'd have been praising them in my Topaz talk.

          -- Chip Salzenberg, Free-Floating Agent of Chaos

        chip, merlyn, and tilly (and anyone else, I suppose):

        Some of the ideas listed here set me to thinking. What would be the implications of creating a separate package just for the row data and using that instead of a hash? That is pretty much what I am doing now, except referencing main:: instead of another symbol table.

        Some things I am concerned about:

        • Memory usage in creation a second package in a perl program
        • Speed of calling variables longhand from other packages (ie, $Foo::Bar::zot)
        • Anything in a similar, pragmatic vein... :-)

        If you folks think it's feasible, I'll generate a couple thousand records of junk data and do some benchmarks this weekend.

        Alakaboo

        I really like merlyn's idea of a tied hash. I will check CPAN for that, else make it myself. I may just make its internal representation look like a pseudohash though. :-)

        Personally I would prefer the syntax of a pseudohash if it needed some sort of declaration, IMO it is too bad that the technical advantages of that interface was not realized earlier. :-(

      As a runtime solution, create a tied hash that supported only a limited set of keys, throwing an exception if a distinct key was used.

      -- Randal L. Schwartz, Perl hacker

RE: You can't get there from here....
by mwp (Hermit) on Aug 12, 2000 at 02:33 UTC

    > I agree with the first replier: If spelling out your variable names is too tedious (and it probably would be too tedious for me), use hashes. That's what they're for. And they can have nice short names.

    Too slow. :-)

    > Your code is a marvelous example of the danger of such approaches. Your code could easily break if someone were to add to the database a column that has the same name as an existing variable in your program!

    I appreciate the wake-up call, but consider this:

    my($field1, $field2, $field3); $sth->prepare("SELECT Field1, Field2, Field3 ..."); $sth->bind_columns(\($field1, $field2, $field3)); while($sth->fetch) { print "$field1\t$field2\t$field3\n"; }

    Versus:

    my($field1, $field2, $field3); $sth->prepare("SELECT Field1, Field2, Field3 ..."); $sth->bind_columns(map { \$$_ } @{ $sth->{NAME_lc} }); while($sth->fetch) { print "$field1\t$field2\t$field3\n"; }

    In both situations, our would-be saboteur has to add a field variable to the my() list, a field name to the SELECT list, and then add the output command. If that doesn't hammer the point home that the variable name is reserved, I doubt one more step (adding the same field to the list of binded variables) is going to make much of a difference.

    I guess the point I'm trying to make here is that there's more than one way to do it... and there's more than one way to break it. In-line comments and self-documenting code (ie, I did not use a SELECT *, the field list was explicitly defined) are really our best tools in fighting "ignorance". Any script can be easily broken in any number of ways.

    Besides the fact, my proposal to use a separate package name gets around this problem. :-) Other than, of course, someone using the same package name. But I think it's safe to assume that a programmer experienced and confident enough to be creating packages like that will at least take a look around to make sure the package is being used. This is where documentation and commenting comes in handy!

    Thanks for your insight.

    Alakaboo