perl6 grammar actions: unable to make anything if not using $/ - match

I wrote a test program, and now it seems that if I don't use $/ in a
method signature because I have to use .match inside the method, I can no long make anything. What did I do wrong?
A further question is that if .match sets $/, and $/ is read-only, then I cannot have $/ in the signature of a method that contains a .match statement, and I cannot have more than one .match inside the method because each .match will try to set the read-only $/. This will be very awkward to program.
Here is the test program with only one .match statement inside and the results:
The test program:
grammar test {
regex TOP { <foo><bar> }
regex foo { :i \s* foo \s* }
regex bar { :i \s bar \s* }
}
class actTest {
method foo ($x) { # program fails if I use $/ in signature
print "1 "; say $x; # how to combine the 2 and show $x as match?
print "2 "; say $x.WHAT;
my $newStr = $x.Str;
print "3 "; say $newStr;
my $newMatch
= $newStr.match(/:i(f)(oo)/); # adverb cannot be outside?
print "4 "; say $newMatch.WHAT;
print "5 "; say $newMatch;
print "6 "; say $/;
my $oo = $newMatch[1].Str;
print "10 "; say $oo;
my $f = $newMatch[0].Str;
print "11 "; say $f;
my $result = $oo ~ $f;
print "12 "; say $result;
make $result; # now I cannot make anything; huh???
}
method TOP ($/) {
print "8 "; say $<bar>;
print "9 "; say $<foo>.made; # failed, method 'foo' makes nothing
make $<bar> ~ $<foo>.made;
}
}
my $m = test.parse("Foo bar", actions => actTest.new);
print "7 "; say $m;
And the results:
1 「Foo 」
2 (Match)
3 Foo
4 (Match)
5 「Foo」
0 => 「F」
1 => 「oo」
6 「Foo」
0 => 「F」
1 => 「oo」
10 oo
11 F
12 ooF
1 「Foo」
2 (Match)
3 Foo
4 (Match)
5 「Foo」
0 => 「F」
1 => 「oo」
6 「Foo」
0 => 「F」
1 => 「oo」
10 oo
11 F
12 ooF
8 「 bar」
9 (Any)
Use of uninitialized value of type Any in string context.
Methods .^name, .perl, .gist, or .say can be used to stringify it to
something meaningful.
in method TOP at matchTest.pl line 28
7 「Foo bar」
foo => 「Foo」
bar => 「 bar」

1) How to make without $/
make ... is just a shortcut for $/.make(...).
If you want to affect a different Match object than the one stored in $/, you have to use the method form directly, i.e. in your case $x.make($result).
2) When and why $/ is read-only
By default, $/ is bound to a normal item container (like a variable declared with my), i.e. not read-only. So there shouldn't be any problem with using the .match method multiple times in a routine.
It's only when you explicitly declare $/ as a parameter in a routine signature, that $/ will be bound directly to the Match object passed to that routine (not wrapped in an item container), and will thus be read-only inside the routine – because that's how normal signature binding works.
You could use the is copy trait to override the normal read-only parameter binding, and force $/ to be a mutable item container inside the routine:
method foo ($/ is copy) { ... }
This way, using .match inside the routine would work, and would store a new Match object in $/. But then you wouldn't have access to the original Match object passed to the routine anymore, and thus couldn't affect it with make. So for an action method that needs to use .match, using a custom parameter name like you did is the way to go.

Related

How to grok (and modify) this Perl statement

I am new to Perl.
How do I interpret this Perl statement?:
my( $foo, $bar ) = split /\s+/, $foobar, 2;
I know that local variables are being simultaneously assigned by the split function, but I don't understand what the integer 2 is for - I'm guessing the func will return an array with two elements?.
Can a Perl monger explain the statement above to me (ELI5)
Also, on occasion, the string being split does not contain the expected tokens, resulting in either foo or bar being uninitialized and thus causing a warning when an attempt is made to use them further on in the code.
How do I initialize $foo and $bar to sensible values (null strings) in case the split "fails" to return two strings?
The split function takes three arguments:
A regex that matches separators, or the special value " " (a string consisting of a single space), which trims the string, then splits at whitespace like /\s+/.
A string that shall be split.
A maximum number of resulting fragments. Sometimes this is an optimization when you aren't interested in all fields, and sometimes you don't want to split at each separator, as is the case here.
So your split expression will return at most two fields, but not neccessarily exactly two. To give your variables default values, either assign default values before the split, or check if they are undef after the split, and give the default:
my ($foo, $bar) = ('', '');
($foo, $bar) = split ...;
or combined
(my ($foo, $bar) = ('', '')) = split ...
or
my ($foo, $bar) = split ...;
$_ //= '' for $foo, $bar;
The //= operator assigns the value on the RHS if the LHS is undef. The for loop is just a way to shorten the code.
You may also want to carry on with a piece of code only when exactly two fields were produced:
if ( 2 == (my ($foo, $bar) = split ...) ) {
say "foo = $foo";
say "bar = $bar";
} else {
warn "could not split!";
}
List assignment in scalar context evaluates to the number of elements assigned.
The 2 is the maximum number of components returned by split.
Thus, the regexp /\s+/ splits $foobar on clumps of whitespace, but will only split once, to make two components. If there is no whitespace, then $bar will be undefined.
See http://perldoc.perl.org/functions/split.html
In addition to amon's method, Perl has a defined(x) function that returns true or false depending on whether its argument x is defined or undefined, and this can be used in an if statement to correct cases where something is undefined.
See http://perldoc.perl.org/functions/defined.html
As stated here: http://perldoc.perl.org/functions/split.html
"If LIMIT is specified and positive, it represents the maximum number of fields into which the EXPR may be split;"
For example:
#!/opt/local/bin/perl
my $foobar = "A B C D";
my( $foo, $bar ) = split /\s+/, $foobar, 2;
print "\nfoo=$foo";
print "\nbar=$bar";
print "\n";
output:
foo=A
bar=B C D

Does Perl support named parameters in function calls?

In my experience of languages that support the feature, programs that call functions with named parameters rather than positional parameters are easier to read and maintain.
I think Perl has this feature, but it's not working for me.
Is it a quirk of the package I'm using, or am I doing it wrong?
Setting up the function call
My fist Perl project is to use the HTML::TableExtract package to extract table data from HTML markup and display it as text.
The following code sets up the parser:
use strict;
use warnings;
use HTML::TableExtract;
my $markup = <<MARKUP;
<table>
<tr> <th>a</th> <th>b</th> <th>c</th> </tr>
<tr> <td>1</td> <td>2</td> <td>3</td> </tr>
<tr> <td>4</td> <td>5</td> <td>6</td> </tr>
</table>
MARKUP
my $parser = HTML::TableExtract->new() ;
$parser->parse($markup) ;
The documentation says that I can dump output to the Command Prompt using the tables_dump method and use parameters $show_content and $col_sep to control the output format:
tables_report([$show_content, $col_sep])
Return a string summarizing extracted tables, along with their depth and count. Optionally takes a $show_content flag which will dump the extracted contents of each table as well with columns separated by $col_sep. Default $col_sep is ':'.
tables_dump([$show_content, $col_sep])
Same as tables_report() except dump the information to STDOUT.
Calling with positional and with named parameters
If I pass positional parameters in documentation order, I get the output I expect:
$parser->tables_dump(1, '_') ;
The columns are separated by an underscore instead of the default colon:
TABLE(0, 0):
a_b_c
1_2_3
4_5_6
Following Perl.com's Advance Subroutines article, I tried to pass a hash containing parameter names and values to clarify the meaning of the parameters:
$parser->tables_dump({show_content => 1, col_sep => '_'}) ;
Perl doesn't understand this. It ignores the value of col_sep and outputs with the default value:
TABLE(0, 0):
a:b:c
1:2:3
4:5:6
I get the same output if I don't try to change the separator:
$parser->tables_dump({show_content => 1}) ;
Even if I specify nonsense parameter names, I get the same output:
$parser->tables_dump({tweedledum => 1, tweedledee => '_'}) ;
Can I call this function using the named parameter style, or should I just settle for positional?
Perl doesn't natively support named parameters, however it's possible to design functions to accept named parameters (as a hash or hashref). It's up to the author of the function as to how they implement it. You'll need to supply arguments the function is expecting or you'll get unexpected results.
Named parameter passing in Perl (even with default values) is explained very well in Object Oriented Perl, Chapter 6.
This style is very important and is widely used in object constructors. That's why it is explained in their OO Perl book.
I will quote two of their examples:
# This is how you call a subroutine using named argument passing
interests(name => "Paul", language => "Perl", favourite_show => "Buffy");
# This is how you define the subroutine to accept named arguments
sub interests {
my (%args) = #_;
# This is how you capture named arguments and define
# defaults for the ones missing from a particular call.
my $name = $args{name} || "Bob the Builder";
my $language = $args{language} || "none that we know";
my $favourite_show = $args{favourite_show} || "the ABC News";
print "${name}’s primary language is $language. " .
"$name spends their free time watching $favourite_show\n";
}
Another example that gives a different way of defining defaults (in a hash) is this:
my %defaults = ( pager => "/usr/bin/less", editor => "/usr/bin/vim" );
sub set_editing_tools {
my (%args) = #_;
# Here we join our arguments with our defaults. Since when
# building a hash it’s only the last occurrence of a key that
# matters, our arguments will override our defaults.
%args = (%defaults, %args);
# print out the pager:
print "The new text pager is: $args{pager}\n";
# print out the editor:
print "The new text editor is: $args{editor}\n";
}
Following Perl.com's Advance Subroutines article, I tried to pass a
hash containing parameter names and values to clarify the meaning of
the parameters:
That article covers a way to write subroutines such that they will accept a hashref of named parameters. If you're calling a sub that isn't written to accept that, then it won't know how to handle it correctly.
$parser->tables_dump({show_content => 1, col_sep => '_'}) ;
Perl doesn't understand this. It ignores the value of col_sep and
outputs with the default value:
Not to be overly pedantic, but Perl understands that just fine. However, tables_dump is only written to accept a list of scalar parameters. When you call it that way, it receives a single scalar parameter. This parameter just happens to be a reference to a hash, but tables_dump doesn't know or care about that, so it uses the reference as the value of $show_content. This is probably equivalent to passing 1 for show_content, since both 1 and any possible reference will evaluate as "true" in boolean context and I assume that $show_content is only ever used as a boolean.
Since there is no second parameter, nothing gets assigned to $col_sep, so it uses the default separator, as you observed.
Perl has no built-in support for named parameters. If you want to use them, the function has to be specifically written to accept arguments in that style. So you'll have to settle for positional arguments (or write a wrapper function (probably in a subclass)).
It's not too complicated. You pass the key-value pair like a hash or as a hash reference, and in the subroutine you load the arguments into a hash or hash reference.
# called like $parser->tables_dump({show_content => 1, col_sep => '_'}) ;
sub TheParser::tables_dump {
my ($self, $args) = #_;
if ($args->{show_content} == 1) {
print join $args->{col_sep}, $self->the_column_data();
...
}
}
With another line, you can load the named arguments you know about into appropriately named variables:
my ($self, $args) = #_;
my ($show_content, $col_sep) = #$args{qw(show_content col_sep)};
if ($show_content == 1) {
...
Going off just the title's question, you could do something like the below:
use strict;
use Carp::Assert;
sub func {
my (%hash) = #_;
assert($hash{'baz'} == 1);
assert($hash{'mu'} == 2);
}
func('baz' => 1, 'mu' => 2);
Here is a simple program I wrote that can use a type of named parameters. It allows for default values.
#!/usr/bin/perl
use strict;
use warnings;
use 5.014;
use POSIX qw/ strftime /;
# Script to get prior Monday (if today is Mon, then Mon a week ago).
for my $day (qw/ Sun Mon Tue Wed Thu Fri Sat /) {
say "Last $day: ", last_monday( day => $day );
}
sub last_monday {
my %arg = ( time => [localtime],
day => 'mon',
span => 1,
#_
);
my $dow; # day of week
if ('sunday' =~ /$arg{day}/i) { $dow = 0}
elsif ('monday' =~ /$arg{day}/i) { $dow = 1}
elsif ('tuesday' =~ /$arg{day}/i) { $dow = 2}
elsif ('wednesday' =~ /$arg{day}/i) { $dow = 3}
elsif ('thursday' =~ /$arg{day}/i) { $dow = 4}
elsif ('friday' =~ /$arg{day}/i) { $dow = 5}
elsif ('saturday' =~ /$arg{day}/i) { $dow = 6}
else {
warn "$arg{day} is not a valid day of week. $!";
return;
}
my ($wday, #dmy) = #{ $arg{time} }[6, 3..5];
# (will work across month, year boundries)
$dmy[0] -= ($wday - $dow) % 7 || ($arg{span} ? 7 : 0); # $dmy[0] == mday
return strftime "%Y%m%d", 0,0,0,#dmy;
}

Bash/perl Printing line(s) from file until a character with conditions

I'm trying to scan a file for lines containing a specific string, and print the lines to another file.
However, I need to print out multiple lines until ")" character IF the line containing the string ended in "," ignoring whitespaces.
Currently I'm using
for func in $fnnames
do
sed/"$func"/p <$file >>$CODEBASEDIR/function_signature -n
done
where $func contains the string I look for, but of course it doesn't work for the restriction.
Is there a way to do this? Currently using bash, but perl is fine also.
Thanks.
Your question is tricky because your restrictions are not precise. You say - I think - that a block should look like this:
foo,
bar,
baz)
Where foo is the string that starts the block, and closing parenthesis ends it. However, you could also be saying:
foo bar baz) xxxxxxxxxxx,
And you only want to print until the ), which is to say foo bar baz), IF the line ends with comma.
You could also be saying that only lines that end with a comma should be continued:
foo, # print + is continued
bar # print + is not continued
xxxxx # ignored line
foo # print + is not continued
foo,
bar,
baz) # closing parens also end block
Since I can only guess that you mean the first alternative, I give you two options:
use strict;
use warnings;
sub flip {
while (<DATA>) {
print if /^foo/ .. /\)\s*$/;
}
}
sub ifchain {
my ($foo, $print);
while (<DATA>) {
if (/^foo/) {
$foo = 1; # start block
print;
} elsif ($foo) {
if (/,\s*$/) {
print;
} elsif (/\)\s*$/) {
$foo = 0; # end block
print;
}
# for catching input errors:
else { chomp; warn "Mismatched line '$_'" }
}
}
}
__DATA__
foo1,
bar,
baz)
sadsdasdasdasd,
asda
adaffssd
foo2,
two,
three)
yada
The first one will print any lines found between a line starting with foo and a line ending with ). It will ignore the "lines end with comma" restriction. On the positive side, it can be simplified to a one-liner:
perl -ne 'print if /^foo/ .. /\)\s*$/' file.txt
The second one is just a simplistic if-structure that will consider both restrictions, and warn (print to STDERR) if it finds a line inside a block that does not match both.
perl -ne 'print if 1 .. /\).*,\s*$/'

In Perl, is there any difference between direct glob aliasing and aliasing via the stash?

In Perl, is there ever any difference between the following two constructs:
*main::foo = *main::bar
and
$main::{foo} = $main::{bar}
They appear to have the same function (aliasing all of the slots in *main::foo to those defined in *main::bar), but I am just wondering if this equivalency always holds.
Maybe not the kind of difference you were looking for, but there are two big differences between *main::foo and $main::{foo}; the former looks up the glob in the stash at compile time, creating it if necessary, while the latter looks for the glob in the stash at run time, and won't create it.
This may make a difference to anything else poking about in the stash, and it certainly can affect whether you get a used only once warning.
The following script:
#!/usr/bin/env perl
#mytest.pl
no warnings;
$bar = "this";
#bar = qw/ 1 2 3 4 5 /;
%bar = qw/ key value /;
open bar, '<', 'mytest.pl' or die $!;
sub bar {
return "Sub defined as 'bar()'";
}
$main::{foo} = $main::{bar};
print "The scalar \$foo holds $foo\n";
print "The array \#foo holds #foo\n";
print "The hash \%foo holds ", %foo, "\n";
my $line = <foo>;
print "The filehandle 'foo' is reads ", $line;
print 'The function foo() replies "', foo(), "\"\n";
Outputs:
The scalar $foo holds this
The array #foo holds 1 2 3 4 5
The hash %foo holds keyvalue
The filehandle 'foo' is reads #!/usr/bin/env perl
The function foo() replies "Sub defined as 'bar()'"
So if *main::foo = *main::bar; doesn't do the same thing as $main::{foo} = $main::{bar};, I'm at a loss as to how to detect a practical difference. ;) However, from a syntax perspective, there may be situations where it's easier to use one method versus another. ...the usual warnings about mucking around in the symbol table always apply.
Accessing the stash as $A::{foo} = $obj allows you to place anything on the symbol table while *A::foo = $obj places $obj on the expected slot of the typeglob according to $obj type.
For example:
DB<1> $ST::{foo} = [1,2,3]
DB<2> *ST::bar = [1,2,3]
DB<3> x #ST::foo
Cannot convert a reference to ARRAY to typeglob at (eval 7)[/usr/local/perl/blead-debug/lib/5.15.0/perl5db.pl:646] line 2.
at (eval 7)[/usr/local/perl/blead-debug/lib/5.15.0/perl5db.pl:646] line 2
eval '($#, $!, $^E, $,, $/, $\\, $^W) = #saved;package main; $^D = $^D | $DB::db_stop;
#ST::foo;
;' called at /usr/local/perl/blead-debug/lib/5.15.0/perl5db.pl line 646
DB::eval called at /usr/local/perl/blead-debug/lib/5.15.0/perl5db.pl line 3442
DB::DB called at -e line 1
DB<4> x #ST::bar
0 1
1 2
2 3
DB<5> x \%ST::
0 HASH(0x1d55810)
'bar' => *ST::bar
'foo' => ARRAY(0x1923e30)
0 1
1 2
2 3
See also "Scalars vs globs (*{} should not return FAKE globs)"
https://github.com/perl/perl5/issues/10625

What pseudo-operators exist in Perl 5?

I am currently documenting all of Perl 5's operators (see the perlopref GitHub project) and I have decided to include Perl 5's pseudo-operators as well. To me, a pseudo-operator in Perl is anything that looks like an operator, but is really more than one operator or a some other piece of syntax. I have documented the four I am familiar with already:
()= the countof operator
=()= the goatse/countof operator
~~ the scalar context operator
}{ the Eskimo-kiss operator
What other names exist for these pseudo-operators, and do you know of any pseudo-operators I have missed?
=head1 Pseudo-operators
There are idioms in Perl 5 that appear to be operators, but are really a
combination of several operators or pieces of syntax. These pseudo-operators
have the precedence of the constituent parts.
=head2 ()= X
=head3 Description
This pseudo-operator is the list assignment operator (aka the countof
operator). It is made up of two items C<()>, and C<=>. In scalar context
it returns the number of items in the list X. In list context it returns an
empty list. It is useful when you have something that returns a list and
you want to know the number of items in that list and don't care about the
list's contents. It is needed because the comma operator returns the last
item in the sequence rather than the number of items in the sequence when it
is placed in scalar context.
It works because the assignment operator returns the number of items
available to be assigned when its left hand side has list context. In the
following example there are five values in the list being assigned to the
list C<($x, $y, $z)>, so C<$count> is assigned C<5>.
my $count = my ($x, $y, $z) = qw/a b c d e/;
The empty list (the C<()> part of the pseudo-operator) triggers this
behavior.
=head3 Example
sub f { return qw/a b c d e/ }
my $count = ()= f(); #$count is now 5
my $string = "cat cat dog cat";
my $cats = ()= $string =~ /cat/g; #$cats is now 3
print scalar( ()= f() ), "\n"; #prints "5\n"
=head3 See also
L</X = Y> and L</X =()= Y>
=head2 X =()= Y
This pseudo-operator is often called the goatse operator for reasons better
left unexamined; it is also called the list assignment or countof operator.
It is made up of three items C<=>, C<()>, and C<=>. When X is a scalar
variable, the number of items in the list Y is returned. If X is an array
or a hash it it returns an empty list. It is useful when you have something
that returns a list and you want to know the number of items in that list
and don't care about the list's contents. It is needed because the comma
operator returns the last item in the sequence rather than the number of
items in the sequence when it is placed in scalar context.
It works because the assignment operator returns the number of items
available to be assigned when its left hand side has list context. In the
following example there are five values in the list being assigned to the
list C<($x, $y, $z)>, so C<$count> is assigned C<5>.
my $count = my ($x, $y, $z) = qw/a b c d e/;
The empty list (the C<()> part of the pseudo-operator) triggers this
behavior.
=head3 Example
sub f { return qw/a b c d e/ }
my $count =()= f(); #$count is now 5
my $string = "cat cat dog cat";
my $cats =()= $string =~ /cat/g; #$cats is now 3
=head3 See also
L</=> and L</()=>
=head2 ~~X
=head3 Description
This pseudo-operator is named the scalar context operator. It is made up of
two bitwise negation operators. It provides scalar context to the
expression X. It works because the first bitwise negation operator provides
scalar context to X and performs a bitwise negation of the result; since the
result of two bitwise negations is the original item, the value of the
original expression is preserved.
With the addition of the Smart match operator, this pseudo-operator is even
more confusing. The C<scalar> function is much easier to understand and you
are encouraged to use it instead.
=head3 Example
my #a = qw/a b c d/;
print ~~#a, "\n"; #prints 4
=head3 See also
L</~X>, L</X ~~ Y>, and L<perlfunc/scalar>
=head2 X }{ Y
=head3 Description
This pseudo-operator is called the Eskimo-kiss operator because it looks
like two faces touching noses. It is made up of an closing brace and an
opening brace. It is used when using C<perl> as a command-line program with
the C<-n> or C<-p> options. It has the effect of running X inside of the
loop created by C<-n> or C<-p> and running Y at the end of the program. It
works because the closing brace closes the loop created by C<-n> or C<-p>
and the opening brace creates a new bare block that is closed by the loop's
original ending. You can see this behavior by using the L<B::Deparse>
module. Here is the command C<perl -ne 'print $_;'> deparsed:
LINE: while (defined($_ = <ARGV>)) {
print $_;
}
Notice how the original code was wrapped with the C<while> loop. Here is
the deparsing of C<perl -ne '$count++ if /foo/; }{ print "$count\n"'>:
LINE: while (defined($_ = <ARGV>)) {
++$count if /foo/;
}
{
print "$count\n";
}
Notice how the C<while> loop is closed by the closing brace we added and the
opening brace starts a new bare block that is closed by the closing brace
that was originally intended to close the C<while> loop.
=head3 Example
# count unique lines in the file FOO
perl -nle '$seen{$_}++ }{ print "$_ => $seen{$_}" for keys %seen' FOO
# sum all of the lines until the user types control-d
perl -nle '$sum += $_ }{ print $sum'
=head3 See also
L<perlrun> and L<perlsyn>
=cut
Nice project, here are a few:
scalar x!! $value # conditional scalar include operator
(list) x!! $value # conditional list include operator
'string' x/pattern/ # conditional include if pattern
"#{[ list ]}" # interpolate list expression operator
"${\scalar}" # interpolate scalar expression operator
!! $scalar # scalar -> boolean operator
+0 # cast to numeric operator
.'' # cast to string operator
{ ($value or next)->depends_on_value() } # early bail out operator
# aka using next/last/redo with bare blocks to avoid duplicate variable lookups
# might be a stretch to call this an operator though...
sub{\#_}->( list ) # list capture "operator", like [ list ] but with aliases
In Perl these are generally referred to as "secret operators".
A partial list of "secret operators" can be had here. The best and most complete list is probably in possession of Philippe Bruhad aka BooK and his Secret Perl Operators talk but I don't know where its available. You might ask him. You can probably glean some more from Obfuscation, Golf and Secret Operators.
Don't forget the Flaming X-Wing =<>=~.
The Fun With Perl mailing list will prove useful for your research.
The "goes to" and "is approached by" operators:
$x = 10;
say $x while $x --> 4;
# prints 9 through 4
$x = 10;
say $x while 4 <-- $x;
# prints 9 through 5
They're not unique to Perl.
From this question, I discovered the %{{}} operator to cast a list as a hash. Useful in
contexts where a hash argument (and not a hash assignment) are required.
#list = (a,1,b,2);
print values #list; # arg 1 to values must be hash (not array dereference)
print values %{#list} # prints nothing
print values (%temp=#list) # arg 1 to values must be hash (not list assignment)
print values %{{#list}} # success: prints 12
If #list does not contain any duplicate keys (odd-elements), this operator also provides a way to access the odd or even elements of a list:
#even_elements = keys %{{#list}} # #list[0,2,4,...]
#odd_elements = values %{{#list}} # #list[1,3,5,...]
The Perl secret operators now have some reference (almost official, but they are "secret") documentation on CPAN: perlsecret
You have two "countof" (pseudo-)operators, and I don't really see the difference between them.
From the examples of "the countof operator":
my $count = ()= f(); #$count is now 5
my $string = "cat cat dog cat";
my $cats = ()= $string =~ /cat/g; #$cats is now 3
From the examples of "the goatse/countof operator":
my $count =()= f(); #$count is now 5
my $string = "cat cat dog cat";
my $cats =()= $string =~ /cat/g; #$cats is now 3
Both sets of examples are identical, modulo whitespace. What is your reasoning for considering them to be two distinct pseudo-operators?
How about the "Boolean one-or-zero" operator: 1&!!
For example:
my %result_of = (
" 1&!! '0 but true' " => 1&!! '0 but true',
" 1&!! '0' " => 1&!! '0',
" 1&!! 'text' " => 1&!! 'text',
" 1&!! 0 " => 1&!! 0,
" 1&!! 1 " => 1&!! 1,
" 1&!! undef " => 1&!! undef,
);
for my $expression ( sort keys %result_of){
print "$expression = " . $result_of{$expression} . "\n";
}
gives the following output:
1&!! '0 but true' = 1
1&!! '0' = 0
1&!! 'text' = 1
1&!! 0 = 0
1&!! 1 = 1
1&!! undef = 0
The << >> operator, for multi-line comments:
<<q==q>>;
This is a
multiline
comment
q