in reply to string context and list operators (was Re: Array in scalar context.)
in thread Array in scalar context.
1. The operation ($!+0) causes $! to be evaluated in numeric context because of the binary + operator. The parenthesis around $!+0 are necessary here because of the preceeding concatenation operator which is left associative and has the same precedence as that of binary + operator. Now, once $!+0 is evaluated in numeric context, to say number 2, does it again get evaluated in string context by the preceeding concatenation operator to string of one character i.e. "2" ?
2. Within a string, say "Hello World!", the default context is string context. So if I have,
@array is evaluated in string context inside "Hello @array World!" so as to yield a single string "perl monks" which is then interpolated into "Hello World!" so as to give "Hello perl monks World!".@array = (perl, monks); print "Hello @array World!";
prints: perlmonksprint @array;
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: string context and list operators (was Re: Array in scalar context.)
by jonadab (Parson) on Oct 05, 2003 at 20:28 UTC | |
1. The operation ($!+0) causes $! to be evaluated in numeric context because of the binary + operator. The parenthesis around $!+0 are necessary here because of the preceeding concatenation operator which is left associative and has the same precedence as that of binary + operator. Now, once $!+0 is evaluated in numeric context, to say number 2, does it again get evaluated in string context by the preceeding concatenation operator to string of one character i.e. "2" ? Yes. But because you added a constant (0), you're now evaluating the result of an addition, which is a number. You're no longer evaluating the variable $!, and so the string magic of $! doesn't come into play. Instead, the number (e.g., 2) gets stringified. 2. Within a string, say "Hello World!", the default context is string context. So if I have, @array = (perl, monks); print "Hello @array World!"; @array is evaluated in string context inside "Hello @array World!" so as to yield a single string "perl monks" which is then interpolated into "Hello World!" so as to give "Hello perl monks World!". Is this observation true? and is this what you are refering to as the "flattaned list" the join operator accepts ? Well, interpolation is different than ordinary string context (or flattened list of strings context, for that matter). Many things that would be evaluated in one fashion or another outside a string (even in string context) are evaluated differently inside a string. For example, consider the hash %foo. In list context, it will return a flat list containing each key and its corresponding value. In string context, it will return something different. (Try it: %foo=(bar=>3); print %foo."\n";.) If you try to interpolate it into a string, in Perl5 you get "%foo". (Way back in the day, it was decided that Perl should have the same sprintf syntax as C, and so when array interpolation was added, hash interpolation along the same lines couldn't be. This will be remedied in Perl6, which is revamping a lot of things that needed to be revamped.) Also, in Perl5, method calls don't interpolate. (In Perl6, they will.) So a method call that does one thing in string context will do something else when you try to interpolate it. If you like, you can think of interpolation as its own type of context. 3. Why does print @array; prints: perlmonks instead of: perl monks ? For the same reason that print 'perl', 'monks'; does the same thing. Remember, print flattens its list of arguments and deals with them individually, so if you pass it an array (or a list), it doesn't see the array (or the list) as a whole, but the individual elements. join does the same thing. push and pop do this with everything except their first argument (which must be an array). Many of the other list operators function this way as well, and if you write your own function that loops over @_, it will behave in this same way: you can pass it arrays, but they are flattened, and the function sees only the elements. When a function takes an array AS SUCH, like push and pop do with their first argument, that's a noteworthy and special feature of that function. If you think print should print something between the values it prints, assign a value to $" 4. What are all the contexts (like numeric context, string context) that exist which are variations of scalar context or list context? I might miss something, but the scalar contexts I can think of are string context, numeric context, general scalar context (created e.g. by assignment to a scalar variable, or by using the scalar keyword), boolean context (present in a condition), and there are also special contexts associated with specific Perl builtins, such as ref and defined and exists, which evaluate their arguments in special ways. Oh, and some people would add void context (where the return value is just thrown away), though I'm not sure that's scalar per se. Oh, you asked about list contexts too. Hmmm... Perl5's concept of list context is fairly basic, though of course the _elements_ of the list may be evaluated in a certain scalar context. (For example, print evaluates the elements of its argument list in string context, so you can think of the overall context supplied by print as flattened-list-of-strings if you like.) In Perl6, a lot more richness is being added to this, so that a function can supply an argument with for example a pairlist context. As far as I know Perl5 doesn't really have this. As an example of the difference, in Perl5 if your function is called as an argument to print, it can use the wantarray function to find out that it's being called in list context, but that's all: it can not determine that a list of strings is wanted, rather than a list of numbers for example. In Perl6 it will be possible for a function to use the want builtin to determine such things, and so it would be possible for a function to return one thing in list-of-strings context and return something different in list-of-numbers context and yet something different in list-of-pairs context -- perhaps pairs containing both the number and the string. Though, in practice, a Perl6 function would probably be more likely to return a list of objects that know how to provide the desired values in various contexts. That way if what the function returns value is assigned to an array for later use, there's no problem about knowing which kind of values are wanted.
| [reply] [d/l] [select] |
by Anonymous Monk on Oct 12, 2003 at 22:57 UTC | |
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 ? 4. In code prints Hello1World But, prints HelloWorld instead of Hello0World. So the print function stringifies boolean true value of the expression $!>0 to "1" but why not the boolean false value 0 to "0" ? 5. When a string is used in numeric context (say, in an expression such as: "h">=0 ) it returns 0 as it's value though a warning (such as: "Argument "h" isn't numeric in numeric gt (>)" ) is thrown. Speaking conversly, is there any case where a numeric value in string context returns empty string ? 6. davido (in his earlier reply to this thread) mentions that "If you could call wantarray on print it would return true. And so, @foo is evaluated in list context when evaluated as argument of 'print'" But if I try , it prints NO indicating that print doesn't want an array. So what did davido mean in his comment then? 7. 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) instead of the symantics of it ? Similarly when you say "print function flattens the list and processes each of the elements in string context, are you refering to it's symantics ? 8. The 'Learning Perl' book - 3rd Edition on page: 125 while describing "split" function mentions that split is an operator instead of a function. Can you please throw some light on this ? 9. You said that "Way back in the day, it was decided that Perl should have the same sprint syntax as C, and so when array interpolation was added , hash interpolation along the same lines couldn't be". Can you explain this little bit. I also tried this in C this prints: Hello abHello abHello ab hereBut not Hello a b c here 10. Can a Perl programmer code functions which do string magic like $! does ? i.e. If $! in numeric context returns 2, in string context, instead of returning stringified 0, it returns the string "No such file or directory". 11. If an array in scalar context returns it's length why wasn' the same thing done for lists as well? Is this due to a similar kind of reason such as sprintf style from C was not possible for hash interpolation ? 12. $count = () = $data =~ m/and/g; The $count has the value of number of times the pattern abc appears in $data. What magic that () is doing . Doesn't the operation $count = () cause the list to be operated in scalar context such as which shall cause $count to have the value of last element of the list which is "abc" instead of 3. Can () be used to force list context ? | [reply] [d/l] [select] |
by jonadab (Parson) on Oct 13, 2003 at 02:31 UTC | |
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.
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...
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...
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...
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.)
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.
(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.
| [reply] [d/l] [select] |
by tilly (Archbishop) on Oct 13, 2003 at 03:25 UTC | |
by Anonymous Monk on Oct 18, 2003 at 20:46 UTC | |
by jonadab (Parson) on Oct 19, 2003 at 04:30 UTC | |
by PodMaster (Abbot) on Oct 13, 2003 at 11:18 UTC | |
11. If an array in scalar context returns it's length why wasn' the same thing done for lists as well? Is this due to a similar kind of reason such as sprintf style from C was not possible for hash interpolation ?You should read "List" Is a Four-Letter Word. | [reply] |
by Anonymous Monk on Oct 13, 2003 at 11:25 UTC | |
7. 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) instead of the symantics of it ? Similarly when you say "print function flattens the list and processes each of the elements in string context, are you refering to it's symantics ?No. join is a function, not an operator. join, like all perl functions, takes lists as arguments (and conveniently provides them in the magical @_ array). join is context independent, observe
| [reply] [d/l] |
by jonadab (Parson) on Oct 13, 2003 at 14:05 UTC | |
by Anonymous Monk on Oct 13, 2003 at 11:37 UTC | |