Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
248 views
in Technique[技术] by (71.8m points)

perl - Concerns with concatenating strings and ints

I have taken a principles of programming class and have been given a Perl expression that concatenates a string number to an int number and then adds another number to it and it evaluates fine. i.e. ("4" . 3) + 7 == 50.

I'm trying to understand why Perl does this and what concerns it may bring up. I'm having a hard time grasping many of the concepts of the class and am trying to get explanations from different sources apart from my horrible teacher and equally horrible notes.

Can the concept behind this kind of expression be explained to me as well as concerns they might bring up? Thanks in advance for the help.

Edit: For Clarity

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Perl is built around the central concept of 'do what I mean'.

A scalar is a multi purpose variable type, and is intended to implicitly cast values to a data type that's appropriate to what you're doing.

The reason this works is because perl is context sensitive - it knows the difference between different expected return values.

At a basic level, you can see this with the wantarray function. (Which as noted below - is probably badly named, because we're talking about a LIST context)

sub context_test {
    if ( not defined wantarray() ) {
        print "Void context
";
    }

    if ( wantarray() ) {
        return ( "List", "Context" );
    }
    else {
        return "scalar context";
    }
}

context_test();
my $scalar = context_test();
my @list   = context_test();

print "Scalar context gave me $scalar
";
print "List context gave me @list
";

This principle occurs throughout perl. If you want, you can use something like Contextual::Return to extend this further - testing the difference between numeric, string and boolean subsets of scalar contexts.

The reason I mention this is because a scalar is a special sort of data type - if you look at Scalar::Util you will see a capability of creating a dualvar - a scalar that has different values in different contexts.

my $dualvar = Scalar::Util::dualvar ( 666, "the beast" );

print "Numeric:",$dualvar + 0,"
";
print "String:",$dualvar . '',"
";

Now, messing around with dualvars is a good way to create some really annoying and hard to trace bugs, but the point is - a scalar is a magic datatype, and perl is always aware of what you're doing with the result.

If you perform a string operation, perl treats it as a string. If you perform a numeric operation, perl tries to treat it as a number.

my $value = '4'; #string;
my $newvalue = $value . 3; #because we concat, perl treats _both_ as strings. 
print $newvalue,"
";

my $sum = $newvalue + 7; #perl turns strings back to numbers, because we're adding;
print $sum,"
";

if (     Scalar::Util::isdual ( $newvalue ) ) { print "newvalue Is a dual var
" };
if ( not Scalar::Util::isdual ( $sum )      ) { print "sum is NOT a dual var
"; };

Mostly 'context' is something that happens behind the scenes in perl, and you don't have to worry about it. If you've come from a programming background, the idea of implicit casting between int and string may seem a little bit dirty. But it mostly works fine.

You may occasionally get errors like: Argument "4a3" isn't numeric in addition (+)

One of the downsides of this approach is these are runtime errors, because you're not doing strong type checking at 'compile' time.

So in terms of specific concerns:

  • You're runtime type checking, not compile time. If you have strict types, you can detect an attempt to add a string to an int before you start to run anything.

  • You're not always operating in the context that you assume you are, which can lead to some unpredictable behaviour. One of the best examples is that print operates in a list context - so to take the example above:

    print context_test();

You'll get List Context.

  • If you monkey around with context sensitive return types, you can create some really annoying bugs that are immensely irritating to back trace and troubleshoot.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...