in reply to Re: Scalars, Lists, and Arrays in thread Scalars, Lists, and Arrays
Dominus,
Thank you for the explanation. Let me see if I have this right:
- There are two contexts in which an expression can be evaluated: scalar and list.
- There are three major types of variables in perl: scalars, arrays, and hashes. 'Scalar' variable type and 'scalar' context are not the same thing, although scalar variables usually impose scalar context.
- Expressions are either constants, the values of variables (either lvalue or rvalue), or the results of functions which may take other expressions as arguments.
So my principle error lies in trying to compare lists and arrays, which are different types of things. The confusion is partly caused by 'scalar' being both a context and a expression variable, and thus capable of being compared with either. Hence, comparisons are not transitive!
Is this right?
-Ton
-----
Be bloody, bold, and resolute; laugh to scorn
The power of man...
Re: Re: Re: Scalars, Lists, and Arrays
by merlyn (Sage) on Apr 13, 2001 at 17:37 UTC
|
I've also found it important to thump the desk when I'm teaching about this topic, over two very specific things:
- A list never gets produced in a scalar context.
- What a construct does produce in a scalar context must be learned,
not derived by any general rule.
So, if you learn about what @foo does in a scalar context,
that tells you nothing about what @foo[3..5] does
in a scalar context, or even what ($x,$y,$z) does in a scalar
context. You must learn them each individually.
As it turns out, there is a bit of consistency in it (it's not just random madness),
but that's available only after the fact. {grin}
-- Randal L. Schwartz, Perl hacker | [reply] [d/l] [select] |
|
I'll agree with your "A list never gets produced in a
scalar context", but only for certain values of "never",
"list", and/or "produced". :) That is an important concept
that needs to be stressed (though I'd put less stress on
the "never" part myself).
But, for the curious, see the last half of (tye)Re: Hash slices ?
for a specific example of what I consider to be a list of
SVs being (temporarily) produced despite a scalar context.
I'm not trying to contradict the above rule. I am
trying to prevent it from being "over interpreted", but
more than that, I think the example will help some people
understand the concept better.
-
tye (but my friends call me "Tye")
| [reply] |
Re: Re: Re: Scalars, Lists, and Arrays
by sierrathedog04 (Hermit) on Apr 13, 2001 at 20:07 UTC
|
There are other contexts as well. Camel III lists three of them. They are: -
Boolean context, such as when we test for the existence of values in an array.
while (@files) {
my $file = shift @files;
unlink $file or warn "Can't delete $file: $!\n;
}
- Void context. It is unclear from Camel III what this context does. The example Camel III gives is a statement consisting of the quoted string "Camel Lot"; Apparently the -w option on the perl interpreter does not like this context, and returns a warning on it. Maybe it's best to avoid this one altogether.
- Interpolative context, which occurs inside quoted strings when one includes a variable name. The substitution operator s/// and some other expressions also occur in interpolative context.
Boolean context is ubiquitous, so let's give this little brother of list and scalar its due!
| [reply] [d/l] |
|
Void context is where you have an expression (not to abuse Dominus' terminology too much) that doesn't go anywhere. For example, if you had:
open(FILE, $filename) or die "Can't open $filename: $!";
"nothing to see here";
close FILE;
Ignoring the fact that the program does nothing, the second line is a scalar expression (help me out here, if I abuse verbiage) in void context.
When you abuse map to iterate over a list and don't assign the results to anything, you're using map in void context.
It's generally not useful, but if you have an expression that can spend a lot of time creating a result value of some sort, it can be inefficient to use void context. | [reply] [d/l] |
|
| [reply] |
|
*sigh* let's not go overboard on what can and can't be
called a "context", either.
So-called "Boolean context" is a useful concept, especially
if you are dealing with overloaded objects. I agree that
it is important to realize that it isn't a "context" in the
same way that "scalar context", "list context", and
"void context" are and that using something in a
"Boolean context" is hard to distinguish from using it
in a scalar context (though it can be done by using
overloading). I'd love to see an enhancement that elevates
"Boolean context" to being a "first class context" (well,
at least "second class" if you don't count "void" as
"first class") by, for example, adding a OPf_WANT_BOOL flag.
"Interpolative context" can also be a valuable concept for
explaining why these are different:
print "@a";
print "".@a;
print @a;
even though it is very much different than the "big three"
contexts. This one reminds me of the "numeric", "string",
and "integer" pseudo contexts.
For built-in Perl operators, [void context] is
identical to scalar context
Doing a quick search, I found that keys knows the
difference between scalar and void context so that it can
avoid some work in the latter case. I suspect there are
more than a few other cases. I'm not trying to contradict
you, I just don't want others to overinterpret what you are
saying.
I guess that by "do something different" (in the case of
a user-defined function detecting void context) you are
referring to "side effects" and that you are asserting that
no built-in functions/operators of Perl have different
side effects between scalar and void context. I would
certainly be somewhat surprised to find a case that
violates such an assertion but I wouldn't feel comfortable
making that assertion myself.
I'd take issue with your using "context" to describe
the special way defined works but that would just seem
ornery of me. A similar "context" that I'm finding
increasingly interesting is the "pseudo code block context"
that is given to the first argument of map or grep:
map func($_), @list;
grep func($_), @list;
-
tye
(but my friends call me "Tye") | [reply] [d/l] [select] |
|
Void context ... Maybe its best to avoid this one altogether
Void context is where you're performing an operation and
doing nothing with the result. That is,
#!/usr/bin/perl -cw
"String";
tells me:
Useless use of a constant in void context at - line 2.
In fact, I care about this because it generally indicates a problem with my program.
What use is a constant where I don't store what that constant is?
Void context can be useful. Consider:
grep { s/\s+$// } @lines;
which will remove all trailing whitespace from all the lines
I have in @lines. grep normally returns the lines
that matched the pattern. But because I'm in void context,
the values just get thrown away and all I'm left with is
@lines which contains every line missing its trailing
whitespace. (By the way, the better way to do that is:
foreach (@lines) { s/\s+$// } ).
Consider also that some objects require methods to be run
in void context. While you're not just throwing away
their values, these things have side effects that perform
useful work. For example, in CGI, you can do:
$cgi->import_names('R');
which, while run in void context, imports all parameters
into the 'R' namespace.
So, in summary, -w isn't complaining because
you're running things in void context. It's complaining
because you're running in void context without doing
anything that could be construed as useful.
Update: D'oh, chromatic beat me to it. | [reply] [d/l] [select] |
|
|