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

I've been roaming thist site for some months now and always found answers to my questions without asking. Here's my first though:

My assignment at work was to make a small program that sends out about 9000 mail to customers of a client of ours.
Sending mail from a Perl-script is almost to easy to be true, so that is not my problem.

When I make a script/program I always try to make small test-scripts for each sub in the program.

I have a sub that reads an ini-file that returns a hash containing the ini-file settings and in the testscript it behaves just as expected.
When I move the EXCACT same code to the main script it fails with an error:
"Odd number of elements in hash assignment at SendMail.pl line 19."

The lvalues is of the same type to.
When I use Data::Dumper to print the hash returned from the sub it prints this:

$VAR1 = { '9/16' => undef };

Now, if the behaviour was consistent it would be something I could live with, but this really puzzles me.
Here's the best part:
When I return a reference from the sub it works like a charm (after changing the lvalue type and argument to Data::Dumper).

If someone knows what's going on here I would appreciate input on this.

Johnny

(Lucky for me there's more than one way to do it...)

Replies are listed 'Best First'.
Re: Returning hash from sub
by duff (Parson) on Dec 05, 2003 at 22:51 UTC

    It looks like you're somehow evaluating the hash in a scalar context. That will give you a string like "9/16" above (16 buckets allocated, 9 used). Show your actual code and I might be able to help more.

Re: Returning hash from sub
by delirium (Chaplain) on Dec 06, 2003 at 06:16 UTC
    Like duff says, we're going to need to see the code. The same code should yield the same results. There may be subtle differences outside of the code you cut and pasted, though, like what $/ is set to, how the subroutine closes, etc.

    For what it's worth, here's how I ended up getting around the hash-in-scalar-context problem with reading in Data::Dumper files:

    sub parse_hist { local $/ = undef; %sess_hist = %{do($hist_file)}; }

    In this case, %sess_hist is the last thing in the subroutine, so that should be what is returned. In my code, parse_hist was called in void context and %sess_hist was a global variable, so it didn't matter how stuff got returned (except that I'm probably wasting memory and cycles).

Re: Returning hash from sub
by tilly (Archbishop) on Dec 06, 2003 at 08:46 UTC
    I have the same comment as everyone else, but I suspect from the error message that you are doing something different than they are guessing. Specifically I would guess that you are actually returning a reference to a hash, and you are trying to assign that to a hash. The reference is a single element, and will generate the error that you describe.

    Your ease in moving to references is consistent with your accidentally returning a reference in the first place.

      Nah, that gives a different message. Something like "reference found where even-sized list expected". But until we see the code, we can only guess what's actually happening :-)

Re: Returning hash from sub
by jweed (Chaplain) on Dec 06, 2003 at 06:36 UTC

    Here's what I get out of it. A hash is just a list which happens to be interpreted in pairs, right? So when you return it is scalar context (somehow), it returns what you would expect, 10/14 or something like that. But if you try and treat it as a hash later, it sees it (10/14) and notices that you don't have a value for the hash, just a key. So that's why you seem to be getting the "odd # of elements" error. It thinks you're trying to make a hash out of a one element list

    As for how to fix this, we'd of course need the code.



    Who is Kayser Söze?