Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

A pair of "mathematical" attributes for arrays?

by blazar (Canon)
on Sep 10, 2007 at 09:56 UTC ( [id://638020]=perlmeditation: print w/replies, xml ) Need Help??

There have been some posts lately, inspired by Project Euler's problems. I also play with PE, although on a sparse basis and having joined much late.

In a particular problem it turned out to be of much use Perl's ability to return undef when accessing an array element beyond its actual length, and the promotion of undef to zero in a numeric addition. Except that it triggers the well know warning, in which case the usual cure is to locally disable it. (Since the actual script body was 14 lines, I eventually committed for once the sin of commenting out the use warnings; line altogether.)

Of course I may have used a (IMHO) visually obtrusive ||0 instead...

The point is, in this case the intended usage is more in line with common mathematical one, especially as in combinatorics. As an example consider the following minimal implementation of a program to print the first ten rows of Pascal's triangle:

#!/usr/bin/perl -l use strict; # use warnings; my @row; while ($row[1]<10) { @row=(1, map $row[$_-1]+$row[$_], 1..@row); print "@row"; } __END__

If I enable warnings I'll get two for the comparison for the first two iterations and one for the addition per each row.

So I wonder if one day a predefined attribute may be specified on an array so that accessing it beyond its limits would return 0 rather than undef. Perhaps something like

my @row :zero;

Also, Perl's current behaviour with negative indices is occasionally practical but also not best suited for some mathematical-like usages. So still in the brainstorming vein as above, perhaps another attribute should exist, say :nocirc, to the effect of returning undef (or 0 if in conjunction with :zero) when accessing negative indices. Thus the code above may become the clearer - for the mathematically inclined:

my @row :zero :nocirc; while ($row[1]<10) { @row=map $row[$_-1]+$row[$_], 0..@row; print "@row"; }

Admittedly, this is not Perl's everyday job. Still it may be useful. I would add this to ysth's 5.12 wishlist.

Replies are listed 'Best First'.
Re: A pair of "mathematical" attributes for arrays?
by moritz (Cardinal) on Sep 10, 2007 at 11:04 UTC
    I quite like these suggestions, especially the first one with :zero.

    I think that generally a better control over warnings is desirable.

    For example if I test if a string has some content I check for defined $str && length $str. It feels clumsy, but a simple $str returns false if the string is "0", and a length $str warns if $str is undef.

    In these cases I would want to disable some warnings specifically for a few builtins.

    no warnings uninitialized => ['length', 'eq']; would be the p5ish way to express this.

Re: A pair of "mathematical" attributes for arrays?
by Jenda (Abbot) on Sep 10, 2007 at 11:06 UTC

    I have yet to encounter a case when would the uninitialized warning actually help. So I'd suggest using

    use warnings; no warnings 'uninitialized';

    it might be helpfull though to be able to specify the default value for the item in arrays and hashes though. In some specific cases. What would be necessary though to treat the stuff in the attribute as a block, not evaluate it to an expression. Consider this:

    my @row :default([]); # or my @other :default(new Foo::Bar());
    You wouldn't want the default value to be the same arrayref/object, right?

    The :nocirc could be handy.

      What would be necessary though to treat the stuff in the attribute as a block, not evaluate it to an expression.

      You could fix that by supplying an anonymous subroutine as the argument. That way, if someone really wanted it to be the same, it would be the same. The attribute would work exactly like other subroutines that take default values. Of course, there is no such thing as attribute arguments today (only "annotations"), but maybe some day in the future.

      lodin

Re: A pair of "mathematical" attributes for arrays?
by jettero (Monsignor) on Sep 10, 2007 at 11:06 UTC

    You could get array FETCH()es that did precisely what you want by using Tie::Array. In fact, if you used @ISA = ('Tie::StdArray'), it wouldn't even be very much work — I mean for this idea to help with changing the behavior of a negative index operation.

    -Paul

Re: A pair of "mathematical" attributes for arrays?
by TGI (Parson) on Sep 10, 2007 at 16:33 UTC

    Interesting ideas. I think that instead of :zero, I'd like something more flexible:

    my @foo :autovalue(0); my @bar :autovalue(23); print "$foo[3]\n"; # prints 0 print "$bar[3]\n"; # prints 23

    Obviously a while (@bar) would run until all memory was exhausted, so care would need to be exercised with the use of this attribute.

    I like the :nocirc suggestion, but the name doesn't make much sense to me. How about :posindex?

    Update: Thanks to moritz for calling me on my lack of caffeine induced foolishness. Now, more awake, I stand by the rest of what I wrote.


    TGI says moo

      Obviously a while (@bar) would run until all memory was exhausted

      Why should it? An empty array with non-zero default values would still be false, right?

        Oops. I somehow convinced myself that while works for array iteration something like it does with a filehandle.

        Array iterators (each, foreach, etc) should only deal with existing indexes. An empty array should be false.


        TGI says moo

      I like the :nocirc suggestion, but the name doesn't make much sense to me. How about :posindex?

      Well, I find it better than mine, but unsatisfactory too. I just couldn't concoct anything better: I wanted something short enough to be practical and I was thinking about "no circularity", but of course it's at best imprecise and more realistically patently wrong. OTOH yours gives me an impression of "positive indices only" which is not the case either. It's a matter of disabling a feature related to negative indices instead, for which I cannot think of a short enough description. But then you'll agree that it's a minor point anyway.

      Update: (just not to clutter the thread with yet another reply) yes, TGI, I like all of your suggestions. Of course they are all as far away from reality as a more thorough coverage and a better implementation of attributes and a wider adoption of them.

        My first though was along the lines of :nonegindex. But that's long and unwieldy. What about something with an argument:

        # $foo[-1] returns 'Illegal Array Index Error' @foo :negindex( value => 'Illegal Array Index Error' ); # $foo[-1] normal behavior @foo :negindex( REVERSE ); # $foo[-1] apply some filter ( filter takes array, index as args) @foo :negindex( filter => sub { return -1 * $_[0]->[ abs( $_[1]) ] } ) +; # $foo[-1] returns undef, exists( $foo[-1] ) is false. #@foo :negindex( DO_NOT_WANT ); @foo :negindex( NO_EXIST ); # And to anticipate all future feature creep: # $foo[-1] returns sends an email message @foo :negindex( email => bob@example.com );


        TGI says moo

Re: A pair of "mathematical" attributes for arrays?
by tsee (Curate) on Sep 11, 2007 at 09:48 UTC

    I'm not suggesting that you actually use this, but the following is a simple implementation of the :zero (here :ZeroDefault) attribute. It's intended to show you that what you would like to have is quite easy to implement in pure Perl without changing the interpreter at all or writing a single line of XS/C. All the usual attribute-gotchas apply. All the usual tie() gotchas apply, too. (Slowness, for example.)

    #!/usr/bin/perl use 5.006; use strict; use warnings; package Attribute::Array::Zeroes; use Tie::Array; use base 'Tie::StdArray'; use Attribute::Handlers autotie => { '__CALLER__::ZeroDefault' => 'Attribute::Array::Zeroes' }; sub FETCH { my $return = $_[0]->[$_[1]]; return 0 if not defined $return; $return; } package main; #use Attribute::Array::Zeroes; my @x : ZeroDefault; print "This is zero, not undef: $x[4]\n"; $x[5] = 1; print "This, too: $x[0] and even this: $x[6]. This isn't: $x[5]\n";

    Of course, this is just a hack and I haven't tested it thoroughly.

    Cheers,
    Steffen

Re: A pair of "mathematical" attributes for arrays?
by Prof Vince (Friar) on Sep 11, 2007 at 08:32 UTC
    Adding an attribute for something that specific (I doubt anyone but PE players would use it) really sounds like unneeded bloat. Especially when you can use a sub that hides your hated || 0 or, as jettero said, when you can already use a tied array.
      Adding an attribute for something that specific (I doubt anyone but PE players would use it) really sounds like unneeded bloat.

      That is not the point. Perl's realm lies in pragmatics and certainly not only PE players could be interested in such a thing as you can judge from the feedback from other people who replied to my root node. The feature would be useful in some situations like the one I described, e.g. with mathematical usages: of course Perl is not the most typical language in that case but again it's practical and there's no reason why it shouldn't be used in that area too.

      Indeed the feature I long for has not been there for ages and people could happily live without it so it's not strictly necessary. Still I fail to see how could it be "bloat": you would only use it if needed and otherwise happily ignore it or even ignore its existence altogether.

      Especially when you can use a sub that hides your hated || 0 or, as jettero said, when you can already use a tied array.

      Except that hinding the thing in a sub would not make the syntax terribly more elegant and sub call in Perl is terribly slow anyway: for mathematical usages (and not only) this may matter. Granted, if one is terribly concerned about speed then she should go with another language altogether, but Perl is still useful for fast prototyping, and making the beast unnecessarily slow is what I see as "bloat". Thus you can:

      • go fast with tricks and inelegant, clumsy syntax;
      • go slower with a trick like the sub and a cleaner, more intuitive syntax;

      The same can be said of jettero's tied arrays, the suggestion of which I reckon to be more a proof of concept than a "use this instead", thus anyway you look at this there's no reason not to desire a beast that would give you the best of both points above in one shot. This is not to say that my suggestion will be readily implemented just because I said that... I was and I still am talking in line of principle.

      Attributes are a recent addition to Perl and their support is largely incomplete, but they are a powerful means. The point is I stumbled into a situation in which any solution with current syntax and semantics left you with a slight flavour of dissatisfaction in your mouth. Admittedly, in my experience that is not a common situation and I do not expect it to be, but it can happen. Making what's practical even more practical and what's good even better is certainly worth.

        Still I fail to see how could it be "bloat": you would only use it if needed and otherwise happily ignore it or even ignore its existence altogether.
        The point of TIMTOWTDI is to offer different sensible ways to achieve the same goal. I fail to see how your proposition offers something that can be generally used. If we were to add every little feature X or Y dream of, Perl would be called PHP.
        Except that hinding the thing in a sub would not make the syntax terribly more elegant...
        That's just personal taste, but I yet again fail to see how could it not be clearer, since you trade $a[$_] || 0 for a($_). And if you like to think in "mathematical" terms, a sub is much closer to a sequence than an array.
        Perl is still useful for fast prototyping, and making the beast unnecessarily slow is what I see as "bloat"
        If you're so concerned about speed, you shouldn't use Perl arrays to begin with, since they are very wasteful on space. Either make your own "sequence" data structure in XS or use a module that already exists (maybe PDL ?).

        But that's definitely not something everyone would need shipped with his perl.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://638020]
Approved by Corion
Front-paged by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2024-04-24 20:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found