in reply to Benefits of everything is an object? Or new sigils?

There are a number of modules for converting hashes to blessed hashrefs with accessors for the elements within, f.e. Data::AsObject and Hash::AutoHash. In this code I imagined you'd be using an %employees hash rather than an array, and keyed it on some imaginary employee id. I then subclassed Data::AsObject::Hash to add a new method to take a reference to the employees hash and create the accessors (through the dao function) automatically.

I was able to add custom methods to my EmployeeData class which can work on $self as either a subclass of Data::AsObject::Hash or as a hashref (or hash, through dereferencing) and you can continue to use the %employees hash as before.

If you wished to use an array, then dao would need to be given a hashref with one key and a reference to the array as the value, e.g. dao { data => \@employees }.

Of course, you could just as easily have created a completely new class, which just blessed \@employees (or \%employees) into $class and just used it as a means to add methods.

If you keep both %employees and $employees in the same scope it would provide a (really ugly) way of keeping the original array|hash and its blessed reference and using, f.e., both push @employees, { name => 'Foo Bar' }; and $employees->method_call; in the same code, though hopefully at some point you'd switch over to just the object/reference.

I don't this is some 'problem' which requires the use of slow modules like autobox or some wholesale re-invention of Perl symbology. Just some reasonable amount of pre-planning and willingness to make reasonable, incremental changes in existing code.

use strict; use warnings; { package EmployeeData; use Data::AsObject; use base 'Data::AsObject::Hash'; sub new { my $class = shift; my ($data) = @_; my $obj = Data::AsObject::dao ( $data ); bless $obj, $class; } sub foo { my $self = shift; my ($eidx) = @_; print STDERR $self->{$eidx}{age} . "\n"; } } my %employees = ( JS0114 => { name => 'Joe Soap', age => 56, }, JS1282 => { name => 'Joan Smith', age => 28, }, ); my $employees = EmployeeData->new(\%employees); bless $employees, 'EmployeeData'; print $employees{JS0114}{age} . "\n"; $employees->foo('JS1282'); print $employees->JS0114->age . "\n";

Replies are listed 'Best First'.
Re^2: Benefits of everything is an object? Or new sigils?
by LanX (Saint) on Mar 04, 2010 at 17:29 UTC
    As far as I understand these packages simplify the workaround I sketched...

    > If you keep both %employees and $employees in the same scope it would provide a (really ugly) way of keeping the original array|hash and its blessed reference

    yeah indeed ugly, thats what I meant.

    > I don't this is some 'problem' which requires the use of slow modules like autobox ...

    Contrary to the believe of the group that flames against me, I'm not propagating autobox as an existing solution! (I was asking a question in another thread about autobox and hit the nerve of a group of united fanboys. But I'm tired to repeat this!)

    I was talking about the theoretical benefits JS has over Perl in this respect, because there a hash acn be treated as object right from the beginning.

    Tieing this hash provides the same functionality in Perl like altering the object in JS (Phase 2)

    BTW: According to the docs, autobox isn't slower than method calls on blessed references. >or some wholesale re-invention of Perl symbology.

    A Sigil for each Ref-Type would open a lot of simplifications for problems newbies face when starting to learn Perl.

    Believe it or not, many people stop and hate Perl just because of these problems...long before even entering a level allowing to understand Data::AsObject and Hash::AutoHash.

    Many thanx for your contribution, it's one of the better ones lifting the level of this discussion! :)

    Cheers Rolf

      In a way you could say there is a sigil for each ref-type, when it gets deferenced (or when it is actually used as the base type, and not a reference in a scalar), @ => @$, % => %$, & => &$.

      For amusement or other purpose, here is code that lets you use a hashref or hash (or arrayref or array) by blessing the former (and the ref of the latter) into an (initially) non-existent package, and then create a function in that package. The function can be called in the usual way ($blessedref->function), but can also be called with NameSpace::function(%indirectlyblessedhash) owing to the \% prototype on the function which uses the reference of that parameter.

      If you use references for your data structures instead of plain hashes and arrays, and bless those references into appropriate packages (and dereference where needed), you will have the equivalent functionality to javascript array|objects. For me, at least, the requirement (softened by autobox), that objects be scalars makes sense, as scalars are for holding one value (base type or object) at a time.


        > In a way you could say there is a sigil for each ref-type, when it gets deferenced (or when it is actually used as the base type, and not a reference in a scalar), @ => @$, % => %$, & => &$.

        Alas, it's more complicated than this.

        Just to give you one example, if you have a nested structure you have to write something like  push @{ $ref->[1][2][3] }, "elem"

        Very motivating for beginners! :(

        In most other languages you can simply write something like push ref[1][2][3] , "elem" ...

        Cheers Rolf