[Purdue-pm] Perl 5's '{' .. '~' "broken"
Mark Senn
mark at purdue.edu
Fri Oct 5 12:32:48 PDT 2018
Joe Kline wrote on 2018-10-05 at 1346 -04:
| Broken or working as documented?
|
|
| http://perldoc.perl.org/perlop.html#Range-Operators
|
| "If the initial value specified isn't part of a magical increment
| sequence (that is, a non-empty string matching /^[a-zA-Z]*[0-9]*\z/ ),
| only the initial value will be returned."
|
| Also, looking at the example in perldoc if you change your code from:
|
| push @r, (ord $_[$i] .. ord $_[$i+1]);
|
| to
|
| push @r, (ord "$_[$i]" .. ord "$_[$i+1]" );
|
| It will work as intended I think.
|
| joe
Hi Joe,
I put broken in quotes because it violates the
priciple of least astonishment in my opinion. See
https://en.wikipedia.org/wiki/Principle_of_least_astonishment
for more info on that. I saw the "If the initial value ..." text
when "reading the fine print" trying to figure out why the simple
way of doing this didn't work.
The code I wrote works with
push @r, (ord $_[$i] .. ord $_[$i+1]);
or
push @r, (ord "$_[$i]" .. ord "$_[$i+1]" );
with Perl 5.28.0. I skipped the quotes because
I didn't want the extra clutter.
I changed some of the comments in the code to make it more
clear that the top part didn't work as expected and that's
why I wrote the code in the bottom part.
-mark
p.s. here's the new program (same code, slightly different comments
as written about above)
#!/usr/new/bin/perl
# In Perl 5
# my @s = ('{'..'~', 'a'..'c');
# print "@s\n";
# prints
# { a b c
# instead of
# { | } ~ a b c
#
# _Modern Perl: 2011--2012_ edition at
# http://modernperlbooks.com/books/modern_perl/chapter_04.html
# states
# The infix range operator (..) produces a list of items in list context:
# my @cards = ( 2 .. 10, 'J', 'Q', 'K', 'A' );
# It can produce simple, incrementing ranges (both as integers or strings),
# but it cannot intuit patterns or more complex ranges.
#
# Apparently '{'..'~' is a range that Perl 5 does not understand.
#
# Because the easy way ('{' .. '~') to do this didn't work for me I
# wrote the following code below to get the ordinal character values
# needed. I didn't use charnames (https://perldoc.perl.org/charnames.html)
# becaue I wanted to be absolutely sure what characters I was dealing with.
use feature 'say';
sub Ranges
{
# The return value.
my @r = ();
(@_ == 0) and die 'Ranges called with no arguments';
(@_ % 2) and die 'Ranges called with an odd number of arguements';
# Process a character range.
for (my $i = 0; $i < @_; $i += 2)
{
push @r, (ord $_[$i] .. ord $_[$i+1]);
}
return @r;
}
my @a = Ranges qw+{ ~ a c+;
say "\@a is @a";
my @b = Ranges qw+A Z a z+;
say "\@b is @b";
my @c = Ranges qw+! / 0 9 : @ [ ` { ~+;
say "\@c is @c";
my @d = Ranges qw+0 9 A Z a z+;
say "\@d is @d";
# -mark
More information about the Purdue-pm
mailing list