The wantarray function can be used inside of a subroutine
definition to determine the context in which that subroutine is
called.
Yes, exactly.
By default, such a context is available to the return
statement of the subroutine.
Well, you could view it that way, insofar as whatever expression
you are returning (either by explicit return or implicitely by
virtue of its being the last thing evaluated in the function)
will be evaluated in the supplied context, yes. But if you want
to return something entirely different in different contexts, then
you use wantarray (or, in Perl6, want).
Is the real usage of wantarray just limited to using
inside of a subroutine?
Yes, wantarray tells you the context in which the current routine
was called. Now, that routine can be a named sub, or it can be an
anonymous sub ("closure"), or a method. In Perl6 it can also be a
multimethod or (I think) a rule. All of these you can think of as
one type or another of subroutine, so the statement "wantarray
tells you the context in which the current subroutine was called"
still holds true irrespective of which exact type of subroutine
that is.
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.
Yes, exactly.
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.
Basically, yes. Some people will tell you that there are two
different comma operators, one that operates in scalar context and one
that operates in list context, but even if you view it that way, it
is still true that the list context is present because that is what
print supplies; if you were to replace print with a function that
supplies scalar context, test_wa would not be called in
list context. (Actually, it would be called in void
context, because only the last value of the "list" would
be wanted. People who believe in two different comma
operators would say that the scalar comma always supplies
void context to its left operand. I prefer to think that
Perl knows only the last value of the list is wanted and
evaluates the others in void context. Either way,
test_wa is called in void context.)
sub print_context {
if (not defined wantarray) {
print "[void context]";
} elsif (wantarray) {
print "[list context]";
} else {
print "[scalar context]";
}
return undef;
}
"Hello", print_context, "World\n"; # void context
print "\n";
"Hello " . print_context . "World\n"; # scalar context
print "\n";
print "Hello " . print_context . "World\n"; # scalar context
print "\n";
print "Hello", print_context, "World\n"; # list context
print "\n";
join print_context, # scalar context
print_context, print_context; # both list context
print "\n";
Is this what davido meant by "IF YOU COULD call wantarray
on print function it would return true."
Yes.
and am I successful in calling wantarray on print function
(i.e. in the case of second print function)?
Indirectly, yes.
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?
Yes. If you put that code inside a subroutine, it will print something
different depending on the context in which you call that 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"?
I was talking about the same thing you were just now talking about:
wantarray takes its notion of context from the current routine,
not necessarily the immediate local grammatical construct. This
is actually useful; if wantarray took its notion of context from the
immediate context, you would not be able to test it easily, because
your test condition would always supply a boolean context. For example
if we had a mythical immediate_context operator that returned the
immediate context in which it was called, and we tried to use it, ...
print (immediate_context?"list":"scalar or void");
we would always get "scalar or void", even though print supplies
a list context, because the trinary operator (foo?bar:baz) supplies
boolean context (which is a type of scalar context) to its leftmost
operand. So, ...
print_context() ? print_context() : print_context();
print "\n";
This prints
"[scalar context][void context]",
because the boolean
context in which the first print_context is called
is scalar, and
so the second one (between the ? and the :) is not called, and the
third is called in void context.
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;
}
The trinary operator supplies boolean context to its leftmost
operand. The middle or right operand (whichever is evaluated) is
evaluated in the context inherited from the context in which the
whole expression is found. In this case, the expression is the
last thing evaluated in the subroutine, so it is an implicit
return, and so it inherits the context in which the routine was
called. Try these:
print_context() ? print_context() : print_context();
print "\n";
print print_context() ? print_context() : print_context();
print "\n";
print join(print_context() ? print_context() : print_context()), print
+_context(), "\n";
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 ?
Flattening. Just as an array is in this context not a single
argument, but is "flattened" into its elements, so also a
subroutine call is "flattened" into as many elements as it
can provide, which all become part of the list that the
function (in this case print) sees. This happens anytime
a function calls for a flat list, which is the default for
all functions that do not explicitely set a different prototype.
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,
This "documentation" you were looking at
was someone's suggestion (Damian Conway's suggestion, as it
happens) for how things ought to be in Perl6. If you want to see
the answer to this suggestion, and an explanation of how this
will actually be in Perl6, see
Apocalypse 6.
For a simpler explanation (by, as it happens, the same Damian Conway who wrote
the suggestion you looked at), see
Exegesis 6.
If what you wanted was the documentation for the Want module for Perl5,
you want to look for it on search.cpan.org (which is, generally, the
best place to find documentation for many modules).
If the return value of an expression is, undef or "" or number 0
would they all evaluate to false value in boolean context?
Yes. undef, "", and 0 are all false in boolean context. Also, "0" if
I am not mistaken is false in boolean context. However, "0.0" or "0 but true"
(as strings) are true. Also, a list containing a single value which is undef
is true. When undef is the entire list, it is considered to be a list containing
no elements, and _that_ would be false, but if undef is an element in the
list, then the list contains elements (at least one element) and therefore
is true. Usually, this is all exactly what you would intuitively think,
but occasionally it can be handy to know exactly what is what.
Can we confirm from the below program that, the internal value of
undef is the ASCII null value (ie. ASCII code: 0)
Not necessarily. For one thing, the ASCII null in Perl does not have
the same semantics in a string as it does in C. It is just another
character, in fact, with no special meaning at all to Perl. I believe
undef in Perl is like nil in lisp: it is a value in its own right,
distinct from other values such as zero. (Also, it may not be entirely
a conincidence that both undef in Perl and nil in lisp are synonymous
with an empty list containing no elements. Perl probably borrowed this
idea from lisp or one of its derivatives.)
The reason it evaluates to the empty string in string context
and zero in numeric context is because Larry Wall thinks (probably
rightly) that this is the least unexpected thing for it to do in those
circumstances, not because of the way it is stored internally. Perl,
generally, tries to do what is right, or what is wanted, or what makes
sense, rather than basing its behavior on lowlevel implementation details.
There are places where the implementation details leak through, but I
do not think this is one of them.
$count = () = $s =~ /abc/g;
I still intend to get to that...
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.
Several different sources. The information about sprintf I've had
in my head for some time and am not sure exactly when or where I
discovered it. My 2nd edition Camel book mentions that sprintf
formattiong codes work the same way in Perl as in C, but somewhere
along the line I believe I have been told by someone that this was
present in Perl4. As far as arrays not interpolating in older
versions of Perl, I picked this up when I was new, by trying this:
print "jonadab@bright.net";
In Perl 5.0 through 5.6, this will give you an error, telling you
that the @ symbol needs to be escaped; in 5.8, it no longer does
this (though if you use warnings you will get a "Possible
unintended interpolation" warning). But in 5.0 this behavior was new,
and so the error message was included so people would know what was
going on when they got "jonadab.net" and wondered where the rest of
their email address went. The information about Perl6 mostly comes
from reading the Apocalypse articles and to a lesser extent the
perl6-language mailing list. I think I may also have picked up
from the Perl6 sources the idea that hash interpretation was not
possible in Perl5 because it would conflict with the sprintf syntax,
or I may have figured that out on my own. If you think about it,
it's obvious that if printf "%02d", 3 gives you
"03", then it can't also interpolate the hash named %02d. But
in Perl6, printf will be handled another way, or such is my
understanding, based on Apocalypse 2.
$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}}
split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
| [reply] [d/l] [select] |