Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:
Hi Monks!
I am trying to understand why I am getting this warning - "Odd number of elements in anonymous hash" - since the variable "$attached" has been initialized before it
gets to the hash. I only need these values in the hash if "$code" is true, otherwise it should be nothing there.
Where/what am I missing, if someone could take a look at this sample code I am posting:
...
for my $email (@mail) {
my $attached = ($code) ? "attach_path => '$file_name',attach_filena
+me => '$file_name',attach_type => 'application/txt'," : '';
my $success = email( {
to => $email,
from => $from,
from_name => $name,
subject => $subject,
body => $body,
$attached
} );
}
...
Thanks for looking!
Re: Odd number of elements in anonymous hash
by toolic (Bishop) on Jun 09, 2016 at 16:11 UTC
|
my $href = {
to => $email,
from => $from,
from_name => $name,
subject => $subject,
body => $body,
};
if ($code) {
$href->{attach_path} = $file_name;
$href->{attach_filename} = $file_name;
$href->{attach_type} = 'application/txt';
}
my $success = email($href);
| [reply] [Watch: Dir/Any] [d/l] |
Re: Odd number of elements in anonymous hash
by tangent (Parson) on Jun 09, 2016 at 16:06 UTC
|
$attached is a hash reference so you need to dereference it, and default to an empty hash ref if $code is false:
my $attached = ($code) ? "attach_path => '$file_name',attach_filena +m
+e => '$file_name',attach_type => 'application/txt'," : {};
my $success = email( {
to => $email,
from => $from,
from_name => $name,
subject => $subject,
body => $body,
%$attached
} );
Update: as pryrt points out, $attached is not a hash reference (it is a string) but can easily be made into one - see my further example below. | [reply] [Watch: Dir/Any] [d/l] [select] |
|
but when $code is true, $attached is a STRING in the OP code. And I couldn't get test code to dereference the string version to include in the new hashref.
Here's some example code which tries and dumps both code=0 and 1:
#!perl
use strict;
use warnings;
use Data::Dumper;
for my $code (0 .. 1) {
my $attached = $code ? { attach_path => 'etc' } : {};
my $args = {
to => 'to email',
from => 'from email',
%$attached
};
print Dumper($args);
}
| [reply] [Watch: Dir/Any] [d/l] |
|
Yes, actually $attached is a single string whether $code is true or false: in the latter case, it’s the empty string. And that means you get a key/value pair in which the string $attached is the key, and the value is undef — which gives the “Odd number of elements” warning.
The solution is to eval the string:
#! perl
use strict;
use warnings;
use Data::Dump;
my $body = 'Hello!';
my $code = 1;
my $email = 'addressee';
my $file_name = 'unknown';
my $from = 'sender';
my $name = 'A Nonny Mouse';
my $subject = 'Greeting';
my $attached = $code ? "attach_path => '$file_name', " .
"attach_filename => '$file_name', " .
"attach_type => 'application/txt'," : '';
my $success =
{
to => $email,
from => $from,
from_name => $name,
subject => $subject,
body => $body,
eval $attached,
};
dd $success;
Output:
2:21 >perl 1655_SoPW.pl
{
attach_filename => "unknown",
attach_path => "unknown",
attach_type => "application/txt",
body => "Hello!",
from => "sender",
from_name => "A Nonny Mouse",
subject => "Greeting",
to => "addressee",
}
2:21 >
Hope that helps,
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
I didn't notice it was a string, thanks. So it could be done like this, though toolic's answer is cleaner.
my $attached = $code ? { attach_path => $file_name, attach_filename =>
+ $file_name, attach_type => 'application/txt' } : {};
| [reply] [Watch: Dir/Any] [d/l] |
|
|
I think $attached should be a hash ref.
use strict;
use warnings;
use Data::Dumper;
my $code = 1;
my $file_name = 'my_file_name';
my $email = 'to@address.com';
my $from = 'from@address.com';
my $from_name = 'Me';
my $subject = 'try_me';
my $body = 'Here is my message.';
my $attached
= ($code) ? { attach_path => $file_name,
attach_filename => $file_name,
attach_type => 'application/txt',
}
: {}
;
my %args = (
to => $email,
from => $from,
from_name => $from_name,
subject => $subject,
body => $body,
%$attached
);
my $success = email(%args);
sub email {
# Display arguments;
my %arg_hash = @_;
print Dumper(\%arg_hash);
...
}
OUTPUT:
$VAR1 = {
'attach_path' => 'my_file_name',
'from' => 'from@address.com',
'subject' => 'try_me',
'from_name' => 'Me',
'attach_filename' => 'my_file_name',
'to' => 'to@address.com',
'attach_type' => 'application/txt',
'body' => 'Here is my message.'
};
Unimplemented at C:\Users\Bill\perl\monks\email.pl line 38
| [reply] [Watch: Dir/Any] [d/l] |
|
|