I was recently told that the "everything is an object" paradigma wouldn't have benefits in Perl...

Well actually I was never advocating this approach, but then I started meditating about the following (and maybe not too abstract) situation of coding phases leading to massive refactorings:

Phase 1

I have an array like structure - let's call it @employees - and I'm using in in dozens or hundreds of code positions, pushing to and shifting from it.

Phase 2

After a while I discover I need to extend this structure to check new elements.

E.g. when I need to guaranty that employees are never doubled after changing the family name (e.g. after a marriage) I need to check the name while storing¹.

In JS I would do something like deriving a new constructor² Employees() from Array() and extending it's push() method to allow this extra checking. Then I would only need to change the declaration of employees.

But what can I do in Perl without refactoring the code at dozens of positions?

Well thankfully there is Tie::Array, I'm able to tie a package "Employees" to @employees overriding the PUSH() method.

(You see ALL primitives in Perl already HAVE a back door to be extended like objects!)

Phase 3

Weeks after I discover that it would be handy that @employees was a full object with special methods - lets say something like ->list_active() and ->list_retired().

This wouldn't be a problem in JS, I would simply add these new methods to Employees().

But now I can't do this without refactoring the Perl code, because I can't bless @employees into a new package allowing these methods. I can only bless references and only call methods on these references.

The best thing I would be able to do is blessing \@employees and write \@employees->list_retired() whenever I need this new object...

Rather ugly isn't it?

Perlish workarounds

So what can I do to avoid this situation?

  • One solution would be to always start right from the beginning with a array-reference $employees and always write push @$employees_ar, "name". Consequently avoiding any use of the @ sigil.

    Here we get into a rather paradox situation in Perl, while push is prototyped (\@@) to work internally with an array_ref, the parser doesn't accept references ... that means I have to explicitly prepend a @ to every ref to make commands like push work... hmm not very handy...

  • There is a possibility to overwrite CORE::push such that it gets a new prototype allowing scalars. But this would not only disable checking at compilation time, it would reasonably slow down any push operation at all arrays ...

  • Another approach would be to use something like autobox and to always have objects right from the beginning and to write $employees_ar->push() !

    But that's

    a) not very perlish and

    b) not faster than overwriting CORE::push (I think even much slower)

    But this shows the benefit of everything is an object that other languages have!

  • Conclusion

    There doesn't seem to be a good solution in plain Perl to extend a data structure and avoiding

  • refactoring
  • universally slowing down operations (like push for all arrays)
  • leading to massive use of extra sigils and (de)referencing syntax.
  • being rather complicated and totally confusing for newbies...

    Especially the last point is important, a JS user has only to learn how to add new methods to an object constructed from Array() without having to fiddle around with

  • sigils syntax
  • (de)referencing sytax,
  • Tie:: and
  • CORE::

    And even most experienced proggers wouldn't do any of this and start to refactor the whole array code into employees objects!

  • Utopia

    The only way I can think of to elegantly solve this situation and to stay compatible to the perl culture is to extend the number of sigils or twigils in future perl versions.

    If we had something like €employees or  $@employees noting scalars which have to hold an array reference, then the parser could be extended to always accept this reference where an array is wanted!

    I.e. if the prototype of a function explicitly asks for an array, like with push @array,"elem", then push €array_ref,"name" should also work.

    Now tieing €array_ref would solve our 2nd phase problem.

    And blessing would allow to call methods like €employees->list_actives() for our 3rd phase problem.

    All this without complicating the syntax, refactorings or slowing down operations.

    (Of course it would be nicer if tieing and blessing of primitives could be unified into one interface like the one showed in autobox ... please note: JS has internally primitives, only the interface is OO)

    Further meditation

    Sigils are a wonderful invention in Perl to immediately show the type of a variable, also for compile time checking and naming convention!

    But unfortunately in most cases of longer programs - e.g when passing around or when nesting structures - proggers are rather quickly forced to use references, which all have the $-sigil.

    Like this the implicit naming convention of @ gets lost, which also leads to workarounds like appending something like _aref to the variable name...(see PBP)

    Consequently extending the sigil system to all known ref types would facilitate many situations without braking old code.

    Cheers Rolf

    Footnotes:

    ¹) of course it's a stupid design decision to use the family name as a key ... it's just an example, think abstract! :) UPDATE: ARGH and even more stupid is talk about a string key when using an Array (I was tired) ... thanks to BrowserUK for pointing this to me! :) ²) the object model in JS is different, just think something like "class" or "package" when I say "constructor".

    In reply to Benefits of everything is an object? Or new sigils? by LanX

    Title:
    Use:  <p> text here (a paragraph) </p>
    and:  <code> code here </code>
    to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.