http://qs321.pair.com?node_id=1217271


in reply to Overloading Weirdness

I boiled your examples down to the case of "$str1 $str2", and I can confirm the behavior you observed on Perl 5.26 as well. The answer seems to be that Perl optimizes away the extra stringification step in certain cases - note how in the below, stringify becomes ex-stringify:

$ perl -MO=Concise -e 'my $x; $x = "$y $z"' b <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 3 <0> padsv[$x:1,2] vM/LVINTRO ->4 4 <;> nextstate(main 2 -e:1) v:{ ->5 a <@> stringify[$x:1,2] sK/TARGMY,1 ->b - <0> ex-pushmark s ->5 9 <2> concat[t3] sKS/2 ->a 7 <2> concat[t2] sK/2 ->8 - <1> ex-rv2sv sK/1 ->6 5 <$> gvsv(*y) s ->6 6 <$> const(PV " ") s ->7 - <1> ex-rv2sv sK/1 ->9 8 <$> gvsv(*z) s ->9 -e syntax OK $ perl -MO=Concise -e 'my $x; $x = ""."$y $z"' c <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 3 <0> padsv[$x:1,2] vM/LVINTRO ->4 4 <;> nextstate(main 2 -e:1) v:{ ->5 b <2> concat[$x:1,2] sK/TARGMY,2 ->c 5 <$> const(PV "") s ->6 - <1> ex-stringify sK/1 ->b - <0> ex-pushmark s ->6 a <2> concat[t3] sKS/2 ->b 8 <2> concat[t2] sK/2 ->9 - <1> ex-rv2sv sK/1 ->7 6 <$> gvsv(*y) s ->7 7 <$> const(PV " ") s ->8 - <1> ex-rv2sv sK/1 ->a 9 <$> gvsv(*z) s ->a -e syntax OK $ perl -MO=Concise -e 'my $x = "$y $z"' a <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 9 <2> sassign vKS/2 ->a - <1> ex-stringify sK/1 ->8 - <0> ex-pushmark s ->3 7 <2> concat[t3] sKS/2 ->8 5 <2> concat[t2] sK/2 ->6 - <1> ex-rv2sv sK/1 ->4 3 <$> gvsv(*y) s ->4 4 <$> const(PV " ") s ->5 - <1> ex-rv2sv sK/1 ->7 6 <$> gvsv(*z) s ->7 8 <0> padsv[$x:1,2] sRM*/LVINTRO ->9 -e syntax OK $ perl -MO=Concise -e 'my $x; $x = $y." ".$z' c <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 3 <0> padsv[$x:1,2] vM/LVINTRO ->4 4 <;> nextstate(main 2 -e:1) v:{ ->5 b <2> sassign vKS/2 ->c 9 <2> concat[t3] sKS/2 ->a 7 <2> concat[t2] sK/2 ->8 - <1> ex-rv2sv sK/1 ->6 5 <$> gvsv(*y) s ->6 6 <$> const(PV " ") s ->7 - <1> ex-rv2sv sK/1 ->9 8 <$> gvsv(*z) s ->9 a <0> padsv[$x:1,2] sRM* ->b -e syntax OK

I'm not yet sure what you could do about this, or even if you can do something about it, because apparently the final stringification is always part of Perl's intended operations, but it's just optimized away in some cases. Plus, at the moment I can't remember and can't find in the docs whether Perl even makes any guarantees as to what order the concatenations and stringifications are executed in a case like "$str1 $str2", which one might think is equivalent to $str1." ".$str2, but apparently is not, because the former sometimes involves an extra stringification. Normally the order doesn't really make a difference, except unfortunately when you rely on overloading. One might even argue that the aforementioned inconsistency could be seen as bug in Perl.

Of course the other possible argument is that in this case, relying on overloading is the problem. If I take a step back and look at this from an "XY Problem" angle: You've got objects that you want to behave as normal strings, except that they (loosely speaking) have an extra layer of encoding wrapped around them. You're generating HTML, so that encoding is for example "<>" to "&lt;&gt;". You're worried because you see this encoding happening too early. But my question here is: you've got some strings that should be encoded (your str objects), and others that shouldn't (plain strings). But in the end, everything is going to become a plain string anyway, so why do you care when the encoding step happens? (Maybe I'm missing something.)

I completely understand that this kind of an implementation is "neat" :-) But why not use the existing solutions for HTML generation? For example, Template::Toolkit, Mojo::Template, ...

By the way: Crossposted to StackOverflow. Crossposting is ok, but it is considered polite to inform about it so that efforts are not duplicated.