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: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?$$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";
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:
then hash defaults might be the way to go:sub database_username { return "fred"; }
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.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";
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:
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.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 }
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
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |