Context Sensitivity

Someone give me an example of why Perl's context sensitivity is a good thing. I've not seen it do anything that wouldn't be done more cleanly in a language without it.


I'm not sure if what Perl does counts as "context-sensitive". The most that it does is imply one variable as an argument. This isn't any thing radical; it is merely a short-hand notation.

For example:

 #!/usr/bin/perl
 while (<>) {        # Read a line from stdin into the variable $_, until EOF.
  s/ugly/u***/g;     # Run a substitution on the implied $_.
  print;             # Print the result, again implying $_.
 }

Or, taking it even further:

 #!/bin/sh
 perl -pe 's/ugly/u***/' # Long story, but this is identical to the above.

I suspect that most people think "Confusing" when they hear "ContextSensitivity". Why would a language designer emphasize tersity, to the point of relying on context?

Well, it's a OnceAndOnlyOnce effort. When you're tossing out quick scripts to perform some manipulation on stdin, you don't want to have to write anything but the logic of your operation. Achieving this requires you to rely on context, or, more accurately, IntelligentDefaults.


Oops. Misunderstanding. That's not what I meant. I've heard Perl people use the term "context sensitivity" to refer to the way Perl uses punctuation in its variable names - @array is an array, $name is a scalar, $array[2] uses a dollar sign because it's returning a scalar, and so on.

The Perl books justify this by talking about natural languages - English has a way to distinguish between singulars and plurals, so Perl should too. Thing is, I write my variable names in English, so I've ALREADY got a way to distinguish between singulars and plurals. "people" is plural, "person" is singular. I don't need to call them "@people" and "$person". And it really scares me that I might type "$people" or "@people[2]" by mistake.

But I can get past that fear. I'm sure that if I took the time to get really good at Perl, I'd get really good at using the right punctuation, and it wouldn't be a problem. My question, though, is: what advantage does this context sensitivity give us? How does it help me write code that's more clear, has less duplication, is more modular? If the language didn't have this "feature," what bad thing would happen?

-- AdamSpitz

it really scares me that I might type "$people" or "@people[2]" by mistake

and so you should be: [http://slashdot.org/yro/01/03/13/208259.shtml Students arrested for confusing the list and scalar contexts in Perl.]


I think this is really important and useful, after all, we always speak in a context...

Context are two: scalar and list. Thus, an array yields itself in list context but its length in scalar context (the only scalar value a list can have).

 my @array = (1, 2, 3, 4, 5);

my $length = @array; # gives 5 my @array2 = @array; # assigns one to another

There are other interesting things:

 print $length, "\n";   # prints "5\n"

Because print has a list context... This means that:

 $, = ', ';       # set list separator to that string
 print @array;    # prints "1, 2, 3, 4, 5"

And we can even get this:

 my @a1 = ( 1, 2, 3);
 my @a2 = (1, 2, 3, 4, 5, 6); 
 my $length = () = ( @a1, @a2 ); 
 my $length2 = (@a1, @a2);

print $length, ' != ', $length2, "\n"; # prints "9 != 6\n"

Why? Because in the second case, we are taking the scalar value of the list expression formed by arrays @a1 and @a2, with the 'comma' operator, which yields its last operand (much like C). That's the length of @a2. In the first case we give the context explicitly (with that pair of parentheses, an empty list) and thus the whole right-hand expression is evaluated to list context, thus the length is 9.

Thus, context is very important and useful. Many Perl functions return different values according to their scalar or list context... This makes programming more intuitive and expressive... This is something I love of Perl... -- DavidDeLis


You've given me examples of how it works, but I'm still not sure why it's a good thing. Suppose that we translated all of the above examples into, say, RubyLanguage. Ruby doesn't have all that context stuff, but every line of code up there translates directly - we don't need to jump through any hoops in order to get around Ruby's lack of ContextSensitivity. The language is simpler without it, and just as expressive. (WhatIsExpressiveness??) What, then, has the ContextSensitivity bought us? The only other thing you mentioned was intuitiveness, and that's, um, debatable. :)

I don't mean to make anybody mad, though. This might be one of those things that I'm just not going to get.

--AdamSpitz

No problem. Let's just take the print command. Print command works on a list context. This means we can just do:

 my @array = ( 1, 2, 3 );
 print 'This is how @array is displayed: ', @array, "\n";

This prints "This is how @array is displayed: 123\n". Why? Because print expects a list of parameters to print, no need to concatenate what's passed to print (using . operator or a loop). Thus, @array is expanded to a list containing its elements and is feeded to print (print consults the value of variable $, before printing... in this case $, = q//).

 # same @array as before
 print '# of elements of @array is ', scalar @array, "\n";

We have to explicitly pass @array to an scalar context to get its length. It's not a length operator. scalar would have worked with a hash, or the output from grep, or unpack or any other perl builtin (or subroutine made by the programmer, by the way) and returned a sensible result (either a length, or number of keys or whatever... You can specify if you expect a list or a scalar context, and act accordingly. This allows a more free, natural way of programming, where you can count on the operation to return something sensible in the context you are working in a given moment... If you are working with sequences, list context (arrays or hashes or lists) and in scalar context, an scalar. This avoids lots of tricks with overloading or multiple functions for different cases or number of input parameters... By being complex, it makes things easier.


It sounds to me like we're down to an aesthetic argument. As far as I can tell, if you show me a piece of Perl code, I can show you an equivalent piece of Ruby code that's equally expressive, equally modular, equally OnceAndOnlyOnce - and you'd claim that the Perl is more elegant, and I'd claim that the Ruby is.

I can deal with that. Thanks.

(If you're interested in seeing Ruby equivalents to the Perl examples you've shown me, I can do that. I've avoided it so far, though, because I don't want this to turn into a LanguagePissingMatch. In your place, though, I'd be skeptical of these claims about Ruby. :)

--AdamSpitz

Oh, I like Ruby (at least more than I like Python :-) But things to come, I have always been able to do some task in Perl (even when I knew really little) and I haven't in Python or Ruby... Maybe it's the way my brain works... who knows? --DavidDeLis

Adam, won't you please show some Ruby code for the above examples? I'm interested in language comparisons.


EditText of this page (last edited November 9, 2014) or FindPage with title or text search