Can overloaded '+' return an array? If so, how?

Discussion in 'Perl Misc' started by PeterSShenkin, Aug 30, 2006.

  1. The following sample code prints:

    combine: result= [1 2 3 4]
    main: ar = [4]

    I expect it to print:

    combine: result= [1 2 3 4]
    main: ar = [1 2 3 4]

    The issue is that "combine", which is the function that '+' maps to,
    returns an array. When, in the main program, I say:

    my @ar = $ca1 + ca2

    I expect the "combine" function to be called in list context. But
    evidently it is called in scalar context, because my @ar variable
    receives the cardinality of the "result" array, rather than a copy of
    the array.

    Looking at Ch 13 of the Camel book, I don't see any restriction on
    return values of overloaded operators; but maybe I'm just missing it.
    If there's a way to do it, but I'm doing it wrong, I'd like to know
    that. Either way, please advise.

    (If, instead of what I do in the example, I return a reference to the
    array, and alter my main routine correspondingly, then, of course,
    everything works.)

    Thanks,
    -P.

    Example:

    ====================
    use strict;

    my $ca1 = ClassAct->new( 1, 3 );
    my $ca2 = ClassAct->new( 2, 4 );

    my @ar = $ca1 + $ca2;
    print "main: ar = [@ar]\n";

    {
    package ClassAct;

    use overload (
    '+' => "combine",
    fallback => 1,
    );

    sub combine {
    my $obj1 = shift;
    my $obj2 = shift;
    my @result = sort ( @{$obj1}, @{$obj2} );
    print "combine: result= [@result]\n";
    return @result;
    };

    sub new {
    my $class = shift;
    my $self = [
    ];
    while( my $value = shift ) {
    push @{$self}, $value;
    }
    bless $self, $class;
    return $self;
    }
    }
    ====================
    PeterSShenkin, Aug 30, 2006
    #1
    1. Advertising

  2. [A complimentary Cc of this posting was sent to
    PeterSShenkin
    <>], who wrote in article <>:
    > The issue is that "combine", which is the function that '+' maps to,
    > returns an array. When, in the main program, I say:
    >
    > my @ar = $ca1 + ca2
    >
    > I expect the "combine" function to be called in list context.


    Some hints: you forgot about cryptocontext. What would you think

    myMultiplyArgs($ca1 + $ca2, $ca3 + $ca4, $ca5 + $ca6)

    would return if your semantic would hold?

    Overloading changes IMPLEMENTATION of operations; the SEMANTIC returns
    the same.

    > (If, instead of what I do in the example, I return a reference to the
    > array, and alter my main routine correspondingly, then, of course,
    > everything works.)


    Enjoy it. ;-)

    Hope this helps,
    Ilya
    Ilya Zakharevich, Aug 30, 2006
    #2
    1. Advertising

  3. PeterSShenkin

    Guest

    "PeterSShenkin" <> wrote:
    > The following sample code prints:
    >
    > combine: result= [1 2 3 4]
    > main: ar = [4]
    >
    > I expect it to print:
    >
    > combine: result= [1 2 3 4]
    > main: ar = [1 2 3 4]
    >
    > The issue is that "combine", which is the function that '+' maps to,
    > returns an array. When, in the main program, I say:
    >
    > my @ar = $ca1 + ca2
    >
    > I expect the "combine" function to be called in list context. But
    > evidently it is called in scalar context, because my @ar variable
    > receives the cardinality of the "result" array, rather than a copy of
    > the array.
    >
    > Looking at Ch 13 of the Camel book, I don't see any restriction on
    > return values of overloaded operators; but maybe I'm just missing it.
    >
    > If there's a way to do it, but I'm doing it wrong, I'd like to know
    > that. Either way, please advise.



    Your understanding seems to be correct (all overloaded operators are
    called in scalar context), and you seem to be correct that this is not
    well documented. The closest thing to it seems to be, under overload's
    section on <> operator:

    BUGS Even in list context, the iterator is currently called
    only once and with scalar context.

    (This fact seems to be true for all operators, but apparently is only
    considered to be a bug for the <> operator.)

    > (If, instead of what I do in the example, I return a reference to the
    > array, and alter my main routine correspondingly, then, of course,
    > everything works.)


    Yep. And, in fact, I would usually expect an overloaded addition
    operator to turn something of the same class as (at least one of) it's
    operands, so I suggest that not only should it return a ref, but a ref
    that is blessed into ClassAct.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Aug 30, 2006
    #3
  4. wrote:

    > Yep. And, in fact, I would usually expect an overloaded addition
    > operator to turn something of the same class as (at least one of) it's
    > operands, so I suggest that not only should it return a ref, but a ref
    > that is blessed into ClassAct.


    That expectation is not fulfilled either in mathematics or in Perl
    native types.

    In Perl, an int divided by an int is not necessarily an int.

    In mathematics, the dot product of two vectors is a scalar. The outer
    product is a matrix.

    Thus, if the inability of an overloaded '+' to always return a scalar
    was a conscious decision, I believe it was the wrong one. What if you
    want to add two arrays?

    Be all this as it may, my thanks to those who responded. I guessed
    this is the way it would turn out, because I couldn't see anything I
    was doing wrong. I'll have to add it to my list of Perl sins (along
    with the inability to handle IEEE exceptional values in a standard
    way).

    Cheers,
    -P.
    PeterSShenkin, Aug 30, 2006
    #4
  5. PeterSShenkin wrote:
    > Thus, if the inability of an overloaded '+' to always return a scalar
    > was a conscious decision, I believe it was the wrong one. What if you
    > want to add two arrays?


    Whoops.... of course I meant "to only return a scalar...."

    -P.
    PeterSShenkin, Aug 30, 2006
    #5
  6. PeterSShenkin wrote:
    > PeterSShenkin wrote:
    > > Thus, if the inability of an overloaded '+' to always return a scalar
    > > was a conscious decision, I believe it was the wrong one. What if you
    > > want to add two arrays?

    >
    > Whoops.... of course I meant "to only return a scalar...."



    Whoops.. sigh. "if the inability of an overloaded '+' to return
    anything but
    a scalar was a conscious decision, I believe it was the wrong one."

    I'll shut up now. :)

    -P.
    PeterSShenkin, Aug 30, 2006
    #6
  7. PeterSShenkin

    Guest

    PeterSShenkin wrote:
    >
    > The issue is that "combine", which is the function that '+' maps to,
    > returns an array. When, in the main program, I say:
    >
    > my @ar = $ca1 + ca2
    >
    > I expect the "combine" function to be called in list context. But
    > evidently it is called in scalar context, because my @ar variable
    > receives the cardinality of the "result" array, rather than a copy of
    > the array.
    >
    > ...
    >
    > (If, instead of what I do in the example, I return a reference to the
    > array, and alter my main routine correspondingly, then, of course,
    > everything works.)



    I fiddled around with your test code, and I found that, while the
    code:

    my @ar = $ca1 + ca2;

    is not called in list context, the following three functionally
    equivalent lines:

    my @ar = $ca1->combine($ca2);
    my @ar = combine $ca1 $ca2;
    my @ar = ClassAct::combine($ca1, $ca2);

    do return an array as you want -- without the need to change the
    combine() method.

    (I don't know if this information is useful to you or not, but I
    thought I'd share it anyway).

    -- Jean-Luc

    --
    perl -le "print(pack'B*','0'.unpack'B*',pack'w*',
    5592691776,37562575106519616,25926642752,354130435682904)"
    , Aug 30, 2006
    #7
  8. wrote:
    > I fiddled around with your test code, and I found that, while the
    > code:
    >
    > my @ar = $ca1 + ca2;
    >
    > is not called in list context, the following three functionally
    > equivalent lines:
    >
    > my @ar = $ca1->combine($ca2);
    > my @ar = combine $ca1 $ca2;
    > my @ar = ClassAct::combine($ca1, $ca2);
    >
    > do return an array as you want -- without the need to change the
    > combine() method.


    I do find that both interesting and useful.

    Thanks,
    -P.
    PeterSShenkin, Aug 31, 2006
    #8
  9. PeterSShenkin

    Guest

    "PeterSShenkin" <> wrote:
    > wrote:
    >
    > > Yep. And, in fact, I would usually expect an overloaded addition
    > > operator to turn something of the same class as (at least one of) it's
    > > operands, so I suggest that not only should it return a ref, but a ref
    > > that is blessed into ClassAct.

    >
    > That expectation is not fulfilled either in mathematics or in Perl
    > native types.
    >
    > In Perl, an int divided by an int is not necessarily an int.


    division is not addition.

    >
    > In mathematics, the dot product of two vectors is a scalar. The outer
    > product is a matrix.


    multiplication is not addition.

    >
    > Thus, if the inability of an overloaded '+' to always return a scalar
    > was a conscious decision, I believe it was the wrong one. What if you
    > want to add two arrays?


    Then you take two arrayrefs (or object) and return an arrayref (or object).
    Or are you going to say it is also a mistake that overloaded + always takes
    its *arguments* in a scalar context, too?

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Aug 31, 2006
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Greenhorn
    Replies:
    15
    Views:
    811
    Keith Thompson
    Mar 6, 2005
  2. benben
    Replies:
    17
    Views:
    566
  3. Grizlyk
    Replies:
    10
    Views:
    746
    bjarne
    Dec 22, 2006
  4. hemantdesai
    Replies:
    0
    Views:
    324
    hemantdesai
    Jan 28, 2008
  5. Replies:
    1
    Views:
    104
    Ken-Yi Lee
    Feb 2, 2014
Loading...

Share This Page