Re: Precedence: assignment vs smartmatch? (Now--with square brackets... .)

Thank you, Brad. I think I've got it (let me know if below is incorrect):

#### pseudocode:
1. eval(LHS --> $_)
2. eval($_ ~~  RHS)
3. overwrites(LHS <-- Step#2), except for S/// and TR///

[ When I first learned the "~~" smartmatch operator, I only thought it
was for testing (e.g. with rx/// and m/// ). I thought it only
returned TRUE/FALSE. But now I've gained a better understanding that
s/// and S/// and tr/// and TR/// also work. As an aside, the
ACCEPTS() notation is quite clear, while the smartmatch notation
reminds me a little bit of 'gazinta' math:
https://www.collinsdictionary.com/us/submission/18703/gazinta ]

New question: Is there an explanation in the docs for the behavior I
see below using square brackets instead of parentheses? It seems that
square brackets in the "abc" series below gives a different result
than parentheses, suggesting a different precedence level:

mbook:~ homedir$ perl6
To exit type 'exit' or '^D'
>
> my $a =3D Q[<i>abc</i>]
<i>abc</i>
> [my $b =3D $a ] ~~ s/ <[cba]>+ // ;
=EF=BD=A2abc=EF=BD=A3
> say $/; say $_; say $a; say $b;
=EF=BD=A2abc=EF=BD=A3
(Any)
<i>abc</i>
<i>abc</i>
>
> my $x =3D Q[<b>xyz</b>]
<b>xyz</b>
> my $y =3D [ $x  ~~ s/ <[zyx]>+ // ];
[=EF=BD=A2xyz=EF=BD=A3]
> say $/; say $_; say $x; say $y;
=EF=BD=A2xyz=EF=BD=A3
(Any)
<b></b>
[=EF=BD=A2xyz=EF=BD=A3]
>
> say $*VM
moar (2019.07.1)

Best Regards, Bill.



On Mon, Dec 9, 2019 at 6:04 PM Brad Gilbert <b2gills@gmail.com> wrote:
>
> I meant that $_ is set to the left value while the right value is being e=
valuated, and also while .ACCEPTS is called.
>
>     LEFT ~~ RIGHT
>
> (Where LEFT and RIGHT represent some expression to be executed during run=
time.)
>
> Imagine that underneath the hood, something like this is happening:
>
>     my $L-value =3D LEFT.evaluate();
>
>     given $L-value {
>         # $_ is temporarily the result of the LEFT expression
>
>         my $R-value =3D RIGHT.evaluate();
>         return $R-value.ACCEPTS($L-value);
>     }
>
> So this:
>
>     =C2=AB a b c =C2=BB.join()   ~~   S/b/y/
>
> is functionally the same as:
>
>     do given =C2=AB a b c =C2=BB.join() {
>         my $R-value =3D S/b/y/;
>         $R-value.ACCEPTS($_)
>     }
>
> Note that $R-value will be "ayc"
>
>     "ayc".ACCEPTS("abc") =3D=3D False
>
> ---
>
>     > $_.say
>     (Any)
>
>     > =C2=AB a b c =C2=BB.join()   ~~   -> $a { say "\$a =3D $a\n\$_ =3D =
$_" }
>     $a =3D abc
>     $_ =3D abc
>
>
>     > =C2=AB a b c =C2=BB.join()   ~~   ($_.say, -> $a { say "\$a =3D $a\=
n\$_ =3D $_" }).tail
>     abc
>     $a =3D abc
>     $_ =3D abc
>
>     > $_.say
>     (Any)
>
>
> On Mon, Dec 9, 2019 at 7:34 PM William Michels <wjm1@caa.columbia.edu> wr=
ote:
>>
>> Thank you Brad, for your in-depth reply.
>>
>> There are parts of your reply that make perfect sense to me, and also
>> parts where I am still confused. I feel I understand your first three
>> examples (1,2,3) explaining how the smartmatch operator relates to
>> ACCEPTS(). However in the second three examples explaining "S///"
>> (also numbered 1,2,3), I'm confused on Your Step 2. I've tried
>> numerous examples, a few of which are reproduced below:
>>
>> mbook:~ homedir$ perl6
>> To exit type 'exit' or '^D'
>> 1> my $a =3D =C2=AB a b c =C2=BB.join()
>> abc
>> 2> say $a ~~ s/b/y/
>> =EF=BD=A2b=EF=BD=A3
>> 3> say $a
>> ayc
>> 4> my $probe =3D "AGCT"
>> AGCT
>> 5 > say $/ if $probe ~~ /"TCGA"/ ;
>> ()
>> 6> say $/ if $probe ~~ /"AGCT"/ ;
>> =EF=BD=A2AGCT=EF=BD=A3
>> 7> say $/ if $probe ~~ s/"AGCT"/"TCGA"/ ;
>> =EF=BD=A2AGCT=EF=BD=A3
>> 8> say $probe
>> "TCGA"
>> 9> say $/ if $probe ~~ S/"TCGA"/"AGCT"/ ;
>> Potential difficulties:
>>     Smartmatch with S/// is not useful. You can use given instead:
>> S/// given $foo
>>     ------> say $/ if $probe ~~ S/"TCGA"/"AGCT"/ ;
>> ()
>> 10> say $probe
>> "TCGA"
>> 11> say $_
>> abc
>> 12> $*VM
>> moar (2019.07.1)
>> >
>>
>> For "S///" in your Step 1 the LHS is evaluated first (your Join
>> example) and the LHS is temporarily set to $_. Then (your Step 2) the
>> RHS is evaluated. Do you mean the RHS is evaluated in the context of
>> $_ from the LHS?? Using your "abc" example I don't understand--if you
>> **solely** look at the "S/b/./" operation--how  the letters "a" and
>> "c" show up in your Step 2 intermediate result. Of course, Raku/Perl6
>> may be far cleverer than I imagined--clever enough based on position
>> and regex-rules (maybe) to simplify the two sides of the "S///"
>> operator into a simple formula that can then be applied to the LHS.
>>
>> So in pseudocode, are you saying the following regarding "s///"
>> (destructive-substitution) operation?
>>
>> 1. LHS:
>> eval( "probe" ) --> $_ ;
>>
>> 2. RHS regex "target" between first two solidi of s/// or S/// :
>> eval( "target".ACCEPTS( $_) );
>>
>> 3. for s///, if above evaluates to TRUE match from above gets assigned
>> to $/ and LHS "probe" gets overwritten with appropriate "substitution"
>> characters between second two solidi of s/// or S/// :
>> ( "match" --> $/ ) ; ( RHS_"substitution" --> "probe" ) ;
>>
>> [ 4. for S///, there is no possibility that Step 2 will evaluate to
>> TRUE, so $/ is Nil and LHS "probe" remains as unchanged ].
>>
>> If I'm close, please let me know. Meanwhile I will: 1) read over what
>> you wrote again, and 2) play around with a little more example code,
>> to gain a better understanding of what Raku/Perl6 is doing
>> under-the-hood.
>>
>> Best Regards, Bill.
>>
>>
>>
>> On Sun, Dec 8, 2019 at 12:42 PM Brad Gilbert <b2gills@gmail.com> wrote:
>> >
>> > smartmatch is among the most complex parts of the language.
>> >
>> > That complexity has to managed or it will be too complex to use effect=
ively.
>> >
>> > To that end, the rules and order of operations are never altered.
>> >
>> > 1. The left side is evaluated first, and the resulting value captured
>> >
>> >         > say('left') ~~ say('right')
>> >         left
>> >         right
>> >
>> > 2. $_ is temporarily set to that value, and the right side is executed
>> >
>> >         > 'ab' ~ 'c'   ~~ say($_)
>> >         abc
>> >
>> > 3. The result of that execution is matched against the left value
>> >
>> >         > 'abc' ~~ 'abb'.succ()
>> >         True
>> >
>> >     Specifically `.ACCEPTS` is called with the left value.
>> >     So the following two lines are roughly equivalent.
>> >
>> >         > 'abc'   ~~   'abb'.succ()
>> >         > 'abb'.succ().ACCEPTS('abc')
>> >
>> > So in the case of S/// and ~~ this is the order that things happen:
>> >
>> > 1. The left side is executed
>> >
>> >         =C2=AB a b c =C2=BB.join()  ~~  S/b/./
>> >
>> >         'abc' ~~ S/b/./
>> >
>> > 2. $_ is temporarily set to that value, and the right side is executed
>> >
>> >         'abc' ~~ S/b/./
>> >
>> >         'abc' ~~ 'a.c'
>> >
>> > 3. the result of the right side is matched against the left value
>> >
>> >         'abc' ~~ 'a.c'
>> >
>> >         'a.c'.ACCEPTS('abc') # False
>> >
>> > So basically if S/// changes the value, the result is False.
>> > If S/// doesn't change it, the result is True.
>> >
>> > Which means the following two lines are functionally identical.
>> >
>> >     'abc'   ~~  S/b/./
>> >     'abc'  !~~   /b/
>> >
>> > So the resulting value will never be the string you wanted!
>> > It will be True or False.
>> >
>> > ---
>> >
>> > The reason for the two stage execution is for the following.
>> >
>> >     'abc' ~~   .contains('b')
>> >     'abc' ~~ { .contains('b') }
>> >     'abc' ~~ m / b /
>> >     'abc' ~~ rx / b /
>> >
>> > Those four lines work basically the same, but for two different reason=
s.
>> >
>> > The first one works because $_ is set to the left value, and True.ACCE=
PTS() always returns True
>> >
>> > The second one works because CODE.ACCEPTS() always runs the code with =
the same parameter list.
>> >
>> > The third one works for the same reason as the first one
>> >
>> > The fourth one works for the same reason as the second one
>> >
>> > 1. Left side executed
>> >
>> >     'abc' ~~   .contains('b')
>> >     'abc' ~~ { .contains('b') }
>> >     'abc' ~~ m  / b /
>> >     'abc' ~~ rx / b /
>> >
>> > 2. Right side executed
>> >
>> >     'abc' ~~  True
>> >     'abc' ~~ { .contains('b') }
>> >     'abc' ~~ True
>> >     'abc' ~~ rx / b /
>> >
>> > 3. R-VALUE  .ACCEPTS( L-VALUE )
>> >
>> >     True.ACCEPTS('abc')
>> >     { .contains('b') }.ACCEPTS('abc')
>> >     True.ACCEPTS('abc')
>> >     rx / b /.ACCEPTS('abc')
>> >
>> > Note again that CODE.ACCEPTS(VALUE) is the same as CODE.(VALUE).
>> > (Note also that a regex is a code object.)
>> >
>> >     True.ACCEPTS('abc')
>> >     { .contains('b') }.('abc')
>> >     True.ACCEPTS('abc')
>> >     rx / b /.('abc')
>> >
>> > ---
>> >
>> > So then why does this work?
>> >
>> >     'abc' ~~ { S/b/./ }
>> >
>> > As I said CODE.ACCEPTS() always runs CODE with the same parameter list=
..
>> >
>> >     { S/b/./ }  .ACCEPTS( 'abc' )
>> >
>> >     { S/b/./ }  .( 'abc' )
>> >
>> > ---
>> >
>> > So why does the warning tell you to use `given` instead of what I just=
 wrote?
>> >
>> > The ~~ is intended mostly for resolving some sort of truthiness.
>> > So I just misused the feature for something it was not intended for.
>> >
>> > `given` is intended for temporarily setting $_, so it is the appropria=
te tool for the job.
>> >
>> >     S/b/./ given 'abc'
>> >
>> > If you don't like `given`, then just use `.subst()`
>> >
>> >     'abc'.subst( 'b', '.' )
>> >
>> > On Sun, Dec 8, 2019 at 1:32 AM William Michels <wjm1@caa.columbia.edu>=
 wrote:
>> >>
>> >> Apologies, looks like the smartmatch operator is listed in the
>> >> Operator Precedence table (15th row: under "Chaining infix"):
>> >>
>> >> https://docs.raku.org/language/operators#Assignment_operators
>> >>
>> >> However, am I correct in stating that the assignment operator ("=3D")=
 is
>> >> on the 19th row ("Item assignment")? Therefore in the absence of
>> >> parentheses, etc., all smartmatch operations take precedence over
>> >> assignment operations?
>> >>
>> >> Best Regards, Bill.
>> >>
>> >>
>> >> On Sat, Dec 7, 2019 at 10:27 PM William Michels <wjm1@caa.columbia.ed=
u> wrote:
>> >> >
>> >> > Wow Brad, that's interesting and informative.
>> >> >
>> >> > I haven't seen the S/// operator before, so I had to look it up. On
>> >> > the first page I found the docs say (quite informatively): "S/// us=
es
>> >> > the same semantics as the s/// operator, except it leaves the origi=
nal
>> >> > string intact and returns the resultant string instead of $/ ($/ st=
ill
>> >> > being set to the same values as with s///)."
>> >> >
>> >> > https://docs.raku.org/syntax/S$SOLIDUS$SOLIDUS$SOLIDUS
>> >> >
>> >> > I was then able to find an overview on regexes, which more explicit=
ly
>> >> > names the "S///" operator as "Non-disruptive substitution". I suppo=
se
>> >> > I could quibble and request that the phrase "Non-disruptive
>> >> > substitution" be added to the operator page (above), but no
>> >> > matter--it's easy enough to find:
>> >> >
>> >> > https://docs.raku.org/language/regexes#S///_non-destructive_substit=
ution
>> >> >
>> >> > So I think I understand that (as Brad has said): "smartmatch with S=
///
>> >> > (or TR///) is not useful." Conversely, I've also found another
>> >> > smartmatch construct that is useless (i.e. disallowed):
>> >> >
>> >> > > my $r =3D 'abc' ~~ { S/b/./ }
>> >> > a.c
>> >> > > my $s =3D 'abc' ~~ { s/b/./ }
>> >> > Cannot modify an immutable Str (abc)
>> >> >   in block <unit> at <unknown file> line 1
>> >> > >
>> >> >
>> >> > No matter how "discouraged' a particular syntax is, people are goin=
g
>> >> > to run into these disallowed syntaxes and wonder why. Could it be d=
ue
>> >> > to precedence? These two prohibited operations beg the question: ca=
n a
>> >> > definitive statement be made regarding the precedence of the
>> >> > smartmatch operator relative to either lowercase-triple-solidus
>> >> > operators such as s/// and tr/// , or relative to
>> >> > uppercase-triple-solidus operators such as S/// and TR/// ?
>> >> >
>> >> > This really makes me wonder if anyone has plans to add "~~" (the
>> >> > smartmatch operator) to the precedence table that can be found
>> >> > below--and where in the table the smartmatch operator would precise=
ly
>> >> > sit:
>> >> >
>> >> > https://docs.raku.org/language/operators#Operator_precedence
>> >> >
>> >> > Best Regards, Bill.
>> >> >
>> >> >
>> >> >
>> >> >
>> >> > On Sat, Dec 7, 2019 at 7:53 AM Brad Gilbert <b2gills@gmail.com> wro=
te:
>> >> > >
>> >> > > The return value of s/// is the same as $/
>> >> > >
>> >> > > If you want the resulting string instead you can use S/// instead=
..
>> >> > >
>> >> > >     > $_ =3D 'abc'
>> >> > >     > my $r =3D S/b/./
>> >> > >     > say $r
>> >> > >     a.c
>> >> > >
>> >> > > Note that it warns you try to use S/// with ~~
>> >> > >
>> >> > >     > my $r =3D 'abc' ~~ S/b/./
>> >> > >     Potential difficulties:
>> >> > >         Smartmatch with S/// is not useful. You can use given ins=
tead: S/// given $foo
>> >> > >         ------> my $r =3D 'abc' ~~ S/b/./
>> >> > >     False
>> >> > >
>> >> > > Which gives you an indicator of how to fix it
>> >> > >
>> >> > >     > my $r =3D S/b/./ given 'abc'
>> >> > >     a.c
>> >> > >
>> >> > > Note that the `given` happens before the `=3D`
>> >> > >
>> >> > > So it works the same as
>> >> > >
>> >> > >     > my $r =3D ( S/b/./ given 'abc' )
>> >> > >     a.c
>> >> > >
>> >> > > ---
>> >> > >
>> >> > > The reason ~~ doesn't work with S/// has to do with the dual pass=
 nature of ~~.
>> >> > >
>> >> > > Without getting into details, you can avoid that by delaying the =
S/// until the second pass.
>> >> > >
>> >> > >     > my $r =3D 'abc' ~~ { S/b/./ }
>> >> > >     a.c
>> >> > >
>> >> > > Or you can just set $_ to the value.
>> >> > > (Which is basically what the previous line is doing.)
>> >> > >
>> >> > >     > my $r =3D S/b/./ given 'abc'
>> >> > >
>> >> > >     > given 'abc' {
>> >> > >     >   my $r =3D S/b/./
>> >> > >     >   =E2=80=A6
>> >> > >     > }
>> >> > >
>> >> > >     > my $_ =3D 'abc'
>> >> > >     > my $r =3D S/b/./
>> >> > >
>> >> > >     > my $r =3D 'abc' ~~ -> $_ { S/b/./ }
>> >> > >
>> >> > >     > my $r =3D 'abc' ~~ sub ( $_ ) { S/b/./ }
>> >> > >
>> >> > >     > my $r =3D 'abc' ~~ anon sub foo ( $_ ) { S/b/./ }
>> >> > > ---
>> >> > >
>> >> > > One of design goals of Raku is to have as few special cases as po=
ssible.
>> >> > > Which is why ~~ and S/// haven't been made to just work.
>> >> > >
>> >> > > (It could be argued that in this case an exception could be made.=
 But I'm not going to argue for it.)
>> >> > >
>> >> > > On Fri, Dec 6, 2019 at 10:37 PM William Michels via perl6-users <=
perl6-users@perl.org> wrote:
>> >> > >>
>> >> > >> Hello All,
>> >> > >>
>> >> > >> Todd put up some interesting code yesterday using the Raku/Perl6=
 REPL,
>> >> > >> which I reproduced with no problem. Additionally I tried some
>> >> > >> variations removing and/or moving parentheses to a different loc=
ation,
>> >> > >> and have numbered the relevant REPL lines 1 through 6:
>> >> > >>
>> >> > >> mbook:~ homedir$ perl6
>> >> > >> To exit type 'exit' or '^D'
>> >> > >> 1> my $x =3D Q[word</b><br>] ;
>> >> > >> word</b><br>
>> >> > >> 2> (my $y =3D $x) ~~ s/ '<' .* //; say $/; say $x; say $y;
>> >> > >> =EF=BD=A2</b><br>=EF=BD=A3
>> >> > >> word</b><br>
>> >> > >> word
>> >> > >> 3> my $a =3D Q[word</b><br>] ;
>> >> > >> word</b><br>
>> >> > >> 4> my $b =3D ($a ~~ s/ '<' .* //); say $/; say $a; say $b;
>> >> > >> =EF=BD=A2</b><br>=EF=BD=A3
>> >> > >> word
>> >> > >> =EF=BD=A2</b><br>=EF=BD=A3
>> >> > >> > my $c =3D Q[word</b><br>] ;
>> >> > >> word</b><br>
>> >> > >> > my $d =3D $c ~~ s/ '<' .* //; say $/; say $c; say $d;
>> >> > >> =EF=BD=A2</b><br>=EF=BD=A3
>> >> > >> word
>> >> > >> =EF=BD=A2</b><br>=EF=BD=A3
>> >> > >> 7> $*VM
>> >> > >> moar (2019.07.1)
>> >> > >>
>> >> > >> Working in groups of 2, lines 1 and 2 replicate the code Todd pu=
t up
>> >> > >> (parenthesis surrounding everything to the left of the smartmatc=
h
>> >> > >> operator). I get the same result as Todd. What interests me are =
lines
>> >> > >> 3 through 6. Lines 3 and 4 are the virtually the same code but w=
ith
>> >> > >> parentheses surrounding everything to the right hand side (RHS) =
of the
>> >> > >> assignment operator (" =3D "). As people will note, lines 2 and =
lines 4
>> >> > >> give different results. Removing parentheses entirely in line 6 =
gives
>> >> > >> the same result as in line 4. Because the results in line 4 and =
line 6
>> >> > >> are the same, this says that as far as parentheses are concerned=
, the
>> >> > >> smartmatch operator "~~" takes precedence over the assignment op=
erator
>> >> > >> "=3D".
>> >> > >>
>> >> > >> What's not clear to me in the code above (lines 4 and 6) is why
>> >> > >> variables $b and $d get assigned to $/. I would have expected in=
 line
>> >> > >> 4 that $a would have been matched against the smartmatch, and th=
e
>> >> > >> result ("word") would have been simply copied into variable $b. =
Have I
>> >> > >> misunderstood?
>> >> > >>
>> >> > >> Anyway, I'm just hoping to start a conversation on the topic of
>> >> > >> precedence in general, and hopefully getting some feedback as to=
 where
>> >> > >> to look in the docs for further instruction.
>> >> > >>
>> >> > >> Best Regards, Bill.
>> >> > >>
>> >> > >>
>> >> > >> On Fri, Dec 6, 2019 at 12:15 AM ToddAndMargo via perl6-users
>> >> > >> <perl6-users@perl.org> wrote:
>> >> > >> >
>> >> > >> > On 2019-12-05 23:19, ToddAndMargo via perl6-users wrote:
>> >> > >> > > On 2019-12-05 03:09, William Michels via perl6-users wrote:
>> >> > >> > >> What happens when you type "perl6" or "raku" at the bash co=
mmand prompt?
>> >> > >> > >
>> >> > >> > > Hi William,
>> >> > >> > >
>> >> > >> > > On my shop machine, it jumps to the next line with an
>> >> > >> > > empty flashing cursor
>> >> > >> > >
>> >> > >> > > On my office machine, it told me to install
>> >> > >> > >      zef install Readline
>> >> > >> > >
>> >> > >> > > After that, I get:
>> >> > >> > >
>> >> > >> > > $ perl6
>> >> > >> > > To exit type 'exit' or '^D'
>> >> > >> > >  >
>> >> > >> > >
>> >> > >> > > and
>> >> > >> > >
>> >> > >> > >  > say "hello World"
>> >> > >> > > hello World
>> >> > >> > >  > say "B" ~ Q[:\] ~ " drive dismounted"
>> >> > >> > > B:\ drive dismounted
>> >> > >> > >  >
>> >> > >> > >
>> >> > >> > > and sticking an obvious booboo into it
>> >> > >> > >
>> >> > >> > >  > if 3 % 2 =3D 1 {say "odd"};
>> >> > >> > > Cannot modify an immutable Int (1)
>> >> > >> > >    in block <unit> at <unknown file> line 1
>> >> > >> > >
>> >> > >> > > Plus I can use the arrow keys to recall previous lines too.
>> >> > >> > >
>> >> > >> > > Time up update my Perl6 on my shop computer!
>> >> > >> > >
>> >> > >> > > No more hassling with `perl6 -e` !!!
>> >> > >> > >
>> >> > >> > > Dude!  THANK YOU !!!!!!
>> >> > >> > >
>> >> > >> > > -T
>> >> > >> >
>> >> > >> > You've created a monster!!
>> >> > >> >
>> >> > >> > perl6
>> >> > >> > To exit type 'exit' or '^D'
>> >> > >> >  > my $x =3D Q[</b><br>]
>> >> > >> > </b><br>
>> >> > >> >  > say $x
>> >> > >> > </b><br>
>> >> > >> >  > (my $y =3D $x ) ~~ s/ Q[<] .* //;
>> >> > >> > =3D=3D=3DSORRY!=3D=3D=3D Error while compiling:
>> >> > >> > Unrecognized regex metacharacter < (must be quoted to match li=
terally)
>> >> > >> > ------> (my $y =3D $x ) ~~ s/ Q[<] .* //;
>> >> > >> >  > my $x =3D Q[abc</b><br>]
>> >> > >> > abc</b><br>
>> >> > >> >  > (my $y =3D $x ) ~~ s/ '<' .* //;
>> >> > >> > =EF=BD=A2</b><br>=EF=BD=A3
>> >> > >> >  > (my $y =3D $x ) ~~ s/ '<' .* //; say $y
>> >> > >> > abc
>> >> > >> >  > (my $y =3D $x ) ~~ s/ '<' .* //; say $x; say $y
>> >> > >> > abc</b><br>
>> >> > >> > abc
>> >> > >> >
>> >> > >> >
>> >> > >> > Thank you!
>> >> > >> >
>> >> > >> >
>> >> > >> > --
>> >> > >> > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> >> > >> > Computers are like air conditioners.
>> >> > >> > They malfunction when you open windows
>> >> > >> > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0
perl6
12/11/2019 7:12:19 PM
perl.perl6.users 1386 articles. 0 followers. Follow

0 Replies
48 Views

Similar Articles

[PageSpeed] 13

Reply: