The only way I have found to make this work -- after several SuperSearches and trying perl5.6 and perl5.8 -- is to create a new simple scalar variable and use this as the method call, as such:
$$database_handle = DBI->connect( map { my $s = "database_$_"; exists $arguments{$_} ? $arguments{$_} : $s->() } qw(data_source_name username password taint) ) or die "Could not connect to the ". "database: $DBI::errstr";
The above code compiles fine. It is a bit kludgy though. Is there any way to accomplish a method call that mixes an interpolated variable and some known text, sort of like a double quoted string?

As far as I can work out there isn't such a way. :( In fact, to do what you're doing up there in the map you have to have strict refs turned off. You've probably turned them off for this whole section because otherwise you could well be having trouble with $$database_handle.

I can offer you two alternatives to this problem, however. Both strict compliant. If your database_* subroutines merely return a string value, ie:

sub database_username { return "fred"; }
then hash defaults might be the way to go:
my %defaults = ( data_source_name => ".....", username => "fred", password => "fred", taint => { Taint => 1 } ); # then later... %arguments = (%defaults, %arguments); my $dbh = DBI->connect( @arguments{ qw(data_source_name username password taint) }) or die "Could not connect to the database: ". "$DBI::errstr";
When assigning to hashes, later keys of the same name overwrite the values from the earlier keys. This means that if "data_source_name" is provided in %arguments the %arguments version is kept. Obviously keys which are not included in %arguments remain those of the default hash.

The @arguments{ qw/.../ } structure is a hash slice. This ensures we get the values out in the order we want them to appear.

This ideas works if your database_* subroutines are ONLY returning simple stuff. If you want your database_* subroutines to read these values from a file or something similar and to do so only if needed then you might want to do something like the following:

my %defaults = ( data_source_name => \&database_data_source_name, username => \&database_username, password => \&database_password, taint => \&database_taint, ); # and later: my $dbh = DBI->connect ( map { exists $arguments{$_} ? $arguments{$_} : $defaults{$_}() } qw(data_source_name username password taint) ) or die "Could not connect to the database: ". "$DBI::errstr"; # and somewhere else: sub database_data_source_name { # read stuff from file.. # do other stuff return #something }
This has the added advantage of looking a whole lot nicer than using a string as a coderef. What we're doing here is creating a hash of references to our subroutines. It's not until we do $defaults{$_}() that these subroutines actually get executed.

I hope this helps,

jarich

Update: Heh. I post my node and already stand corrected. Well done Anonymous Monk. If you do wish to make your code strict compliant, however, you may find my suggestions useful.

map { exists $arguments{$_} ? $arguments{$_} : ${\"database_$_"}->() }

In reply to Re: Double quoted string as method call by jarich
in thread Double quoted string as method call by ryantate

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.