[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