New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
perldwim document - Code completions, and other optimizations Perl does for you #13908
Comments
From @b2gillsI went and created a document that lists several modifications that The purpose of this document is to enable people to find this information The reason I combined optimizations with DWIM code changes, is that the I have previously sent this to P5P where at least Yves Orton (demerphq) Here is a short snippet of the file as viewed with perldoc NAME DESCRIPTION That is Perl will re-write the opcodes to do what you probably wanted These can reduce the amount of code you would normally have to type, Knowing about these modifications can help you determine the best way to OPCODE-TREE MODIFICATIONS gets turned into: while( <ARGV> ){...} Which is a construct that reads from the files in @ARGV, or "STDIN" See "I/O Operators" in perlop for more details. range in for loop conditional Normally the ranges would get turned into something like a normal Instead the two endpoints are left in the op-tree, with the rest of This is particularly helpful if the range is large. for( 0..65536 ){...} |
From @b2gills0001-Create-the-perldwim-document.patchFrom e0bdad934a2a2335bdab2977c13ce692b6d23919 Mon Sep 17 00:00:00 2001
From: Brad Gilbert <b2gills@gmail.com>
Date: Fri, 6 Jun 2014 17:49:34 -0500
Subject: [PATCH] Create the perldwim document
---
MANIFEST | 1 +
pod/perldwim.pod | 287 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 288 insertions(+)
create mode 100644 pod/perldwim.pod
diff --git a/MANIFEST b/MANIFEST
index baf405f..3f58e8b 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -4488,6 +4488,7 @@ pod/perldelta.pod Perl changes since previous version
pod/perldiag.pod Perl diagnostic messages
pod/perldsc.pod Perl data structures intro
pod/perldtrace.pod Perl's support for DTrace
+pod/perldwim.pod Code completions, and other optimizations Perl does for you
pod/perlebcdic.pod Considerations for running Perl on EBCDIC platforms
pod/perlembed.pod Perl ways to embed perl in your C or C++ application
pod/perlexperiment.pod A listing of experimental features in Perl
diff --git a/pod/perldwim.pod b/pod/perldwim.pod
new file mode 100644
index 0000000..afc5f0f
--- /dev/null
+++ b/pod/perldwim.pod
@@ -0,0 +1,287 @@
+=encoding utf8
+
+=head1 NAME
+
+perldwim - Code completions, and other optimizations Perl does for you
+
+=head1 DESCRIPTION
+
+This document lists the modifications Perl does to your code which allow you to
+write your code in a clean way, and have your code still do what you actually
+want.
+
+That is Perl will re-write the opcodes to do what you probably wanted Perl
+to do. Commonly reffered to as "Do What I Mean" (DWIM) within the Perl
+community.
+
+These can reduce the amount of code you would normally have to type,
+improve the clarity of your code, or they can improve performance.
+
+Knowing about these modifications can help you determine the best way to
+structure your code.
+It can also help you determine which versions of Perl your code will work on,
+or which versions it will work on the best.
+
+=head1 OPCODE-TREE MODIFICATIONS
+
+=over 4
+
+=item C<< <> >>
+
+ while( <> ){...}
+
+gets turned into:
+
+ while( <ARGV> ){...}
+
+Which is a construct that reads from the files in L<C<@ARGV>|perlvar/"@ARGV">,
+or C<STDIN> if L<C<@ARGV>|perlvar/"@ARGV"> is empty.
+
+See L<perlop/"I/O Operators"> for more details.
+
+=item range in for loop conditional
+
+ for( 1..10 ){...}
+ for( 1..$n ){...}
+ for( "a".."z" ){...}
+
+Normally the ranges would get turned into something like a normal array
+containing all of the items to be iterated over.
+
+Instead the two endpoints are left in the op-tree, with the rest of the items
+to be iterated over generated as they are needed.
+
+This is particularly helpful if the range is large.
+
+ for( 0..65536 ){...}
+ for( 'a'..'perl' ){...} # 285076
+
+=item constant folding
+
+Perl will replace most basic operations on constants with the result.
+
+So these
+
+ my $v = 4 * 10 ** 3 + 3 * 10 ** 2 + 2 * 10 ** 1 + 1 * 10 ** 0;
+ my $five = 5 || 3;
+ my $three = 5 && 3;
+ my $true = 5 < 6;
+ my false = "a" gt "b";
+ my $neg = "a" cmp "b";
+
+become
+
+ my $v = 4321;
+ my $five = 5;
+ my $three = 3;
+ my $true = 1;
+ my $false = !1;
+ my $neg = "a" cmp "b";
+
+There are many more ops and functions that Perl will constant fold,
+such as C<sin> C<!> C<< < >> c<cmp>.
+
+This helps when Perl is trying to reduce code that has a
+L<constant value as a conditional|/"constant value in conditional">.
+
+=item constant value in conditional
+
+In constructs where Perl can determine at compile time that it doesn't need to
+check the conditional at run-time, it will optimize it to the fastest code
+that still has the same side effects.
+
+These constructs will effectively be no-ops.
+
+ if( 0 ){...}
+ unless( 1 ){...}
+ while( 0 ){...}
+ while( 0 ){...}continue{...}
+ until( 1 ){...}
+ until( 1 ){...}continue{...}
+ for( ; 0 ; ){...}
+ for( ; 0 ; ){...}continue{...}
+
+While these will end up as C<do> blocks.
+
+ if( 1 ){...}
+ unless( 0 ){...}
+
+The loop constructs that can get entered into will be mostly the same,
+but without the check of the conditional.
+
+ while( 1 ){...}
+ until( 0 ){...}
+ for( ; 1 ; ){...}
+ while(){...}
+
+Constructs that have a section to be run when true, and one to be run when
+false will also get optimized.
+
+ if( 0 ){ say 'true' }else{ say 'false' } # do{ say 'false' }
+ $v = 0 ? 'true' : 'false'; # $v = 'false';
+
+Knowing this you can help performance by storing values that cannot change
+over the course of your program, in constants.
+
+ use constant DEBUG => 0;
+ if( DEBUG ){...}
+
+You can create subroutines that will act similar to constants.
+
+ sub True (){ !!1 }
+ sub False (){ !!0 }
+
+It is usually clearer to use the L<constant> pragma though.
+
+ use constant True => !!1;
+ use constant False => !!0;
+ # or
+ use constant {
+ True => !!1,
+ False => !!0,
+ };
+
+=item iterator function in while loop conditional
+
+ while( readline $fh ){...}
+ while( <> ){...}
+ while( <STDIN> ){...}
+ while( glob '"*e f*"' ){...}
+ while( <"*e f*"> ){...}
+ while( readdir $dh ){...}
+ while( each %h ){...}
+ while( each @a ){...}
+
+Normally the while loop would stop when the return value of these ops were
+false and don't store the result anywhere.
+Which is both rather pointless,
+and would stop early if the function returned C<0>.
+
+Instead it stores the result in C<$_>, and stops when they return C<undef>.
+
+In other words it changes this:
+
+ while( <> ){...}
+
+into this
+
+ while( defined( $_ = <> ) ){...}
+
+This also applies to the conditional part of c-style C<for> loops.
+
+ for ( ; <> ; ) {...}
+ for ( ; defined( $_ = <> ) ; ) {...}
+
+Perl also adds the C<defined> check if you explicitly store the result
+in a variable.
+
+ while( my $line = readline $fh ){...}
+ while( defined( my $line = readline $fh ) ){...}
+
+This code modification helps reduce the amount of code you have to write;
+which reduces the possibility for errors, and improves clarity of intent.
+
+See L<perlop/"I/O Operators"> for more information.
+
+Support for C<readdir> was added in L<5.12|perlfunc/"readdir DIRHANDLE">
+with commit
+114c60ecb1f775ef1deb4fdc8fb8e3a6f343d13d
+
+Support for C<each> was added in L<5.18|perl5180delta/"Selected Bug Fixes">
+with commit
+8ae39f603f0f5778c160e18e08df60affbd5a620
+
+=item padrange op
+
+This single op can, in some circumstances, replace the sequence of a
+pushmark followed by one or more padsv/padav/padhv ops, and possibly
+a trailing C<list> op.
+
+This is generally more efficient, but is particularly so in the case
+of C<void/INTRO> combination: formerly, C<my($a,$b,@c,%d)>; would be compiled as
+
+ pushmark; padsv[$a]; padsv[$b]; padav[@c]; padhv[%d]; list; nextstate
+
+which would have the effect of pushing C<$a>, C<$b> onto the stack, then
+pushing the (non-existent) elements of C<@c>, then pushing the C<%d> C<HV>;
+then C<pp_list> would pop all the elements except the last C<%h>;
+finally C<nextstate> would pop C<%h>.
+Instead C<padrange> skips all the pushing and popping in void context.
+
+This also handles constructs like
+
+ my ($x,$y) = @_
+
+With the C<OPf_SPECIAL> flag to indicate that in addition,
+C<@_> should be pushed onto the stack, skipping an
+additional C<pushmark>/C<gv[*_]>/C<rv2sv> combination.
+
+
+So in total the above construct
+goes from being
+
+ 3 <0> pushmark s
+ 4 <$> gv(*_) s
+ 5 <1> rv2av[t3] lK/1
+ 6 <0> pushmark sRM*/128
+ 7 <0> padsv[$x:1,2] lRM*/LVINTRO
+ 8 <0> padsv[$y:1,2] lRM*/LVINTRO
+ 9 <2> aassign[t4] vKS
+
+to
+
+ 3 <0> padrange[$x:1,2; $y:1,2] l*/LVINTRO,2 ->4
+ 4 <2> aassign[t4] vKS
+
+Added in L<5.18|perl5180delta/Internal Changes> with the first commit being
+a7fd8ef68b459a13ba95615ec125e2e7ba656b47
+
+=item De Morgan's law
+
+Perl will use De Morgan's law to reduce the number of ops.
+
+So these
+
+ if ( $p and (!$x || !$y) ) { ... }
+ if ( !$x || !$y ) { ... }
+
+become
+
+ if ( $p and not $x && $y ) { ... }
+ unless ( $x and $y ) { ... }
+
+This should not affect your code, unless you are using L<overload|overload>
+improperly.
+
+=item enable features when declaring the lowest supported version
+
+If you declare the minimum version of Perl with a
+L<C<use>|perlfunc/"use VERSION"> statement, Perl will also enable
+any features that came with that version of Perl.
+
+That is this:
+
+ use 5.10.0;
+
+is the same as:
+
+ BEGIN{
+ require 5.10.0;
+ require feature;
+ feature->import(':5.10')
+ }
+
+This is not limited to just enabling features, it will also enable full
+L<strict> mode if the declared version is at least 5.11.0.
+
+See L<feature> for more information.
+
+Added in L<5.10|perl5100delta/"The feature pragma">
+
+The enabling of strict mode was added in
+L<5.12|perl5120delta/"Implicit strictures"> with the first commit being
+53eb19dd57d98e5a28ec6e1a56a1a40ce469145f
+
+=back
+
+=cut
--
1.9.1
|
From @jkeenanOn Fri Jun 06 16:10:12 2014, brad wrote:
I like this. There are a few places where the grammar needs to be ironed out, but we don't need to do that yet. We first need to have people review the document for accuracy. Thank you very much. |
The RT System itself - Status changed from 'new' to 'open' |
From @xdgOn Fri, Jun 6, 2014 at 7:10 PM, Brad Gilbert <perlbug-followup@perl.org> wrote:
+1 or more I'm not sure "perldwim" is the right name, but I love the idea of I would omit the padrange optimization -- this isn't something that David -- |
From @b2gillsOn Fri, Jun 6, 2014 at 8:12 PM, David Golden <xdg@xdg.me> wrote:
Actually there are probably ways of writing a program where you can I do think that section can be whittled down much further than it is currently. I do think that this is just the tip of the iceberg of the things that should As to the name: There is a reason I decided to put DWIM stuff and optimizations together; For example `for(1...10){...}` could be considered DWIM because So I figured perldwim was better than perloptimize. Any way, I just thought that the distribution could use such a |
From @druud62On 2014-06-07 01:10, Brad Gilbert wrote:
I would put a space after "while", because it is not a function call.
Likewise.
-- |
From @AbigailOn Fri, Jun 06, 2014 at 04:10:13PM -0700, Brad Gilbert wrote:
This actually gets turned into: while (defined ($_ = <ARGV>)) {...}
Not an array. A list.
Does the intended audience have any idea what the op-tree is? Or what
What's "285076"?
This is nice, but is this a DWIM? Will knowing this fact actually cause
Two things:
But earlier you said it turns into while (<ARGV>) {...}
I think this item will confuse the majority of the readers of this
So, that's not a DWIM, but a "do something else than what I mean"...
My overall feeling is that this document is just a hodgepot of random The points you bring up are good in general, I just don't see the value Abigail |
From @jhiOn Saturday-201406-07, 17:32, Abigail wrote:
I don't know whether it's "DWIM" (and I have doubts about the naming of my $V = 4/3 * PI() * $r ** 3; instead of my $V = 4.18879 * $r ** 3; |
From @b2gillsOn Sat, Jun 7, 2014 at 4:32 PM, Abigail <abigail@abigail.be> wrote:
The defined check and setting $_ is taken care of elsewhere in the doc.
That's why I said it was something like a normal array.
No and yes. That is it's intended as a resource similar to an So each item in there should be rather short with a
$ perl -E'for("a".."perl"){$count++} say $count'
Yes actually. Just look at t/test_pl/_num_to_alpha.t is( _num_to_alpha(26 ** 3 + 26 ** 2 + 26 + 1 ), 'AAAB'); with is( _num_to_alpha( 18279 ), 'AAAB'); ( In that case it would have definitely been premature, and still have Or if I needed a variable to start with the value of sin(253)
Well 0 is not the same as !!0, and the same is true to a lesser It was just an example, perhaps these would not attract your ire: sub thousand (){ 1_000 }
That is not the op-tree modification I was trying to show in this
Perhaps I should call it an "internal OPCODE" to help prevent any confusion.
I combined DWIM and opcode optimizations because they are implemented I had some difficulty figuring out a name that was If you have a better name I would like to hear it.
That was rather the point. It was meant as a place to find where Since some of the things are almost undocumented it ( I have yet to find any freely available resource discuss the
I assume that means that you would rather see some of it moved out Really I just wanted to throw something against the wall to see what If you can think about how this information should be structured |
From @khwilliamsonOn 06/07/2014 04:43 PM, Brad Gilbert wrote:
I think something like this is a fine idea; I thought several people |
From @neilb
++ - this is both interesting and very useful. Reading it made me immediately want to go trawling through my modules for things to adjust, and has already changed one aspect of my personal coding style. DWIM doesn't feel like the right name - it's more like idiomatic perl, "working with the compiler", "behind the curtain". The latter feels the most appropriate, but perlcurtain is a bit opaque :-) Thank you for creating this. Neil |
From @xdgOn Fri, Jun 6, 2014 at 9:43 PM, Brad Gilbert <b2gills@gmail.com> wrote:
Then that's the point to make. You don't need to explain the gory There are reasons to shift, such as C<< my $x = shift // default() >> -- |
From @b2gillsOn Sun, Jun 8, 2014 at 9:56 AM, David Golden <xdg@xdg.me> wrote:
I will reiterate that the padrange section was a bit out of place I think my current proposal should be scrapped and restarted Perhaps one that is more of a tutorial style which comes At a later point it might be useful to have another document that goes |
From @jplinderman+1 for concept, but I agree with many that "perldwim" is not the right name. In particular, the "poster child" while (my $line = <$fh>) ... caused me considerable confusion when I preceded it with if (my $lastline = <$fh>) ... and I got barked at. Why it's "what I mean" in one context but not the |
From @karenetheridgeOn Sun, Jun 08, 2014 at 08:14:50PM -0500, Brad Gilbert wrote:
Perhap a new document in the perlfaq family? |
Migrated from rt.perl.org#122055 (status was 'open')
Searchable as RT122055$
The text was updated successfully, but these errors were encountered: