Thank you for your detailed responses. This relly helps in understanding the concepts. It took me sometime to go over your answers. Based on these here are the questions I have. Please let me know your answers. Thanks much
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
$! = 10;
print "Hello", $!>0, "World\n";
prints Hello1World
But,
$! = 0;
print "Hello", $!>0, "World\n";
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 ,
print wantarray ? YES : NO , "\n";
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
int main()
{
char buf[50];
char a[] = {'a', 'b', 'c'};
sprintf (buf, "Hello %s here\n", a);
printf ("%s", buf);
}
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
$count = ("abc", "abc", "abc")
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] |
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$/
| [reply] [d/l] [select] |
Thanks again for your reply. Since I am new to PERL it takes a long time to go through the responses and understand them. Once again here are my questions. Thanks for your help.
1. On wantarray/want and context
(a) what I understand by the definition of wantarray
The wantarray function can be used inside of a subroutine definition to determine the context in which that subroutine is called. By default, such a context is available to the return statement of the subroutine. But if the context is to be known in other parts of the definition of the subroutine then wantarray needs to be used. Is this observation true ? Is the real usage of wantarray just limited to using inside of a subroutine ?
(b) In the program,
sub test_wantarray{
wantarray ? Y : N;
}
print "Hello" . &test_wa . "World\n";
print "Hello", &test_wa, "World\n";
output:
HelloNWorld
HelloYWorld
In the first print function, the concatenation operator supplies the context to subroutine test_wantarray. Hence wantarray from inside of test_wantarray finds this context to be a scalar context and returns N. In the second print function, since the comma operator (,) doesn't supply a context of it's own, the subroutine test_wantarray is operating under the context supplied by print function. Hence wantarray from inside of test_wantarray finds this context to be list context and hence returns Y. Is this what davido meant by "IF YOU COULD call wantarray on print function it would return true." and am I successful in calling wantarray on print function (i.e. in the case of second print function)?
(c) Since the above subroutine test_wantarray is just one line, if the subroutine call is replaced in the above print function to be,
print "Hello", (wantarray ? Y : N), "World\n";
it prints: HelloNWorld. Is it that wantarray can only be used inside a subroutine? Can you explain about what you mentioned earlier? i.e. "you are not calling wantarray in the context that print supplies, in the context that ternary operator supplies" ?
If the ternary operator context is scalar how can it return a list if the expression for this ternary operator evaluates to true and an array is to be returned? i.e. in cases such as,
sub test_wantarray{
wantarray ? @array: \@array;
}
Why this scalar context of ternary operator doesn't come into play inside of the subroutine test_wantarray ?
(d) Refering to the print function in the above sub section (b)
print "Hello", &test_wa, "World\n";
returns true confirming that the print function is providing a list context to it's arguements. If such is the case,
why provide a list context to it's arguments only to see to it that print cannot operate on them (or rather it has to flattens them)? Why not just provide a "flattened list context" where the argument list/array isn't seen but only the individual elements within the list/array ? i.e. in your earlier reply you mentioned "print and join both take a flattened list". What am I missing here ?
(e) I looked at want module documentation (http://dev.perl.org/perl6/rfc/21.html) but wasn't able to understand. Is the real use of this,
(i). want should be able to distinguish between various type of scalar contexts or various type of list contexts when used inside of a subroutine . Can you please provide an example ?
(ii). how does it get down to small constructs (as opposed to wantarray) ? Can you please provide an example ?
2. If the return value of an expression is, undef or "" or number 0 would they all evaluate to false value in boolean context?
3. Can we confirm from the below program that, the internal value of undef is the ASCII null value (ie. ASCII code: 0)
if (undef eq "")
{
print "undef evaluates to empty string in string context\n";
}
if (undef == 0)
{
print "undef evaluates to zero in numeric context\n";
}
4. In the below code
$count = () = $s =~ /abc/g;
Did you get any chance to find out what exaclty causes $count to return the number of times abc appears in $s instead of abcwhen you mentioned that "....I'm not sure what magic causes $count to come out as a number instead of "abc". 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."
5. Just wanted to know, where did you come accross the information that your earlier mentioned i.e. "....way back in the day it was decided that the array interpolation inside double quoted string should have the same syntax as that of sprintf of C. So when array interpolation was added, hash interpolation along the same lines couldn't be. This will be remedied in PERL 6....". I just needed this detail just to understand why hash interpolation couldn't be added.
| [reply] [d/l] [select] |
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
use strict;
use warnings;
my @stuff = 1 .. 10;
print( join(' a ',@stuff), $/ );
print( scalar join(' a ',@stuff), $/ );
__END__
1 a 2 a 3 a 4 a 5 a 6 a 7 a 8 a 9 a 10
1 a 2 a 3 a 4 a 5 a 6 a 7 a 8 a 9 a 10
| [reply] [d/l] |
print( join(' a ',@stuff), $/ );
print( scalar join(' a ',@stuff), $/ );
Yes, but...
print scalar join ' a ', @stuff, $/;
In this last example, join will take the $/ as
just one more argument, with the result that
you'll get one last " a " after the 10, before
the newline. The reason it does this is because
of join's behavior as a list operator. Just about
any function in Perl will behave this way, if it
is called this way. print is usually called this
way, but just about anything can be. Like I said,
Perl blurs the distinction between functions and
operators. Context, as in most of Perl, is
everything. One is almost tempted to say that
Perl is a context-oriented language and that this
could be viewed as an entirely separate paradigm,
an alternative to imperative or object-oriented or
functional programming. Almost.
$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}}
split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
| [reply] [d/l] [select] |
join, like all perl functions, takes lists as arguments (and conveniently provides them in the magical @_ array).
Another good example is substr.
It can be used in lvalue context ( special context for subroutines, means you can assign to their result)
use strict;
use warnings;
my $a = 'abcdefg';
print $a,$/;
print substr($a,0,3),$/; # rvalue (list)
print $a,$/;
print substr($a,0,3)='bob',$/; # lvalue
print $a,$/;
print scalar( substr($a,0,3,'ABC')),$/; # rvalue (scalar)
print $a,$/;
__END__
abcdefg
abc
abcdefg
bob
bobdefg
bob
ABCdefg
As you can see substr has special behaviour in lvalue context.
RValue means the result is treated as an ordinary value. | [reply] [d/l] |