FAQ
Hi

I have requirement to make the key of a perl hash to be read only so that
no other function can modify it.

I got Hash::Util package and managed to do what I needed

use strict;
use warnings;
use Hash::Util qw (lock_keys lock_value);
use Data::Dumper;
my %hash=( name => "satya", number => "21");
my $ref=\%hash;
print ("\nBefore ".Dumper(%hash));
lock_value(%hash,"name");
$hash{name}="new name";
print ("\nAfter ".Dumper(%hash));

The problem is that now I get the error

snemana@bats4:~/perlprogs>$perl lock_hash_keys.pl

Before $VAR1 = 'number';
$VAR2 = '21';
$VAR3 = 'name';
$VAR4 = 'satya';
Cannot usefully lock values in an unlocked hash at lock_hash_keys.pl line 10
Modification of a read-only value attempted at lock_hash_keys.pl line 11.

As seen above the program halts when the attempt is made to assign value to
the hash key.
What I wanted is way to stop the assignment and throw and error but not
halt the program, but continue with the program.

Could someone help me with the error handling please?

Thanks,
Satya

Search Discussions

  • Shaji Kalidasan at May 12, 2014 at 9:31 am
    Dear Satya,

    Here is one way to do it.

    [code]
    use strict;
    use warnings;
    use Hash::Util qw (lock_keys lock_value);
    use Data::Dumper;

    my %hash=( name => "satya", number => "21");
    my $ref=\%hash;
    print ("\nBefore ".Dumper(%hash));

    eval {
    no warnings;
    lock_value(%hash,"name");
            $hash{name}="new name";
    };

    if ($@) {
    print "An error occured : $@\n";
    }

    print ("\nAfter " . Dumper(%hash));
    [/code]

    [output]

    Before $VAR1 = 'name';
    $VAR2 = 'satya';
    $VAR3 = 'number';
    $VAR4 = '21';
    An error occured : Modification of a read-only value attempted at
    C:/Users/Shaji/workspace/Perl/sandbox/lock-hash-keys.pl line 13.


    After $VAR1 = 'name';
    $VAR2 = 'satya';
    $VAR3 = 'number';
    $VAR4 = '21';
    [/output]

    On Mon, May 12, 2014 at 2:29 PM, Satya Prasad Nemana wrote:

    Hi

    I have requirement to make the key of a perl hash to be read only so that
    no other function can modify it.

    I got Hash::Util package and managed to do what I needed

    use strict;
    use warnings;
    use Hash::Util qw (lock_keys lock_value);
    use Data::Dumper;
    my %hash=( name => "satya", number => "21");
    my $ref=\%hash;
    print ("\nBefore ".Dumper(%hash));
    lock_value(%hash,"name");
    $hash{name}="new name";
    print ("\nAfter ".Dumper(%hash));

    The problem is that now I get the error

    snemana@bats4:~/perlprogs>$perl lock_hash_keys.pl

    Before $VAR1 = 'number';
    $VAR2 = '21';
    $VAR3 = 'name';
    $VAR4 = 'satya';
    Cannot usefully lock values in an unlocked hash at lock_hash_keys.pl line
    10
    Modification of a read-only value attempted at lock_hash_keys.pl line 11.

    As seen above the program halts when the attempt is made to assign value
    to the hash key.
    What I wanted is way to stop the assignment and throw and error but not
    halt the program, but continue with the program.

    Could someone help me with the error handling please?

    Thanks,
    Satya


    --
    best,
    Shaji
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Your talent is God's gift to you. What you do with it is your gift back to
    God.
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  • Satya Prasad Nemana at May 12, 2014 at 9:39 am
    Shaji

    thank you.
    But the solution will not suffice.
    As I said, there are various other functions in different packages which
    are modifying an environment variable.
    I want to have a lock or make it ready only so that only one can modify and
    the rest cant.
    This code will work but I have to make the same code change in all the
    places where this hash value is being set.
    so, this will not work for me.

    Please tell me if there are other ways to handle this.

    thanks,
    Satya


    On 12 May 2014 15:01, Shaji Kalidasan wrote:

    Dear Satya,

    Here is one way to do it.

    [code]
    use strict;
    use warnings;
    use Hash::Util qw (lock_keys lock_value);
    use Data::Dumper;

    my %hash=( name => "satya", number => "21");
    my $ref=\%hash;
    print ("\nBefore ".Dumper(%hash));

    eval {
    no warnings;
    lock_value(%hash,"name");
    $hash{name}="new name";
    };

    if ($@) {
    print "An error occured : $@\n";
    }

    print ("\nAfter " . Dumper(%hash));
    [/code]

    [output]

    Before $VAR1 = 'name';
    $VAR2 = 'satya';
    $VAR3 = 'number';
    $VAR4 = '21';
    An error occured : Modification of a read-only value attempted at
    C:/Users/Shaji/workspace/Perl/sandbox/lock-hash-keys.pl line 13.


    After $VAR1 = 'name';
    $VAR2 = 'satya';
    $VAR3 = 'number';
    $VAR4 = '21';
    [/output]

    On Mon, May 12, 2014 at 2:29 PM, Satya Prasad Nemana wrote:

    Hi

    I have requirement to make the key of a perl hash to be read only so that
    no other function can modify it.

    I got Hash::Util package and managed to do what I needed

    use strict;
    use warnings;
    use Hash::Util qw (lock_keys lock_value);
    use Data::Dumper;
    my %hash=( name => "satya", number => "21");
    my $ref=\%hash;
    print ("\nBefore ".Dumper(%hash));
    lock_value(%hash,"name");
    $hash{name}="new name";
    print ("\nAfter ".Dumper(%hash));

    The problem is that now I get the error

    snemana@bats4:~/perlprogs>$perl lock_hash_keys.pl

    Before $VAR1 = 'number';
    $VAR2 = '21';
    $VAR3 = 'name';
    $VAR4 = 'satya';
    Cannot usefully lock values in an unlocked hash at lock_hash_keys.plline 10
    Modification of a read-only value attempted at lock_hash_keys.pl line 11.

    As seen above the program halts when the attempt is made to assign value
    to the hash key.
    What I wanted is way to stop the assignment and throw and error but not
    halt the program, but continue with the program.

    Could someone help me with the error handling please?

    Thanks,
    Satya


    --
    best,
    Shaji

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Your talent is God's gift to you. What you do with it is your gift back to
    God.

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


    --
    Satya Prasad
  • Janek Schleicher at May 12, 2014 at 10:09 am

    On 12.05.2014 11:39, Satya Prasad Nemana wrote:

    But the solution will not suffice.
    As I said, there are various other functions in different packages which
    are modifying an environment variable.
    I want to have a lock or make it ready only so that only one can modify
    and the rest cant.
    This code will work but I have to make the same code change in all the
    places where this hash value is being set.
    so, this will not work for me.
    Some general stuff:

    - having various other functions in different packages modifying and
    working with global variables is usually not a good idea. With growing
    complexity, your code will be hard to handle and to understand and
    controlling the workflow gets nasty. You're probably right at the moment
    exactly at this point.

    - Trying to modify environment variables to control workflow is a bad
    idea in general. There a gazillions possible that side effects are not
    handlebar and even if it gets too complicated.

    - Bulding a global data structure around environment variables (like you
    try by locking them via Perl) will not work or not work like you expect
    unless the underlying OS enhances it. For at least, *nix und Windows
    does not. Usually the environment variables are controlled by the OS and
    not the programming language. Yes, you can set $ENV{...} and it will
    work, but don't do it for program flow. Do it for configuration.

    - In general, if you want to encapsulate a data structure, so only your
    own script/module/whatever can change it allover and the rest of the
    world only should get restricted access, the solution is called: Object
    Oriented Programming. [Here, maybe you want a Singleton-Object that
    controlls a global configuration?]

    Please tell me if there are other ways to handle this.
    2 general ways are there:

    - Make your scripts/modules/programs/w/e indepedent from each other. So
    they get data piped in and pipe it out. They can use then environment
    variables, but they use it for configuration, not for working flow
    logic. Then in the end, all your master program will do is similiar to a
    shell script. Like a ps -a | grep -r *.txt | ... and so on.

    - Redesign it object oriented.


    If your code is small, let's say <500 lines, then of course you can find
    "hacking" alternatives, but even if you intend it, first describe your
    problem detailed and analyzed.
    Especially: Why do you want global locked name=>key pairs?
    As you haven't yet (all you say so far is that you want them), neither
    you nor we can give you a way to the solution.


    Greetings,
    Janek
  • Satya Prasad Nemana at May 12, 2014 at 10:19 am
    Janek

    Thank you.
    I would have taken all your inputs had I been designing new stuff.
    But, this is existing stuff and cant be redesigned or changed.
    I am looking for this change to avoid having to modify some 200 files all
    setting the same environment variable.
    If this does not work(locking and not letting others change the hash key
    value), I will have to do the old way of having to modify all the 200 files
    that are setting this variable and comment out that code.

    Regards,
    Satya



    On 12 May 2014 15:39, Janek Schleicher wrote:

    On 12.05.2014 11:39, Satya Prasad Nemana wrote:

    But the solution will not suffice.
    As I said, there are various other functions in different packages which
    are modifying an environment variable.
    I want to have a lock or make it ready only so that only one can modify
    and the rest cant.
    This code will work but I have to make the same code change in all the
    places where this hash value is being set.
    so, this will not work for me.
    Some general stuff:

    - having various other functions in different packages modifying and
    working with global variables is usually not a good idea. With growing
    complexity, your code will be hard to handle and to understand and
    controlling the workflow gets nasty. You're probably right at the moment
    exactly at this point.

    - Trying to modify environment variables to control workflow is a bad idea
    in general. There a gazillions possible that side effects are not handlebar
    and even if it gets too complicated.

    - Bulding a global data structure around environment variables (like you
    try by locking them via Perl) will not work or not work like you expect
    unless the underlying OS enhances it. For at least, *nix und Windows does
    not. Usually the environment variables are controlled by the OS and not the
    programming language. Yes, you can set $ENV{...} and it will work, but
    don't do it for program flow. Do it for configuration.

    - In general, if you want to encapsulate a data structure, so only your
    own script/module/whatever can change it allover and the rest of the world
    only should get restricted access, the solution is called: Object Oriented
    Programming. [Here, maybe you want a Singleton-Object that controlls a
    global configuration?]



    Please tell me if there are other ways to handle this.
    2 general ways are there:

    - Make your scripts/modules/programs/w/e indepedent from each other. So
    they get data piped in and pipe it out. They can use then environment
    variables, but they use it for configuration, not for working flow logic.
    Then in the end, all your master program will do is similiar to a shell
    script. Like a ps -a | grep -r *.txt | ... and so on.

    - Redesign it object oriented.


    If your code is small, let's say <500 lines, then of course you can find
    "hacking" alternatives, but even if you intend it, first describe your
    problem detailed and analyzed.
    Especially: Why do you want global locked name=>key pairs?
    As you haven't yet (all you say so far is that you want them), neither you
    nor we can give you a way to the solution.


    Greetings,
    Janek

    --
    Satya Prasad
  • Jing Yu at May 12, 2014 at 11:34 am
    Hi Satya,

    I do not know whether you can use Tie::Hash?
    This is my try:

    use strict;
    use warnings;
    use Data::Dumper;
    use TieReadOnly;
    tie my %hash, "TieReadOnly";
    %hash=( name => "satya", number => "21");
    print ("\nBefore ".Dumper(\%hash));

    $hash{name}="new name";
    print ("\nAfter ".Dumper(\%hash));

    package TieReadOnly;
    use Tie::Hash;
    use Carp;
    our @ISA = 'Tie::StdHash';

    sub STORE {
         my ($self, $key, $value) = @_;
         if ($self->{$key}){
             carp "The value is read only. You failed";
         }else{
             $self->{$key} = $value;
         }
    }

    The output is like this:

    Before $VAR1 = {
               'name' => 'satya',
               'number' => '21'
             };
    The value is read only. You failed at tst.pl line 22.

    After $VAR1 = {
               'name' => 'satya',
               'number' => '21'
             };
    dhcp-892b2e52:Perl logust$
    On 12 May 2014, at 09:59, Satya Prasad Nemana wrote:

    Hi

    I have requirement to make the key of a perl hash to be read only so that no other function can modify it.

    I got Hash::Util package and managed to do what I needed

    use strict;
    use warnings;
    use Hash::Util qw (lock_keys lock_value);
    use Data::Dumper;
    my %hash=( name => "satya", number => "21");
    my $ref=\%hash;
    print ("\nBefore ".Dumper(%hash));
    lock_value(%hash,"name");
    $hash{name}="new name";
    print ("\nAfter ".Dumper(%hash));

    The problem is that now I get the error

    snemana@bats4:~/perlprogs>$perl lock_hash_keys.pl

    Before $VAR1 = 'number';
    $VAR2 = '21';
    $VAR3 = 'name';
    $VAR4 = 'satya';
    Cannot usefully lock values in an unlocked hash at lock_hash_keys.pl line 10
    Modification of a read-only value attempted at lock_hash_keys.pl line 11.

    As seen above the program halts when the attempt is made to assign value to the hash key.
    What I wanted is way to stop the assignment and throw and error but not halt the program, but continue with the program.

    Could someone help me with the error handling please?

    Thanks,
    Satya
  • Dr.Ruud at May 13, 2014 at 3:51 pm

    On 2014-05-12 10:59, Satya Prasad Nemana wrote:

    I have requirement to make the key of a perl hash to be read only so
    that no other function can modify it.
    The keys are already read-only.

    --
    Ruud

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupbeginners @
categoriesperl
postedMay 12, '14 at 8:59a
activeMay 13, '14 at 3:51p
posts7
users5
websiteperl.org

People

Translate

site design / logo © 2021 Grokbase