Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't modify key/value hash slice in list assignment at .\metro.pl line 31, near "$year;"

Tags:

perl

I'm new in Perl. I can not understand why I can not assign year to the hash field in string

   %currentBook{year}=$year; 
Full code here.
use warnings;
use strict;
use Scalar::Util qw(looks_like_number);
use Time::localtime; 

my $maxYear = Time::localtime->year+1;
my $year = $maxYear;
my %currentBook = (name=>"firstCurrentBook",
    author=>"NO",
    place=>"NO",
    year=>0);
my %maxBook = %currentBook;
my %minBook = %currentBook;
print "Choose action\n1 - Input book\n2 - Print min max year\n3 = exit\n->";
my $cond = <STDIN>;
while ($cond  != 3)
{
    if ($cond == 1){
        print "\nInput book name: ";
        $currentBook{name} = <STDIN>;
        print "\nInput author surname and initials: ";
        $currentBook{author} = <STDIN>;
        print "\nInput place: ";
        $currentBook{place} = <STDIN>;    
        do{
            print "\nInput year of book: ";
            $year = <STDIN>;
            chomp $year;
        } while  (!looks_like_number($year) || $year < 0 || $year > Time::localtime->year);
        %currentBook{year}=$year;
        if (%currentBook{year} > %maxBook{year}){
            %maxBook=%currentBook;
        }
        if (%currentBook{year} < %minBook{year}){
            %minBook=%currentBook;
        }
    }
}

like image 436
Павел Михаловский Avatar asked Jan 11 '18 16:01

Павел Михаловский


1 Answers

You've already got the answer in a comment by toolic, but I will elaborate why this happens.

my %books = ( year => 2017 );
%books{year} = 2018;

This code will throw the error you saw.

Can't modify key/value hash slice in list assignment at /home/simbabque/code/scratch.pl line 6313, near "2018;"
Execution of /home/simbabque/code/scratch.pl aborted due to compilation errors.

To make your program do what you intended, you need to use the $ sigil, not the % sigil, because the value inside $books{year} is a scalar.

But why the error message?

Actually, %books{year} is a totally valid Perl expression.

use Data::Dumper;

my %books = ( year => 2017 );
print Dumper %books{year};

This will print

$VAR1 = 'year';
$VAR2 = 2017;

The construct %book{year} is a so-called hash slice, and it returns a list of key/value pairs. You can also put in a list of keys, and get a list of both the keys and their values out. This is useful to quickly construct a sub hash.

my %timestamp = ( year => 2017, month => 12, day => 31, hour => 23, minute => 59 );
my %date = %timestamp{ 'year', 'month', 'day' };

print Dumper \%date;

The output of that is

$VAR1 = {
          'day' => 31,
          'month' => 12,
          'year' => 2017
        };

However, this kind of behavior does not allow you to assign to %books{year}. It simply does not make sense, because it returns a list of key/value pairs. That's why this construct is not what we call an lvalue in Perl, so it cannot be on the left hand side of an assignment.

like image 116
simbabque Avatar answered Nov 20 '22 17:11

simbabque