"between" function equivalent in Perl?

A

Alexandra

Tad McClellan said:
That is what we are focusing on here as well!

You needed a m// in list context to get what you wanted.

I will play with this because I do want to understand all the different ways
to accomplish the same things (in some cases).
From p69 in the 3rd Camel:

Assignment to a list of scalars also provides list context
to the righthand side, even if there's only one element
in the list.

I have that book open right now on my desk and after reading this, I looked
down to see it was already open to p.69 (not a lie). Out of curiosity, I was
trying to get my "wrong" expression to evaluate to 2 or 0 or any other
number besides 1. But I couldn't do it. I was attempting this by adding in
more elements in the original search string that would match the re, but I
still received a 1.

$mystring = ('xxx blah=bleh @', 'yyy bloh=bluh @', 'zzz blea=blech @');
$mymatch = $mystring =~ /=(.*?)\s/; #for example (one of the
correct solutions previously provided) returns 1
($mymatch) = $mystring =~ /=(.*?)\s/; #returns 'blech', the last
value to match in the string
($foo) = ...list context...

has only one element in the list.

Would you know how to get it to return 3 instead of 1?

(I know, I've got to read and keep at this to understand lists and contexts.
The advanced and even not-advanced programmers reading this must be laughing
at me but if I can learn it then its worth it.)

Alexandra
 
A

Alexandra

John W. Krahn said:
Alexandra wrote:

Instead of running an external program for this you can do it in perl
and have better control of error reporting:

my $file = '/AAA/bbbb/ccc/dd/eeee.ff';
open my $fh, '<', $file or die "Cannot open $file: $!"
my $mystr = join '', grep $in{lookup_key}, <$fh>;
close $fh;

That's great. I did see the grep function in the Perl books, but was a
little afraid to tackle that before I got a handle on the matching. This way
seems much cleaner and contained. I will also be needing to use this
functionality in another part of the script to update an Apache .htaccess
file. Hashes are next... said:
$in{mystr} = $mystr; #debug
$from = '=';
$in{myfrom} = $from; #debug
$to = ' ';
$in{myto} = $to; #debug

($in{mysubstr0}) = $mystr =~ /=(\S+)/;
($in{mysubstr1}) = $mystr =~ /=(.*?)\s/;
($in{mysubstr2}) = $mystr =~ m/[=]([^\s]+)/;
($in{mysubstr3}) = $mystr =~ /$from(.*?)$to/;

I found that most all of the regular expression examples in the Programming
Perl book use shorthand of referring to $_ (thus, not providing an
explicitly named variable at all).

Whenever you see "/regex/" or "$var = /regex/" you can expand them to
"$_ =~ /regex/" and "$var = $_ =~ /regex/" then the "$_ =~" part can be
replaced with whatever scalar variable you want.

Very helpful to know, thanks.
Because the binding operator (=~) has higher precedence then the
assignment operator (=) the parenthesis are required to assign the
contents of $bar to $foo before the substitution is performed on the
result so that $foo is changed and $bar is not. Without the parenthesis
the substitution would be performed on $bar first and the result of that
(true or false) would be assigned to $foo.

I so did not intuit that from the example alone. I'd assumed both would be
changed to the re result. (I think I need to read what you wrote a couple
more times to absorb it, and will, but I wanted to reply promptly.)
Is that irony?

Heavy. said:
perlsub.pod explains a bit about the difference between scalar and list
context.

perldoc perlsub

Bookmarked it and will read along with the other ones tomorrow. Thanks
again.

Alexandra
 
E

Eric Bohlman

Okay, I read up a bit more (and re-read), and I still do not fully
understand the implications of scalar v. list context. And I tried to

Probably the most important thing to remember about context is this:

When you're doing an assignment, whether it takes place in scalar context
or list context is determined by the *left* side of the assignment, *not*
the right side! The thingy (technical Perl term) being assigned *to* gives
marching orders to the expression being evaluated to assign *from*.

my $var=expression(); #scalar context because the left side is a scalar

my ($var)=expression(); #list context because the left side is a list

@values=expression(); #list context; array on left side acts like a list
 
T

Tad McClellan

Alexandra said:
$mystring = ('xxx blah=bleh @', 'yyy bloh=bluh @', 'zzz blea=blech @');


You should always enable warnings when developing Perl code!

Did you print out $mystring to see what it contains at this point?

That code has the same effect as:

$mystring = 'zzz blea=blech @';

(only it doesn't do "busy work" and then discard the results)

$mymatch = $mystring =~ /=(.*?)\s/; #for example (one of the
correct solutions previously provided) returns 1


That is m// in a scalar context, it returns "true" or "false".

(which might be 1 or 0, but could be something else.)

($mymatch) = $mystring =~ /=(.*?)\s/; #returns 'blech', the last
value to match in the string


That is m// in a list context, it returns all of the "memories"
if the match succeeds.

Would you know how to get it to return 3 instead of 1?


if $mystring contains the "3" character, then:

($mymatch) = $mystring =~ /(3)/;

(I know, I've got to read and keep at this to understand lists and contexts.
The advanced and even not-advanced programmers reading this must be laughing
at me but if I can learn it then its worth it.)


Please see the Posting Guidelines that are posted here frequently.

It suggests you use warnings.

It suggests you post real code.

We could save a lot of round-and-round if you had just
done it right the first time...



If you don't understand something in the "Context" section
of perldata.pod, then post that part here, and we'll try
helping you to understand it.

It is unclear what you've already seen, and it would be a waste
of time doing all here if what is in the std docs is enough for you.
 
T

Tad McClellan

Eric Bohlman said:
Probably the most important thing to remember about context is this:


The most important thing to remember about context is this:

It is the operator or function being used that imposes
context its operands/arguments.

Which is my paraphrasing of the first sentence in the "Context"
section of perldata.pod:

The interpretation of operations and values in Perl sometimes depends
on the requirements of the context around the operation or value.

When you're doing an assignment, whether it takes place in scalar context
or list context is determined by the *left* side of the assignment, *not*
the right side! The thingy (technical Perl term) being assigned *to* gives
marching orders to the expression being evaluated to assign *from*.


When the operator being used is the assignment operator, _then_
that becomes important (especially since it is a "strange" one).

It doesn't help at all when the operator used is, say, print().



In the context <g> of this thread about context, the most important
thing _is_ what context the assignment operator puts on its operands,
but I thought I'd throw out the more general rule in case it helps anyone.
 
J

John W. Krahn

Alexandra said:
That's great. I did see the grep function in the Perl books, but was a
little afraid to tackle that before I got a handle on the matching. This way
seems much cleaner and contained. I will also be needing to use this
functionality in another part of the script to update an Apache .htaccess
file. Hashes are next... <g>

That was just an example. :) Something like this may actually work:

my $mystr = join '', grep /\Q$in{lookup_key}\E/, <$fh>;



John
 
A

Alexandra

Tad McClellan said:
You should always enable warnings when developing Perl code!

Whoops, I didn't see warnings in my inherited code (obviously). The
explanations in Learning Perl and Programming Perl were minimal but I found
the pod doc on warnings to read.
Did you print out $mystring to see what it contains at this point?

Yes, $mystring came out similary to the dummied text string as follows:

$mystring = 'aaa @ bbbb @ c @ dd @ eeeeee @ FFFFF=xxxx @ ggg @ h'

My apologies for using dummied code. The real result string contained
sensitive data so I had to mask it. In the future I'll make an effort to
post more accurate coding examples in these cases.
That code has the same effect as:

$mystring = 'zzz blea=blech @';

(only it doesn't do "busy work" and then discard the results)




That is m// in a scalar context, it returns "true" or "false".

(which might be 1 or 0, but could be something else.)



That is m// in a list context, it returns all of the "memories"
if the match succeeds.

With these explanations, rereading the Camel books, *are* more clear.
if $mystring contains the "3" character, then:


($mymatch) = $mystring =~ /(3)/;

I didn't phrase my question very well and the masked code was a bit
misleading (still masked below, but less so). I was looking to find a return
value of the count of the 3 list values. I've since discovered the count
function. What I also read is that scalar values (in some cases) can be
thought of list values which return the last list item, which is why I was
receiving the 3rd value in my list of 3 values:

$mystring = ('namea server1=login_a @', ' nameb server1=login_b @', 'namec
server2=login_c @');
Please see the Posting Guidelines that are posted here frequently.

(found it in Google Groups, and also the pointer to the Perl FAQ, thanks)
It suggests you use warnings.

It suggests you post real code.

We could save a lot of round-and-round if you had just
done it right the first time...

Very true. I see this now.

Unfortunately I did understand how to specifically address (or post enough
code with out posting "too much code" to address) related issues in the
code that I wasn't aware of in the first place nor did I anticipate how many
more questions my initial post would raise. Sometimes textbooks are just not
enough. So again, thank you for taking the time to help this newbie.
If you don't understand something in the "Context" section
of perldata.pod, then post that part here, and we'll try
helping you to understand it.

It is unclear what you've already seen, and it would be a waste
of time doing all here if what is in the std docs is enough for you.

Alexandra
 
A

Alexandra

(still reading Camel 3 and pod docs, it's slowly sinking in... thanks to all
for the references)
The most important thing to remember about context is this:

It is the operator or function being used that imposes
context its operands/arguments.

Thanks Eric and Tad, for taking the time to explain. Would it be accurate to
assume that most Perl expressions/functions will evaluate "at large" and
then look to "format" (for lack of a better term) the return value depending
on the context of the assignment variable or operand?

I read somewhere that you do not have to declare variables in Perl, you just
use them. Getting a grasp on contexts, even a tiny one, explains now how
that can work.

Alexandra
 
T

Tad McClellan

Alexandra said:
Would it be accurate to

No.


assume that most Perl expressions/functions will evaluate "at large" and


They have 2 different behaviors.

If called in a scalar context, they do one thing.

If called in a list context, they do something else.

They are often "related" things, but that is convention rather
than requirement. They could do wildly different unconnected
things, such as send an email in scalar context and return
the contents of a database table in list context.

It is up to the author of the function to decide what it is that
their function will do in each context. (So you cannot use the
function intelligently without reading the functions' docs.)

You can write your own context-sensitive subroutines too. Here's
one that outputs what context it was called in:

---------------------------------------------
#!/usr/bin/perl
use strict;
use warnings;

foreach ( context() ) {} # list

$_ = 2 + context(); # scalar

context(); # void

sub context {
my $context = wantarray();
if ( $context )
{ print "list context\n" }
elsif ( defined $context )
{ print "scalar context\n" }
else
{ print "void context\n" }
}
---------------------------------------------

then look to "format" (for lack of a better term) the return value depending
on the context of the assignment variable or operand?
^^^^^^^^^^

You should have left that word out. Context matters for operators
other than assignment as well.

I read somewhere that you do not have to declare variables in Perl, you just
use them.


Right (but not recommended, other than in one-liners).

Getting a grasp on contexts, even a tiny one, explains now how
that can work.


No it doesn't.

Context has nothing whatsoever to do with either of Perl's two
systems of variables.


If you can explain why you think context relates to declaring (or not)
variables, then perhaps we can help fix the misunderstanding.
 
A

Alexandra

Tad McClellan said:
What is the count function?

Um, something from my imagination? I had misinterpreted the variable name in
the following text.

=== copied from perldata pod ===

List assignment in scalar context returns the number of elements produced by
the expression on the right side of the assignment:

$x = (($foo,$bar) = (3,2,1)); # set $x to 3, not 2
$x = (($foo,$bar) = f()); # set $x to f()'s return count

This is handy when you want to do a list assignment in a Boolean context,
because most list functions return a null list when finished, which when
assigned produces a 0, which is interpreted as FALSE.

It's also the source of a useful idiom for executing a function or
performing an operation in list context and then counting the number of
return values, by assigning to an empty list and then using that assignment
in scalar context. For example, this code:

$count = () = $string =~ /\d+/g;

will place into $count the number of digit groups found in $string. This
happens because the pattern match is in list context (since it is being
assigned to the empty list), and will therefore return a list of all
matching parts of the string. The list assignment in scalar context will
translate that into the number of elements (here, the number of times the
pattern matched) and assign that to $count. Note that simply using

$count = $string =~ /\d+/g;

would not have worked, since a pattern match in scalar context will only
return true or false, rather than a count of matches.

=== end paste ===

However, I still could not get the following to return $count as a value of
3, $count returned a value of 1:

#! /usr/bin/perl -s
#use strict;
#use warnings;

$mystring = ('xxx server1=user1 @', 'yyy server1=user2 @', 'zzz
server2=user1 @');
$count = () = $mystring =~ /=(.*?)\s/;
print $count;

Also, when I included the 'use strict' and 'use warnings' statements I
received the following output messages and don't understand how to resolve
them. Any insight?

Can't locate warnings.pm in @INC (@INC contains:
/usr/lib/perl5/5.00502/sun4-solaris /usr/lib/perl5/5.00502
/usr/lib/perl5/site_perl/5.005/sun4-solaris /usr/lib/perl5/site_perl/5.005
..) at test.pl line 3.
BEGIN failed--compilation aborted at test.pl line 3.

Global symbol "$mystring" requires explicit package name at test.pl line 6.
Global symbol "$count" requires explicit package name at test.pl line 7.
Execution of test.pl aborted due to compilation errors.

A posting guideline question:
This thread originated with my question about a between function equivalent
in Perl but has since evolved to this question on list count evaluation.
Would it be proper to have renamed this post subject line to something like
"List counts <was: Re: "between" function equivalent in Perl?>" or is it
preferred by this group to keep all related posts under the original
discussion thread?

Much thanks,
Alexandra
 
A

Alexandra

Tad McClellan said:

(My apologies for the untimely reply as I was taking some time to read up
more.)
They have 2 different behaviors.

If called in a scalar context, they do one thing.

If called in a list context, they do something else.

They are often "related" things, but that is convention rather
than requirement. They could do wildly different unconnected
things, such as send an email in scalar context and return
the contents of a database table in list context.

Ok, I see now my generalizations were inaccurate and that context does
determine how operators *and* functions evaluate, even though "certain
operators know
which context they are in". (Programming Perl, p45) It goes on to say: "In
computer lingo, the functions are 'overloaded' on the type of their return
value. But it's a very simple kind of overloading, based only on the
distinction between singular and plural values, and nothing else."

Before, I was reading this to mean that in most cases only the variable type
(scalar or list) determines the context in which the expression evaluates.
It is up to the author of the function to decide what it is that
their function will do in each context. (So you cannot use the
function intelligently without reading the functions' docs.)

It seems a bit of a paradigm shift from languages such as VB, where
declarations are used to determine object classes and variable datatypes.
Functions in many cases are tied to object classes and variable datatype
declarations; I was trying to make a connection between this convention with
determining context in Perl.

Not to get mired in semantics with this, but working with Perl seems to
require a shift in approach: Perl statements are more compressed, and a lot
more can happen on one line than in other programming languages. (I'm sure
this could be debated, too. I'm merely trying to breach the disconnect I was
having here in approaching the Perl language as a whole. Still much reading
to do...)
^^^^^^^^^^

You should have left that word out. Context matters for operators
other than assignment as well.

I see that a little better now. It's incorrect to assume context is
restricted to or solely determined by the assignment operator.
Right (but not recommended, other than in one-liners).


No it doesn't.

Context has nothing whatsoever to do with either of Perl's two
systems of variables.

If you can explain why you think context relates to declaring (or not)
variables, then perhaps we can help fix the misunderstanding.

I believe I was trying to apply my previous experience with object-oriented
languages to use as a framework for understanding Perl. I'm under the
impression now, after this discussion, that many of the same principles do
apply (object declarations, datatype assignment, determining evaluation
context) but they are more compressed in Perl syntax. I feel that coming up
with an example at this point would only serve to waste your time before I
read up more and can phrase clear questions with specific examples (such as
the question in the other post in this thread), but I very much appreciate
your willingness to help and explain.

Also, I appreciate your indulging me in this discussion as I realize it is
beneath the level of most everyone in this group. While I'm still in a bit
over my head
here, I believe I'm getting on track, if slowly, thanks to you and all
who've replied in this string.

Alexandra
 
S

Steven Kuo

On Mon, 15 Sep 2003, Alexandra wrote:

(snipped)
However, I still could not get the following to return $count as a value of
3, $count returned a value of 1:

#! /usr/bin/perl -s
#use strict;
#use warnings;


Why the '-s' on the shebang line? Perhaps you meant '-w'?

$mystring = ('xxx server1=user1 @', 'yyy server1=user2 @', 'zzz
server2=user1 @');


A scalar from list assignment? The assigns the last item in the list
to the scalar. Perhaps you meant to use a quote operator?

my $mystring = q('xxx server1=user1 @', 'yyy server1=user2 @', 'zzz server2=user1 @');


$count = () = $mystring =~ /=(.*?)\s/;
print $count;

And here, for counting the number of matches, I guess you meant to
use global matches:

my $count = () = $mystring =~ /=(.*?)\s/g; # note the /g modifier
print $count;

Also, when I included the 'use strict' and 'use warnings'
statements I received the following output messages and don't
understand how to resolve them. Any insight?

strict.pm ought to be okay -- warnings.pm was introduced in version 5.6.
 
A

Alexandra

Steven Kuo said:
On Mon, 15 Sep 2003, Alexandra wrote:

(snipped)


Why the '-s' on the shebang line? Perhaps you meant '-w'?

The '-s' I included because of an internal convention here where I work. I'm
not sure if it's still necessary or perhaps obsolete (some of this code is
more than 6 years old). Previously I had tried the '-w' switch (instead and
in addition to) but received the 'Can't locate warnings.pm in @INC' as with
the 'use warnings' statement. (However, the code below works fine now.)
A scalar from list assignment? The assigns the last item in the list
to the scalar. Perhaps you meant to use a quote operator?

my $mystring = q('xxx server1=user1 @', 'yyy server1=user2 @', 'zzz
server2=user1 @');

rrrg. yes. :)
And here, for counting the number of matches, I guess you meant to
use global matches:

my $count = () = $mystring =~ /=(.*?)\s/g; # note the /g modifier
print $count;

Huh. I did experiment with including the global modifier to return all
matching parts, but still received a return value of 1 (I assume due to my
list assignment issue).
strict.pm ought to be okay -- warnings.pm was introduced in version 5.6.

Thanks for the help! This statement worked perfectly:

#! /usr/rand/bin/perl -ws
#use warnings; #running Perl version 5.00502
use strict;

my $stringvar = q('xxx server1=user1 @', 'yyy server1=user2 @', 'zzz
server2=user1 @');
my $count = () = $stringvar =~ /=(.*?)\s/g;
print $count;


Alexandra
 
T

Tad McClellan

Alexandra said:
$mystring = ('xxx server1=user1 @', 'yyy server1=user2 @', 'zzz
server2=user1 @');


I think I've already suggested that you try print()ing the
value of $mystring at this point in your code.

Have you tried that yet?

Can't locate warnings.pm in @INC (@INC contains:
/usr/lib/perl5/5.00502/sun4-solaris /usr/lib/perl5/5.00502
/usr/lib/perl5/site_perl/5.005/sun4-solaris /usr/lib/perl5/site_perl/5.005
.) at test.pl line 3.
BEGIN failed--compilation aborted at test.pl line 3.


use warnings;

only works with perls that are less than three and a half years old (v5.6.0).

So you can only use the inferior -w command line switch with
your perl of antiquity.

Global symbol "$mystring" requires explicit package name at test.pl line 6.


use strict;

("perldoc strict" to read the docs for the pragma)

requires that you declare all of your variables:

my $mystring = ...

or that you use an explicit package name:

$main::mystring = ...

A posting guideline question:
This thread originated with my question about a between function equivalent
in Perl but has since evolved to this question on list count evaluation.
Would it be proper to have renamed this post subject line to something like
"List counts <was: Re: "between" function equivalent in Perl?>"

Yes.


preferred by this group to keep all related posts under the original
discussion thread?


Changing the subject does not move the post out of the thread
(in newsreaders that do threading properly), so it will still be
in the original thread even after changing the Subject.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,142
Latest member
arinsharma
Top