Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re^6: Order of evaluation/interpolation of references (UPDATED)

by BrowserUk (Patriarch)
on Mar 08, 2012 at 02:16 UTC ( [id://958398]=note: print w/replies, xml ) Need Help??


in reply to Re^5: Order of evaluation/interpolation of references (op order)
in thread Order of evaluation/interpolation of references

The problem with this pseudo-code:

${ X() } . ${ X() } concat( deref( X() ), deref( X() ), )

is that it means that concat() copies both it arguments -- rather than a copy of the second being appended to the first -- otherwise it would modified the referenced var.

Which means that here:

${ X() } . ' ' . ${ X() } concat( concat( deref( X() ), ' ', ), deref( X() ), )

The deref'd value and the space are copied once to put them together, and then the whole thing is copied again in the second concat().

That is not an optimisation.

If the sequences were:

${ X() } . ${ X() } concat( new( deref( X() ) ), deref( X() ), )
${ X() } . ' ' . ${ X() } concat( concat( new( deref( X() ) ), ' ', ), deref( X() ), )

Ie. concat() appends it second argument to its first (as in sv_catsv()) and new() return a copy of its argument (as in newSVsv()), the each part of the final string is only copied once (subject to the need for reallocs which will be unnecessary for two or three short strings because of allocation (alignment) minimums), and it would be more efficient.

It would also prevent the bug from manifesting itself.

Update: Maybe this will clarify things; or not:

use strict; use warnings; use feature qw( say ); package ike; { sub concat { $_[0] . $_[1] } sub deref :lvalue { ${ $_[0] } } my $a = \ '1'; my $b = \ '2'; say concat( deref( $a ), deref( $b ), ); say $$a; say <<'EOS'; Note: $$a has not changed, So, $$a was copied to produce the concatena +tion 1 + 1 = 2 bytes copied. EOS say concat( concat( deref( $a ), ' ', ), deref( $b ), ); say <<'EOS'; Note: $$a has not changed, So, $$a was copied to produce the concatena +tion Therefore, the whole of that result was copied (again) to produce the result of the second concatenation. ( 1 + 1 ) * 2 + 1 = 5 bytes copied. EOS } package buk; { sub concat { $_[0] .= $_[1] } sub deref { ${ $_[0] } } sub new{ "$_[0]" } my $a = \ '1'; my $b = \ '2'; say concat( concat( new( deref( $a ) ), ' ', ), deref( $b ), ); say <<'EOS'; New copies 1 byte its arg into a new string The first concat() copes the space and apend it to the new string. The second concat() copies 1 byte from $b and apend it to that. 1 + 1 + 1 = 3 bytes copied. EOS } __END__ C:\test>junk999 12 1 Note: $$a has not changed, So, $$a was copied to produce the concatena +tion 1 + 1 = 2 bytes copied. 1 2 Note: $$a has not changed, So, $$a was copied to produce the concatena +tion Therefore, the whole of that result was copied (again) to produce the result of the second concatenation. ( 1 + 1 ) * 2 + 1 = 5 bytes copied. 1 2 New copies 1 byte its arg into a new string The first concat() copes the space and apend it to the new string. The second concat() copies 1 byte from $b and apend it to that. 1 + 1 + 1 = 3 bytes copied.

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

The start of some sanity?

Replies are listed 'Best First'.
Re^7: Order of evaluation/interpolation of references (op order)
by ikegami (Patriarch) on Mar 08, 2012 at 02:35 UTC

    That is not an optimisation.

    Who said anything about optimisation?

    It would also prevent the bug from manifesting itself.

    What bug?

    If the sequences were:

    Sure, but that's not what the OP wrote.

    Or are you suggesting that making a copy of the non-last operand of every operator is somehow a good idea?

      Or are you suggesting that making a copy of the non-last operand of every operator is somehow a good idea?

      Sorry, but that makes no sense in relation to what I posted.

      I'm not going to explain it again, so either re-read it more carefully, or just forget it.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

      The start of some sanity?

        Sorry, but that makes no sense in relation to what I posted.

        That's why I asked what you considered to be a bug. My guess: The lack of copying by operators causes other operators to behave differently than you'd expect.

        If you deliberately hide information, you only have yourself to blame for any ensuing confusion.

Re: Optimising concat (was Order of evaluation/interpolation of references)
by ikegami (Patriarch) on Mar 09, 2012 at 02:29 UTC

    Reguarding the update, I believe you're suggesting it would be more efficient to implement

    $a.$b.$c.$d

    as

    concat_assign( concat_assign( concat_assign( copy($a), $b ), $c, ), $d )

    rather than how it's actually implemented. However, I believe it's being implemented as the following, which is practically the same (ever so slightly better):

    concat_assign( concat_assign( concat( $a, $b ), $c, ), $d )

    I believe that's what's causing the "S" to appear in concat's flags.

    $ perl -MO=Concise,-exec -e'$a.$b.$c.$d' 1 <0> enter 2 <;> nextstate(main 1 -e:1) v:{ 3 <#> gvsv[*a] s 4 <#> gvsv[*b] s 5 <2> concat[t3] sK/2 6 <#> gvsv[*c] s 7 <2> concat[t5] sKS/2 8 <#> gvsv[*d] s 9 <2> concat[t7] vKS/2 a <@> leave[1 ref] vKP/REFC -e syntax OK

    But the problem with both of the approaches is that enlarging the string buffer requires copying it (at least on this Debian machine), so the "buk" and current version is usually more expensive (6 bytes rather than 3) than the naïve one I had posted.

    A string buffer is only given 4 extra bytes when it's grown, which is pityful. (In comparison, arrays are given N+4 extra elements!) Aside from adding more padding, one could convert concat into an N-ary operator rather than a binary operator.

    sub concat_list :lvalue { my $tot_len; $tot_len += length($_) for @_; my $buf = ''; # Allocate $tot_len bytes. $buf .= $_ for @_; $buf }
      Reguarding the update,

      Thankyou for re-reading. The update is just a re-iteration of the original content.

      On my 64-bit system, minimum allocations are 8 bytes. (64-bit alignment).


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

      The start of some sanity?

        It just occurred to me that using a list concat would cause the OP's

        print "${X()} ${X()}\n";

        to behave the same as his

        print "${X()}${X()}\n";

        Faster AND fewer surprises :) (Or is it su-prises?)

        Of course, the OP will still be surprised by the difference in

        $ perl -E'my $x=5; sub X { \(++$x) } say ${ X() } + ${ X() };' 14 $ perl -E'my $x=5; sub X { \(++$x) } say ${ X() } + 0 + ${ X() };' 13
        Poor choice of words on my part. I meant "Guessing from the update".

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://958398]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (5)
As of 2024-04-24 08:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found