in reply to Re: Re: string context and list operators (was Re: Array in scalar context.)
in thread Array in scalar context.
1. Is a string context same as scalar context where the scalar value is "stringified" ? 2. Is a numeric context same as scalar context where the scalar value is turned to numeric so as to perform any numeric operation ? 3. Is a boolean context same as scalar context where the scalar value is booleanized ?
Sort of, but not really, or at least not always. perl may sometimes work that way internally, but I don't think of it that way in Perl as a language. In particular, some things return entirely different values depending on which type of scalar context they are in. For example, $! has magic that allows it to return an error number in numeric context but return an error description in string context. The description is not just an ordinary stringification of the number. Sure, $! is internal Perl magic, but see also the Want module, which allows user code to distinguish (e.g.) boolean context from other kinds of scalar context. There will be even more of this sort of thing in Perl6. Also, with regard to boolean context, it is noteworthy that some of the operators you might think of as boolean (&&, ||, and, or) do not supply boolean context to their operands, but rather a generic scalar context. (This is why $foo = $bar or $baz works the way you want.) The condition of an if clause does, however, supply boolean context, or such is my understanding.
4. (...) So the print function stringifies boolean true value of the expression $!>0 to "1" but why not the boolean false value 0 to "0" ?
I think false stringifies to the empty string.
my $bool = not (1==1); if ($bool eq "") { print "False stringifies to the empty string.\n" } else { print "Nope.\n" }
Speaking conversly, is there any case where a numeric value in string context returns empty string ?
None that I'm aware of. Zero returns "0" in string context, of course. However, here are a couple of things that are fun to try...
my $bignum = 1000; for (1..1000) { $bignum *= $bignum } print "bignum is now $bignum\n"; my $epsilon = 1/$bignum; print "epsilon is now $epsilon\n";
I could have sworn there used to be a way to get a result that was NaN (Not a Number), but I can't seem to find an example of that right now. Maybe it involved using a math module or something. All I get when I try to produce it is an error.
davido (in his earlier reply to this thread) mentions that "If you could call wantarray on print it would return true.
Yes, that's right, but...
print wantarray ? YES : NO , "\n";
Two things here: first, wantarray tells you what the current subroutine wants, and does not extend down to smaller constructs, which is why davido said, "if you could". Second, in the above code, you are not calling wantarray in the context that print supplies, but in the context that the trinary ?: operator supplies, which is scalar, so even if wantarray _did_ work on things smaller than subroutines (which it doesn't), that code still wouldn't do what you want.
When you said in your first reply that, "join function is a list operator, like print" are you refering to the syntactial behavior of print (because it can take an array as one of it's arguments)
print and join both take a flattened list; it is not quite right to say that either of them "can take an array as one of its arguments". Rather, either of them can take some of its arguments from an array. So, print @foo, @bar has the same effect as @args = @foo; push @args, @bar; print @args; and similarly with join. And yes, semantically they both then procede to treat the individual arguments (the _elements_ of the list they are passed) with a string context. This is not at all the same as treating the arrays in string context (which would count the elements in the array and stringify the resulting number).
split is an operator instead of a function. Can you please throw some light on this?
Well, in Perl you can use an operator as a function and vice versa...
my $foo = 3; my $x = print($foo) + 7; # There we used print (which is a list operator) as # a function; it returns true, which in numeric # context is 1. $x is now 8 print "\n"; sub mult { # Declare a function... print "Entering function bar\n 1"; # Here print is used as a statement. my $product = 1; for (@_) { $product *= $_; print " * $_" } print " = $product\nExiting function bar\n"; return $product; } print mult 42, $x; # Here print is used as a statement, # but mult (a function) is used as a list operator. print "\n";
If we wanted to be more clever, we could write our mult function so that in scalar context it returns the product, but so that in list context it would returns all the numbers and multiplication signs, equal sign, and product showing the whole multiplication. In Perl6 we'll be able to go one better and write it so that in numeric context it returns just the product, in list context all the numbers and the product, and in string context an equation showing the multiplication. Better, it could return a "multiplaction" object that knows how to represent itself in all of these ways on demand, so that we could call the function once, do something with the product immediately, but hang onto the whole problem and later reproduce the list of numbers that were multiplied together or if desired print out the whole equation. This sort of thing would be great e.g. if we were building a Huffman tree. (Okay, so that's addition not multiplication; anyway, Perl6 is going to be entirely too cool.)
So anyway, as I was saying, Perl blurs the distinction between operators and functions. In fact, I'm pretty sure you can use split as a function...
print join "\n", split(/\s+/,"Just Another Perl Hacker"), "\n";
So, without reading the larger context of the chapter, I'm not sure what point the author of Learning Perl was trying to make. (I've never read it. I started with Programming Perl.)
int main() { char buf[50]; char a[] = {'a', 'b', 'c'}; sprintf (buf, "Hello %s here\n", a); printf ("%s", buf); }
Well, my knowledge of C is somewhat less advanced than my knowledge of Perl (translation: I don't know C worth beans), but my understanding is that you need one formatting code (e.g., %s) for each item you pass. Note that it is the formatting codes (e.g., "%s") that are the same as in Perl as in C. The call syntax for the function, of course, is different, to say nothing of the difference in the way strings are handled in general.
Can a Perl programmer code functions which do string magic like $! does?
In Perl5 I think that kind of magic requires XS. (i.e., you have to write part of your Perl module in C). However, you might look for existing modules, e.g., Want, which might (depending on what you need to do) save you from needing to write any XS yourself. Update: see tilly's better answer on this point. In Perl6 this will be improved further with the introduction of the new want builtin, which will replace wantarray and be much, much more general (and therefore will be much more useful).
If an array in scalar context returns it's length why wasn' the same thing done for lists as well?
I don't know why. It doesn't, though. A list in scalar context returns one element from the list. This might change in Perl6. Meanwhile, if you need a count of the number of items in a list, you can always throw it in an array. If you don't want to use a named array, you could use an anonymous array.
my $count = @{[@foo, @bar, @baz]}; print "There are $count elements altogether between the three arrays.\ +n";
(But note that the above code makes a temporary copy of all three arrays, so if they have lots of elements it would be more efficient to call them in scalar context individually and add up the results.)
Is this due to a similar kind of reason such as sprintf style from C was not possible for hash interpolation?
I don't think so, but I don't know enough about C to be absolutely certain.
$count = () = $data =~ m/and/g;
I'm not sure exactly what's going on here. The () does, I think, cause the =~ operator to be in list context, but beyond that I'm not sure what magic causes $count to come out as a number instead of "and". It may be that what I'm missing has to do with the difference between m/foo/g and s/foo/bar/g. The latter I use much more frequently than the former, but they work differently. I'll try to remember to look into that and reply again if I figure out exactly what's going on there.
$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Re: string context and list operators (was Re: Array in scalar context.)
by tilly (Archbishop) on Oct 13, 2003 at 03:25 UTC | |
|
Re: Re: string context and list operators (was Re: Array in scalar context.)
by Anonymous Monk on Oct 18, 2003 at 20:46 UTC | |
by jonadab (Parson) on Oct 19, 2003 at 04:30 UTC |