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

I have been editing a small script to get the hashes to work for a larger script. So far, I have been getting the error: Reference found where even-sized list expected at ./idv1csv line ---. The "---" represents one of many lines. This script retrieves MP3 information and outputs the hash/value pairs to the screen. Or is supposed to. When running without warnings or strict, it happily produces empty hashes and clean output (wrong). I placed a lot of debugging in the script, but here is what I have:
#! /usr/bin/perl # (above should be "perl -s" for parameters) use strict; use warnings; use MP3::Info; foreach my $file (`ls *.mp3`) { chomp $file; print "$file\n"; my %info = get_mp3info($file); my %tags = get_mp3tag($file); foreach my $key (keys %info) { my $value = $info{$key}; print __LINE__, "\t $key = $value\n"; } print __LINE__, "\t Time: $info{TIME}\n"; foreach my $key (keys %tags) { my $value = $tags{$key}; print __LINE__, "\t $key = $value\n"; } print __LINE__, "\t Title: $tags{TITLE}\n"; }
The output on a console looks like this for one MP3 file:
02_-_Too_Close_To_The_Sun.mp3 Reference found where even-sized list expected at ./idv1csv line 12. Reference found where even-sized list expected at ./idv1csv line 13. Use of uninitialized value $value in concatenation (.) or string at ./ +idv1csv line 17. 17 HASH(0x600070340) = Use of uninitialized value $info{"TIME"} in concatenation (.) or strin +g at ./idv1csv line 19. 19 Time: Use of uninitialized value $value in concatenation (.) or string at ./ +idv1csv line 23. 23 HASH(0x6001cb690) = Use of uninitialized value $tags{"TITLE"} in concatenation (.) or stri +ng at ./idv1csv line 25. 25 Title:
ANy help as to why I get this error (Reference found where even-sized list expected) is appreciated. That might help me figure out the other errors, if there is any left.

Replies are listed 'Best First'.
Re: Reference found where even-sized list expected
by choroba (Cardinal) on Sep 26, 2017 at 11:21 UTC
    As documented in MP3::Info , the functions get_mp3info and get_mp3tag don't return hashes, but hash references. Either store them in scalars, or dereference them to store them in hashes:
    my $info = get_mp3info($file); for my $key (keys %$info) {
    or
    my %info = %{ get_mp3info($file) }; for my $key (keys %info) {
    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

      Or, as of Perl v5.22, the experimental "refaliasing" feature can be used, allowing one to access %info as if it were a regular hash, without having to make a copy of it:

      use experimental 'refaliasing'; \my %info = get_mp3info($file); for my $key (keys %info) { print "$key / $info{$key}\n"; }
      Looks like an oversight then. I fixed all the hashes and made them pointers ($), and de-referenced them (%$) where appropriate. Now everything works. Thanks for your help.
Re: Reference found where even-sized list expected
by kcott (Archbishop) on Sep 28, 2017 at 05:04 UTC

    G'day sciguy,

    I see you've been shown three different ways to deal with this: here's a fourth.

    Change

    my %info = get_mp3info($file); my %tags = get_mp3tag($file);

    to

    my %info = get_mp3info($file)->%*; my %tags = get_mp3tag($file)->%*;

    and leave the remainder of your code as is.

    That's called "Postfix Dereference Syntax". It became available in 5.20 with a feature declaration; as of 5.24, that declaration is not required. It's not experimental, so quite OK for production code. Follow that link for more complete details.

    — Ken