# [PATCH 00/16] git-send-email cleanups

29 messages from 2010-09-30 to 2010-10-01. Participants: Ævar Arnfjörð Bjarmason, Brian Gernhardt, Jay Soffian, Jeff King, Junio C Hamano.
Thread: https://gitlist.dev/t/25299

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:42

Subject: [PATCH 00/16] git-send-email cleanups
Message-ID: <1285854189-10240-1-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-1-git-send-email-avarab%40gmail.com

```
As threatened here's a series that cleans up some of the glaring warts
in git-send-email.

Ævar Arnfjörð Bjarmason (16):
  send-email: use lexical filehandle for opendir
  send-email: use lexical filehandles for $compose
  send-email: use lexical filehandles during sending
  send-email: get_patch_subject doesn't need a prototype
  send-email: file_declares_8bit_cte doesn't need a prototype
  send-email: unique_email_list doesn't need a prototype
  send-email: cleanup_compose_files doesn't need a prototype
  send-email: use \E***\Q instead of \*\*\*
  send-email: sanitize_address use $foo, not "$foo"
  send-email: sanitize_address use qq["foo"], not "\"foo\""
  send-email: use (?:) instead of () if no  match variables are needed
  send-email: is_rfc2047_quoted use qr// regexes
  send-email: extract_valid_address use qr// regexes and /o
  send-email: send_message die on $!, not $?
  send-email: make_message_id use "require" instead of "use"
  send-email: use Perl idioms in while loop

 git-send-email.perl   |   80 +++++++++++++++++++++++-------------------------
 t/t9001-send-email.sh |    2 +-
 2 files changed, 39 insertions(+), 43 deletions(-)

-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:42

Subject: [PATCH 01/16] send-email: use lexical filehandle for opendir
Message-ID: <1285854189-10240-2-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-2-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 8cc4161..2f18d83 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -512,12 +512,12 @@ while (defined(my $f = shift @ARGV)) {
 		push @rev_list_opts, "--", @ARGV;
 		@ARGV = ();
 	} elsif (-d $f and !check_file_rev_conflict($f)) {
-		opendir(DH,$f)
+		opendir my $dh, $f
 			or die "Failed to opendir $f: $!";
 
 		push @files, grep { -f $_ } map { catfile($f, $_) }
-				sort readdir(DH);
-		closedir(DH);
+				sort readdir $dh;
+		closedir $dh;
 	} elsif ((-f $f or -p $f) and !check_file_rev_conflict($f)) {
 		push @files, $f;
 	} else {
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:42

Subject: [PATCH 02/16] send-email: use lexical filehandles for $compose
Message-ID: <1285854189-10240-3-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-3-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |   22 +++++++++++-----------
 1 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 2f18d83..634835c 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -567,7 +567,7 @@ if ($compose) {
 	$compose_filename = ($repo ?
 		tempfile(".gitsendemail.msg.XXXXXX", DIR => $repo->repo_path()) :
 		tempfile(".gitsendemail.msg.XXXXXX", DIR => "."))[1];
-	open(C,">",$compose_filename)
+	open my $c, ">", $compose_filename
 		or die "Failed to open for writing $compose_filename: $!";
 
 
@@ -575,7 +575,7 @@ if ($compose) {
 	my $tpl_subject = $initial_subject || '';
 	my $tpl_reply_to = $initial_reply_to || '';
 
-	print C <<EOT;
+	print $c <<EOT;
 From $tpl_sender # This line is ignored.
 GIT: Lines beginning in "GIT:" will be removed.
 GIT: Consider including an overall diffstat or table of contents
@@ -588,9 +588,9 @@ In-Reply-To: $tpl_reply_to
 
 EOT
 	for my $f (@files) {
-		print C get_patch_subject($f);
+		print $c get_patch_subject($f);
 	}
-	close(C);
+	close $c;
 
 	if ($annotate) {
 		do_edit($compose_filename, @files);
@@ -598,23 +598,23 @@ EOT
 		do_edit($compose_filename);
 	}
 
-	open(C2,">",$compose_filename . ".final")
+	open my $c2, ">", $compose_filename . ".final"
 		or die "Failed to open $compose_filename.final : " . $!;
 
-	open(C,"<",$compose_filename)
+	open $c, "<", $compose_filename
 		or die "Failed to open $compose_filename : " . $!;
 
 	my $need_8bit_cte = file_has_nonascii($compose_filename);
 	my $in_body = 0;
 	my $summary_empty = 1;
-	while(<C>) {
+	while(<$c>) {
 		next if m/^GIT:/;
 		if ($in_body) {
 			$summary_empty = 0 unless (/^\n$/);
 		} elsif (/^\n$/) {
 			$in_body = 1;
 			if ($need_8bit_cte) {
-				print C2 "MIME-Version: 1.0\n",
+				print $c2 "MIME-Version: 1.0\n",
 					 "Content-Type: text/plain; ",
 					   "charset=UTF-8\n",
 					 "Content-Transfer-Encoding: 8bit\n";
@@ -639,10 +639,10 @@ EOT
 			print "To/Cc/Bcc fields are not interpreted yet, they have been ignored\n";
 			next;
 		}
-		print C2 $_;
+		print $c2 $_;
 	}
-	close(C);
-	close(C2);
+	close $c;
+	close $c2;
 
 	if ($summary_empty) {
 		print "Summary email is empty, skipping it\n";
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:42

Subject: [PATCH 03/16] send-email: use lexical filehandles during sending
Message-ID: <1285854189-10240-4-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-4-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 634835c..488d894 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -1144,7 +1144,7 @@ $subject = $initial_subject;
 $message_num = 0;
 
 foreach my $t (@files) {
-	open(F,"<",$t) or die "can't open file $t";
+	open my $fh, "<", $t or die "can't open file $t";
 
 	my $author = undef;
 	my $author_encoding;
@@ -1157,7 +1157,7 @@ foreach my $t (@files) {
 	$message = "";
 	$message_num++;
 	# First unfold multiline header fields
-	while(<F>) {
+	while(<$fh>) {
 		last if /^\s*$/;
 		if (/^\s+\S/ and @header) {
 			chomp($header[$#header]);
@@ -1233,7 +1233,7 @@ foreach my $t (@files) {
 		}
 	}
 	# Now parse the message body
-	while(<F>) {
+	while(<$fh>) {
 		$message .=  $_;
 		if (/^(Signed-off-by|Cc): (.*)$/i) {
 			chomp;
@@ -1250,12 +1250,12 @@ foreach my $t (@files) {
 				$c, $_) unless $quiet;
 		}
 	}
-	close F;
+	close $fh;
 
 	if (defined $cc_cmd && !$suppress_cc{'cccmd'}) {
-		open(F, "$cc_cmd \Q$t\E |")
+		open my $fh, "$cc_cmd \Q$t\E |"
 			or die "(cc-cmd) Could not execute '$cc_cmd'";
-		while(<F>) {
+		while(<$fh>) {
 			my $c = $_;
 			$c =~ s/^\s*//g;
 			$c =~ s/\n$//g;
@@ -1264,7 +1264,7 @@ foreach my $t (@files) {
 			printf("(cc-cmd) Adding cc: %s from: '%s'\n",
 				$c, $cc_cmd) unless $quiet;
 		}
-		close F
+		close $fh
 			or die "(cc-cmd) failed to close pipe to '$cc_cmd'";
 	}
 
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:42

Subject: [PATCH 04/16] send-email: get_patch_subject doesn't need a prototype
Message-ID: <1285854189-10240-5-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-5-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 488d894..b50c963 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -549,7 +549,7 @@ if (@files) {
 	usage();
 }
 
-sub get_patch_subject($) {
+sub get_patch_subject {
 	my $fn = shift;
 	open (my $fh, '<', $fn);
 	while (my $line = <$fh>) {
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:42

Subject: [PATCH 05/16] send-email: file_declares_8bit_cte doesn't need a prototype
Message-ID: <1285854189-10240-6-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-6-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index b50c963..f471888 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -679,7 +679,7 @@ sub ask {
 
 my %broken_encoding;
 
-sub file_declares_8bit_cte($) {
+sub file_declares_8bit_cte {
 	my $fn = shift;
 	open (my $fh, '<', $fn);
 	while (my $line = <$fh>) {
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:42

Subject: [PATCH 06/16] send-email: unique_email_list doesn't need a prototype
Message-ID: <1285854189-10240-7-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-7-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index f471888..90b777a 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -136,7 +136,6 @@ my $have_mail_address = eval { require Mail::Address; 1 };
 my $smtp;
 my $auth;
 
-sub unique_email_list(@);
 sub cleanup_compose_files();
 
 # Variables we fill in automatically, or via prompting:
@@ -1332,7 +1331,7 @@ sub cleanup_compose_files() {
 
 $smtp->quit if $smtp;
 
-sub unique_email_list(@) {
+sub unique_email_list {
 	my %seen;
 	my @emails;
 
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:43

Subject: [PATCH 07/16] send-email: cleanup_compose_files doesn't need a prototype
Message-ID: <1285854189-10240-8-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-8-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 90b777a..ce9b5eb 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -136,8 +136,6 @@ my $have_mail_address = eval { require Mail::Address; 1 };
 my $smtp;
 my $auth;
 
-sub cleanup_compose_files();
-
 # Variables we fill in automatically, or via prompting:
 my (@to,$no_to,@cc,$no_cc,@initial_cc,@bcclist,$no_bcc,@xh,
 	$initial_reply_to,$initial_subject,@files,
@@ -1325,7 +1323,7 @@ foreach my $t (@files) {
 
 cleanup_compose_files();
 
-sub cleanup_compose_files() {
+sub cleanup_compose_files {
 	unlink($compose_filename, $compose_filename . ".final") if $compose;
 }
 
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:43

Subject: [PATCH 08/16] send-email: use \E***\Q instead of \*\*\*
Message-ID: <1285854189-10240-9-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-9-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
Change the regex introduced in a03bc5b to use the \E...\Q escape
syntax instead of using backslashes. It's more readable like this, and
easier to grep for.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index ce9b5eb..1218bbe 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -705,7 +705,7 @@ if (!defined $auto_8bit_encoding && scalar %broken_encoding) {
 
 if (!$force) {
 	for my $f (@files) {
-		if (get_patch_subject($f) =~ /\*\*\* SUBJECT HERE \*\*\*/) {
+		if (get_patch_subject($f) =~ /\Q*** SUBJECT HERE ***\E/) {
 			die "Refusing to send because the patch\n\t$f\n"
 				. "has the template subject '*** SUBJECT HERE ***'. "
 				. "Pass --force if you really want to send.\n";
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:43

Subject: [PATCH 09/16] send-email: sanitize_address use $foo, not "$foo"
Message-ID: <1285854189-10240-10-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-10-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
There's no reason to explicitly stringify a variable in Perl unless
it's an overloaded object and you want to call overload::StrVal,
otherwise it's just creating a new scalar redundantly.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 1218bbe..1bf090a 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -864,7 +864,7 @@ sub sanitize_address {
 	my ($recipient_name, $recipient_addr) = ($recipient =~ /^(.*?)\s*(<.*)/);
 
 	if (not $recipient_name) {
-		return "$recipient";
+		return $recipient;
 	}
 
 	# if recipient_name is already quoted, do nothing
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:43

Subject: [PATCH 10/16] send-email: sanitize_address use qq["foo"], not "\"foo\""
Message-ID: <1285854189-10240-11-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-11-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
Perl provides an alternate quote syntax which can make using "" inside
interpolated strings easier to read.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 1bf090a..c012b95 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -881,7 +881,7 @@ sub sanitize_address {
 	# double quotes are needed if specials or CTLs are included
 	elsif ($recipient_name =~ /[][()<>@,;:\\".\000-\037\177]/) {
 		$recipient_name =~ s/(["\\\r])/\\$1/g;
-		$recipient_name = "\"$recipient_name\"";
+		$recipient_name = qq["$recipient_name"];
 	}
 
 	return "$recipient_name $recipient_addr";
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:43

Subject: [PATCH 11/16] send-email: use (?:) instead of () if no match variables are needed
Message-ID: <1285854189-10240-12-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-12-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index c012b95..5a0c4a8 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -365,7 +365,7 @@ my(%suppress_cc);
 if (@suppress_cc) {
 	foreach my $entry (@suppress_cc) {
 		die "Unknown --suppress-cc field: '$entry'\n"
-			unless $entry =~ /^(all|cccmd|cc|author|self|sob|body|bodycc)$/;
+			unless $entry =~ /^(?:all|cccmd|cc|author|self|sob|body|bodycc)$/;
 		$suppress_cc{$entry} = 1;
 	}
 }
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:43

Subject: [PATCH 12/16] send-email: is_rfc2047_quoted use qr// regexes
Message-ID: <1285854189-10240-13-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-13-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 5a0c4a8..b87c3f2 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -852,8 +852,8 @@ sub quote_rfc2047 {
 
 sub is_rfc2047_quoted {
 	my $s = shift;
-	my $token = '[^][()<>@,;:"\/?.= \000-\037\177-\377]+';
-	my $encoded_text = '[!->@-~]+';
+	my $token = qr/[^][()<>@,;:"\/?.= \000-\037\177-\377]+/;
+	my $encoded_text = qr/[!->@-~]+/;
 	length($s) <= 75 &&
 	$s =~ m/^(?:"[[:ascii:]]*"|=\?$token\?$token\?$encoded_text\?=)$/o;
 }
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:43

Subject: [PATCH 13/16] send-email: extract_valid_address use qr// regexes and /o
Message-ID: <1285854189-10240-14-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-14-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
Change the regex fragment in extract_valid_address to use the qr//
syntax for compiled regexes, and when they're used add a /o flag so
they're only compiled once for the lifetime of the program.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index b87c3f2..47d86ad 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -777,11 +777,11 @@ our ($message_id, %mail, $subject, $reply_to, $references, $message,
 
 sub extract_valid_address {
 	my $address = shift;
-	my $local_part_regexp = '[^<>"\s@]+';
-	my $domain_regexp = '[^.<>"\s@]+(?:\.[^.<>"\s@]+)+';
+	my $local_part_regexp = qr/[^<>"\s@]+/;
+	my $domain_regexp = qr/[^.<>"\s@]+(?:\.[^.<>"\s@]+)+/;
 
 	# check for a local address:
-	return $address if ($address =~ /^($local_part_regexp)$/);
+	return $address if ($address =~ /^($local_part_regexp)$/o);
 
 	$address =~ s/^\s*<(.*)>\s*$/$1/;
 	if ($have_email_valid) {
@@ -789,7 +789,7 @@ sub extract_valid_address {
 	} else {
 		# less robust/correct than the monster regexp in Email::Valid,
 		# but still does a 99% job, and one less dependency
-		$address =~ /($local_part_regexp\@$domain_regexp)/;
+		$address =~ /($local_part_regexp\@$domain_regexp)/o;
 		return $1;
 	}
 }
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:43

Subject: [PATCH 14/16] send-email: send_message die on $!, not $?
Message-ID: <1285854189-10240-15-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-15-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
If close fails we want to emit errno, not the return code of whatever
happened to be the child process run.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 47d86ad..9cb6aa6 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -1035,7 +1035,7 @@ X-Mailer: git-send-email $gitversion
 			exec($smtp_server, @sendmail_parameters) or die $!;
 		}
 		print $sm "$header\n$message";
-		close $sm or die $?;
+		close $sm or die $!;
 	} else {
 
 		if (!defined $smtp_server) {
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:43

Subject: [PATCH 15/16] send-email: make_message_id use "require" instead of "use"
Message-ID: <1285854189-10240-16-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-16-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
Change the use of Sys::Hostname from a "use" to a "require". The
former happens in an implicit BEGIN block and is thus immune from the
if block it's contained in, so it's always loaded.

This should speed up the invocation of git-send-email by a few
milliseconds.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 9cb6aa6..5a19d3d 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -819,7 +819,7 @@ sub make_message_id {
 		last if (defined $du_part and $du_part ne '');
 	}
 	if (not defined $du_part or $du_part eq '') {
-		use Sys::Hostname qw();
+		require Sys::Hostname;
 		$du_part = 'user@' . Sys::Hostname::hostname();
 	}
 	my $message_id_template = "<%s-git-send-email-%s>";
-- 
1.7.3.159.g610493

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 13:43

Subject: [PATCH 16/16] send-email: use Perl idioms in while loop
Message-ID: <1285854189-10240-17-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285854189-10240-17-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
Change `while(<$fh>) { my $c = $_' to `while(my $c = <$fh>) {', and
use `chomp $c' instead of `$c =~ s/\n$//g;', the two are equivalent in
this case.

I've also changed the --cccmd test so that we test for the stripping
of whitespace at the beginning of the lines returned from the
--cccmd. I think we probably shouldn't do this, but it was there
already so I haven't changed the behavior.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-send-email.perl   |    5 ++---
 t/t9001-send-email.sh |    2 +-
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 5a19d3d..445d2ec 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -1252,10 +1252,9 @@ foreach my $t (@files) {
 	if (defined $cc_cmd && !$suppress_cc{'cccmd'}) {
 		open my $fh, "$cc_cmd \Q$t\E |"
 			or die "(cc-cmd) Could not execute '$cc_cmd'";
-		while(<$fh>) {
-			my $c = $_;
+		while(my $c = <$fh>) {
+			chomp $c;
 			$c =~ s/^\s*//g;
-			$c =~ s/\n$//g;
 			next if ($c eq $sender and $suppress_from);
 			push @cc, $c;
 			printf("(cc-cmd) Adding cc: %s from: '%s'\n",
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 6f67da4..99a16d5 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -204,7 +204,7 @@ test_expect_success $PREREQ 'Prompting works' '
 test_expect_success $PREREQ 'cccmd works' '
 	clean_fake_sendmail &&
 	cp $patches cccmd.patch &&
-	echo cccmd--cccmd@example.com >>cccmd.patch &&
+	echo "cccmd--  cccmd@example.com" >>cccmd.patch &&
 	{
 	  echo "#!$SHELL_PATH"
 	  echo sed -n -e s/^cccmd--//p \"\$1\"
-- 
1.7.3.159.g610493

```

## Brian Gernhardt, 2010-09-30 14:30

Subject: Re: [PATCH 00/16] git-send-email cleanups
Message-ID: <18E0A903-D625-4C7A-A575-AC5C5EF448C9@gernhardtsoftware.com>
URL: https://gitlist.dev/e/18E0A903-D625-4C7A-A575-AC5C5EF448C9%40gernhardtsoftware.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```

On Sep 30, 2010, at 9:42 AM, Ævar Arnfjörð Bjarmason wrote:

>  send-email: get_patch_subject doesn't need a prototype
>  send-email: file_declares_8bit_cte doesn't need a prototype
>  send-email: unique_email_list doesn't need a prototype
>  send-email: cleanup_compose_files doesn't need a prototype

None of these subroutines strictly need the prototype, but it does allow Perl to warn us if we send incorrect arguments.  Why remove them?  Are they causing problems somewhere?

~~ Brian

```

## Jay Soffian, 2010-09-30 14:30

Subject: Re: [PATCH 00/16] git-send-email cleanups
Message-ID: <AANLkTimi-8jotJwubC5FpNx0NfVB0zQ_+dKaeEW0y4hN@mail.gmail.com>
URL: https://gitlist.dev/e/AANLkTimi-8jotJwubC5FpNx0NfVB0zQ_%2BdKaeEW0y4hN%40mail.gmail.com
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
On Thu, Sep 30, 2010 at 9:42 AM, Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
> As threatened here's a series that cleans up some of the glaring warts
> in git-send-email.
>
> Ævar Arnfjörð Bjarmason (16):
>  send-email: use lexical filehandle for opendir
>  send-email: use lexical filehandles for $compose
>  send-email: use lexical filehandles during sending
>  send-email: get_patch_subject doesn't need a prototype
>  send-email: file_declares_8bit_cte doesn't need a prototype
>  send-email: unique_email_list doesn't need a prototype
>  send-email: cleanup_compose_files doesn't need a prototype
>  send-email: use \E***\Q instead of \*\*\*
>  send-email: sanitize_address use $foo, not "$foo"
>  send-email: sanitize_address use qq["foo"], not "\"foo\""
>  send-email: use (?:) instead of () if no  match variables are needed
>  send-email: is_rfc2047_quoted use qr// regexes
>  send-email: extract_valid_address use qr// regexes and /o
>  send-email: send_message die on $!, not $?
>  send-email: make_message_id use "require" instead of "use"
>  send-email: use Perl idioms in while loop
>
>  git-send-email.perl   |   80 +++++++++++++++++++++++-------------------------
>  t/t9001-send-email.sh |    2 +-
>  2 files changed, 39 insertions(+), 43 deletions(-)

These all look pretty uncontroversial and sane by me, though I don't
think you touched any of the lines I contributed to git-send-email. If
anything, perhaps this series is a bit too granular -- I might combine
the commits that get rid of the function prototypes into one for
example. Otherwise, thanks for the cleanup.

Acked-by: Jay Soffian <jaysoffian@gmail.com>

j.

```

## Jeff King, 2010-09-30 14:52

Subject: Re: [PATCH 00/16] git-send-email cleanups
Message-ID: <20100930145218.GB32728@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20100930145218.GB32728%40sigill.intra.peff.net
In-Reply-To: <18E0A903-D625-4C7A-A575-AC5C5EF448C9@gernhardtsoftware.com>

```
On Thu, Sep 30, 2010 at 10:30:31AM -0400, Brian Gernhardt wrote:

> >  send-email: get_patch_subject doesn't need a prototype
> >  send-email: file_declares_8bit_cte doesn't need a prototype
> >  send-email: unique_email_list doesn't need a prototype
> >  send-email: cleanup_compose_files doesn't need a prototype
> 
> None of these subroutines strictly need the prototype, but it does
> allow Perl to warn us if we send incorrect arguments.  Why remove
> them?  Are they causing problems somewhere?

They don't necessarily do what you want:

  perl -e 'sub want_scalar($) { print "got $_[0]\n" }
           want_scalar("ok");
           my @a = qw(totally broken);
           want_scalar(@a);
  '

I get:

  got ok
  got 2

And using "sub want_list(@)" basically does nothing at all (you can pass
nothing, a scalar, or a list).

For more details, read:

 http://www.perlmonks.org/?node_id=861966

(If you're impatient, skip to the section "Problems with Regular
Prototypes").

-Peff

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 15:11

Subject: Re: [PATCH 00/16] git-send-email cleanups
Message-ID: <AANLkTikDFJ8jWnuSc9U3hZCRSA971h5Zc2FfJmNiqTUN@mail.gmail.com>
URL: https://gitlist.dev/e/AANLkTikDFJ8jWnuSc9U3hZCRSA971h5Zc2FfJmNiqTUN%40mail.gmail.com
In-Reply-To: <18E0A903-D625-4C7A-A575-AC5C5EF448C9@gernhardtsoftware.com>

```
On Thu, Sep 30, 2010 at 14:30, Brian Gernhardt
<brian@gernhardtsoftware.com> wrote:

> None of these subroutines strictly need the prototype, but it does
> allow Perl to warn us if we send incorrect arguments.  Why remove
> them?  Are they causing problems somewhere?

As Jeff pointed out prototypes are troublesome. If you want to be
warned about too many arguments a better way is:

    sub foo {
        warn sprintf "You gave me %d arguments", scalar @_ if @_ != 1;

Or something like that, but there's no reason to do that for these
subs in particular. There are 32 subroutines in git-send-email.perl,
these weren't in any way more special than the rest.

They probably had prototypes in the first place because they were
added by someone who was under the mistaken impression that Perl
prototypes were remotely similar to C-like prototypes, they're not.

The purpose of Perl prototypes is to rewrite the *caller* code, so
that e.g. if you have:

    sub blah ($$) { ... }

Perl will rewrite this call:

    blah @foo, @bar;

As:

    blah(scalar(@foo), scalar(@bar))

While a blah without prototypes would just be:

    blah(@foo, @bar);

Using prototypes superfluously like this makes it harder to read the
code, because you end up checking every call site for every subroutine
call that uses prototypes to see if rewriting the argument list like
this is producing some unexpected logic error.

```

## Brian Gernhardt, 2010-09-30 15:15

Subject: Re: [PATCH 00/16] git-send-email cleanups
Message-ID: <7703AA30-C1A1-455D-9856-022588EF00B4@gernhardtsoftware.com>
URL: https://gitlist.dev/e/7703AA30-C1A1-455D-9856-022588EF00B4%40gernhardtsoftware.com
In-Reply-To: <20100930145218.GB32728@sigill.intra.peff.net>

```

On Sep 30, 2010, at 10:52 AM, Jeff King wrote:

> They don't necessarily do what you want:
> 
>  perl -e 'sub want_scalar($) { print "got $_[0]\n" }
>           want_scalar("ok");
>           my @a = qw(totally broken);
>           want_scalar(@a);
>  '
> 
> I get:
> 
>  got ok
>  got 2
> 
> And using "sub want_list(@)" basically does nothing at all (you can pass
> nothing, a scalar, or a list).

I'm not surprised by that at all, but I've spent too much time in scripting languages recently.

> For more details, read:
> 
> http://www.perlmonks.org/?node_id=861966
> 
> (If you're impatient, skip to the section "Problems with Regular
> Prototypes").

Huh.  Somewhere along the way I had picked up using prototypes as a solution to some problem and got used to them.  Interesting to see the full discussion why you shouldn't.  I guess I'm reading too much Ruby and Perl6 and didn't think about how that would work with Perl5.

~~ Brian

```

## Jeff King, 2010-09-30 16:19

Subject: Re: [PATCH 13/16] send-email: extract_valid_address use qr// regexes and /o
Message-ID: <20100930161912.GA8707@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20100930161912.GA8707%40sigill.intra.peff.net
In-Reply-To: <1285854189-10240-14-git-send-email-avarab@gmail.com>

```
On Thu, Sep 30, 2010 at 01:43:06PM +0000, Ævar Arnfjörð Bjarmason wrote:

> Change the regex fragment in extract_valid_address to use the qr//
> syntax for compiled regexes, and when they're used add a /o flag so
> they're only compiled once for the lifetime of the program.
> [...]
>  sub extract_valid_address {
>  	my $address = shift;
> -	my $local_part_regexp = '[^<>"\s@]+';
> -	my $domain_regexp = '[^.<>"\s@]+(?:\.[^.<>"\s@]+)+';
> +	my $local_part_regexp = qr/[^<>"\s@]+/;
> +	my $domain_regexp = qr/[^.<>"\s@]+(?:\.[^.<>"\s@]+)+/;
>  

Hmm. But these are lexical variables, so won't we recompile them each
time we enter the subroutine? I don't think it affects correctness, as
this "/o":

> +	return $address if ($address =~ /^($local_part_regexp)$/o);

means that we will compile and use the value from the first time we run
the function.

But we are unnecessarily compiling the sub-regexes each time. Not that
this is probably a performance critical piece of code, but your "/o" is
doing very little, and this is exactly the sort perl wankery that I find
interesting.

Sadly, there is no real perl equivalent of C static local variables,
which is what you really want.  Usually I would do:

  {
    my $local_part_regexp = qr/.../;
    sub extract_valid_address {
      ...
    }
  }

but beware of the execution order. That works well in a module, where
the module code is executed before anybody calls the function. But it
breaks in something like this:

  foo();
  {
    my $foo_static_local = 5;
    sub foo {
      print "$foo_static_local\n";
    }
  }

I think you could get by with:

  {
    my $local_part_regexp;
    sub extract_valid_address {
      $local_part_regexp ||= qr/.../;
      ...
    }
  }

-Peff

```

## Jeff King, 2010-09-30 16:21

Subject: Re: [PATCH 00/16] git-send-email cleanups
Message-ID: <20100930162153.GB8707@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20100930162153.GB8707%40sigill.intra.peff.net
In-Reply-To: <1285854189-10240-1-git-send-email-avarab@gmail.com>

```
On Thu, Sep 30, 2010 at 01:42:53PM +0000, Ævar Arnfjörð Bjarmason wrote:

> As threatened here's a series that cleans up some of the glaring warts
> in git-send-email.
> 
> Ævar Arnfjörð Bjarmason (16):
>   send-email: use lexical filehandle for opendir
>   send-email: use lexical filehandles for $compose
>   send-email: use lexical filehandles during sending
>   send-email: get_patch_subject doesn't need a prototype
>   send-email: file_declares_8bit_cte doesn't need a prototype
>   send-email: unique_email_list doesn't need a prototype
>   send-email: cleanup_compose_files doesn't need a prototype
>   send-email: use \E***\Q instead of \*\*\*
>   send-email: sanitize_address use $foo, not "$foo"
>   send-email: sanitize_address use qq["foo"], not "\"foo\""
>   send-email: use (?:) instead of () if no  match variables are needed
>   send-email: is_rfc2047_quoted use qr// regexes
>   send-email: extract_valid_address use qr// regexes and /o
>   send-email: send_message die on $!, not $?
>   send-email: make_message_id use "require" instead of "use"
>   send-email: use Perl idioms in while loop

With the exception of my comments on the "/o" regexes, these all look
sane to me.

-Peff

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 16:33

Subject: Re: [PATCH 13/16] send-email: extract_valid_address use qr// regexes and /o
Message-ID: <AANLkTimSHxU8EhuOHn77kw+ASCCeg_Bjg2or7L=G_o=M@mail.gmail.com>
URL: https://gitlist.dev/e/AANLkTimSHxU8EhuOHn77kw%2BASCCeg_Bjg2or7L%3DG_o%3DM%40mail.gmail.com
In-Reply-To: <20100930161912.GA8707@sigill.intra.peff.net>

```
On Thu, Sep 30, 2010 at 16:19, Jeff King <peff@peff.net> wrote:
> On Thu, Sep 30, 2010 at 01:43:06PM +0000, Ævar Arnfjörð Bjarmason wrote:
>
>> Change the regex fragment in extract_valid_address to use the qr//
>> syntax for compiled regexes, and when they're used add a /o flag so
>> they're only compiled once for the lifetime of the program.
>> [...]
>>  sub extract_valid_address {
>>       my $address = shift;
>> -     my $local_part_regexp = '[^<>"\s@]+';
>> -     my $domain_regexp = '[^.<>"\s@]+(?:\.[^.<>"\s@]+)+';
>> +     my $local_part_regexp = qr/[^<>"\s@]+/;
>> +     my $domain_regexp = qr/[^.<>"\s@]+(?:\.[^.<>"\s@]+)+/;
>>
>
> Hmm. But these are lexical variables, so won't we recompile them each
> time we enter the subroutine? I don't think it affects correctness, as
> this "/o":
>
>> +     return $address if ($address =~ /^($local_part_regexp)$/o);
>
> means that we will compile and use the value from the first time we run
> the function.
>
> But we are unnecessarily compiling the sub-regexes each time. Not that
> this is probably a performance critical piece of code, but your "/o" is
> doing very little, and this is exactly the sort perl wankery that I find
> interesting.

IIRC different perl versions treat this differently. In more recent
versions doing:

    perl -Mre=debug -E 'sub x { my $x = qr/foo/; my $y = qr/bar/;
/$x$y/ } x($_) for 1..2'

Will only compile all of those regexes once, since perl can see that
they're constant. So the /o does nothing.

We might want to keep it for self-documentation purposes to indicate
that the $local_part_regexp would never change, but it's probably best
to drop that /o altogether.

> Sadly, there is no real perl equivalent of C static local variables,
> which is what you really want.  Usually I would do:
>
>  {
>    my $local_part_regexp = qr/.../;
>    sub extract_valid_address {
>      ...
>    }
>  }
>
> but beware of the execution order. That works well in a module, where
> the module code is executed before anybody calls the function. But it
> breaks in something like this:
>
>  foo();
>  {
>    my $foo_static_local = 5;
>    sub foo {
>      print "$foo_static_local\n";
>    }
>  }
>
> I think you could get by with:
>
>  {
>    my $local_part_regexp;
>    sub extract_valid_address {
>      $local_part_regexp ||= qr/.../;
>      ...
>    }
>  }

Perl has static variables like that, just not in the ancient version
we're pinned to:

    sub foo {
        state $foo = qr/$_[0]/
    }

```

## Junio C Hamano, 2010-09-30 17:25

Subject: Re: [PATCH 13/16] send-email: extract_valid_address use qr// regexes and /o
Message-ID: <7vocbfjg7x.fsf@alter.siamese.dyndns.org>
URL: https://gitlist.dev/e/7vocbfjg7x.fsf%40alter.siamese.dyndns.org
In-Reply-To: <20100930161912.GA8707@sigill.intra.peff.net>

```
Jeff King <peff@peff.net> writes:

> ...
> But we are unnecessarily compiling the sub-regexes each time. Not that
> this is probably a performance critical piece of code, but your "/o" is
> doing very little, and this is exactly the sort perl wankery that I find
> interesting.

Well, isn't the _sole_ point of using qr// to optimize by avoiding
recompilation?  If this is not a performance critical section of the code,
what is the point of this change?

This [PATCH 13/16] and also [PATCH 12/16] rewrite strings using qr// but
the patterns thus compiled are used exactly once before the control leaves
the scope of the variables, so...

It is a different story if the patch instead introduced module-level
global variables to hold a pre-compiled regexp objects, but that is not
what we are seeing here.

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 18:56

Subject: Re: [PATCH 13/16] send-email: extract_valid_address use qr// regexes and /o
Message-ID: <AANLkTin_b6eSnHgY2YCOfN7E83gEzrOpktUD3heOnfQw@mail.gmail.com>
URL: https://gitlist.dev/e/AANLkTin_b6eSnHgY2YCOfN7E83gEzrOpktUD3heOnfQw%40mail.gmail.com
In-Reply-To: <7vocbfjg7x.fsf@alter.siamese.dyndns.org>

```
On Thu, Sep 30, 2010 at 17:25, Junio C Hamano <gitster@pobox.com> wrote:
> Jeff King <peff@peff.net> writes:
>
>> ...
>> But we are unnecessarily compiling the sub-regexes each time. Not that
>> this is probably a performance critical piece of code, but your "/o" is
>> doing very little, and this is exactly the sort perl wankery that I find
>> interesting.
>
> Well, isn't the _sole_ point of using qr// to optimize by avoiding
> recompilation?  If this is not a performance critical section of the code,
> what is the point of this change?
>
> This [PATCH 13/16] and also [PATCH 12/16] rewrite strings using qr// but
> the patterns thus compiled are used exactly once before the control leaves
> the scope of the variables, so...

The point is to use Perl's data-types for what they're supposed to be
used for. In perl you *can* write:

    my $two = "1" + "1";

To get 2, but that's silly. You should just use integers instead of
string coercion:

    my $two = 1 + 1;

Similarly you *can* put regexes in strings, but perl has a first-class
datatype for it, so you should do:

    my $rx = qr/foo/;

Not:

    my $rx = "foo";

So it's just a change to use a better style. There are some tangible
advantages to using qr// over qq// (also known as ""), e.g. Emacs and
Vim will know to highlight the string as a regexp, and when the $rx is
interpolated Perl won't need to recompile it because it can just add a
pointer to the existing regex in the new pattern.

But the main reason here is to not write code that looks like it
targets Perl 5.5, but 5.8.

```

## Ævar Arnfjörð Bjarmason, 2010-09-30 19:03

Subject: [PATCH v2 13/16] send-email: extract_valid_address use qr// regexes
Message-ID: <1285873411-14045-1-git-send-email-avarab@gmail.com>
URL: https://gitlist.dev/e/1285873411-14045-1-git-send-email-avarab%40gmail.com
In-Reply-To: <1285854189-10240-14-git-send-email-avarab@gmail.com>

```
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---

Here's v2 which omits the confusing /o addition and just uses the more
correct qr// syntax over qq//.

 git-send-email.perl |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index b87c3f2..30000b9 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -777,8 +777,8 @@ our ($message_id, %mail, $subject, $reply_to, $references, $message,
 
 sub extract_valid_address {
 	my $address = shift;
-	my $local_part_regexp = '[^<>"\s@]+';
-	my $domain_regexp = '[^.<>"\s@]+(?:\.[^.<>"\s@]+)+';
+	my $local_part_regexp = qr/[^<>"\s@]+/;
+	my $domain_regexp = qr/[^.<>"\s@]+(?:\.[^.<>"\s@]+)+/;
 
 	# check for a local address:
 	return $address if ($address =~ /^($local_part_regexp)$/);
-- 
1.7.3.159.g610493

```

## Jeff King, 2010-10-01 05:40

Subject: Re: [PATCH 13/16] send-email: extract_valid_address use qr// regexes and /o
Message-ID: <20101001054029.GA18674@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20101001054029.GA18674%40sigill.intra.peff.net
In-Reply-To: <AANLkTimSHxU8EhuOHn77kw+ASCCeg_Bjg2or7L=G_o=M@mail.gmail.com>

```
On Thu, Sep 30, 2010 at 04:33:59PM +0000, Ævar Arnfjörð Bjarmason wrote:

> > But we are unnecessarily compiling the sub-regexes each time. Not that
> > this is probably a performance critical piece of code, but your "/o" is
> > doing very little, and this is exactly the sort perl wankery that I find
> > interesting.
> 
> IIRC different perl versions treat this differently. In more recent
> versions doing:
> 
>     perl -Mre=debug -E 'sub x { my $x = qr/foo/; my $y = qr/bar/;
> /$x$y/ } x($_) for 1..2'

Ah, right. I am used to using qr// with variable input (since that is
the intended use), but of course perl is smart enough to just need to
compile qr/constant/ once.

> Will only compile all of those regexes once, since perl can see that
> they're constant. So the /o does nothing.

Nice. I didn't think it would be smart enough to handle the layer of
indirection, but obviously it does. Go perl.

> We might want to keep it for self-documentation purposes to indicate
> that the $local_part_regexp would never change, but it's probably best
> to drop that /o altogether.

Yeah, I would just drop the /o. It will in all probability never change,
but it it _did_, I think having the /o just makes it buggy.

> Perl has static variables like that, just not in the ancient version
> we're pinned to:
> 
>     sub foo {
>         state $foo = qr/$_[0]/
>     }

Nice, I obviously have not kept up on my perl-changelog-reading. ;) But
yeah, it's not in 5.8. It's a moot point anyway, since as you
demonstrated above, perl is already doing the optimization.

-Peff

```
