0

I am trying to assign output of grep into variable but I get numeric as output.

Case I:

output of

print ( grep !/create/i&&!/or/i &&!/replace/i&&!/package/i&&!/body/i&&!/as/i ,  split ( / / , $str1[0] ) );

Case II:

is string but output of

my $pname = grep !/create/i&&!/or/i &&!/replace/i&&!/package/i&&!/body/i&&!/as/i ,  split ( / / , $str1[0] ) ;
print $pname , "\n";

is number

What is difference and how do I get string.

Any help would be greatly appreciated.

2 Answers 2

3

Like many Perl functions (and operators), grep does slightly different things in list context and scalar context. Its different return behaviours are explained in its documentation.

Evaluates the BLOCK or EXPR for each element of LIST (locally setting $_ to each element) and returns the list value consisting of those elements for which the expression evaluated to true. In scalar context, returns the number of times the expression was true.

In your first example, print imposes list context on the expression, so you get a list of values back. In your second example, you assign the results to a scalar, so grep gets called in scalar context and returns the number of matches found.

The solution is to ensure that grep is called in list context. Two easy ways to do this are to do a list assignment:

my ($pname) = grep ...;

Or by assigning the results to an array;

my @pnames = grep ...;

You'll find Perl programming a lot easier if you get used to consulting the documentation.

Sign up to request clarification or add additional context in comments.

Comments

3

When you are using grep, you are dealing with lists. grep takes input as a list, and produces a list as output.

Whenever an array is evaluated in scalar context (such as assigning to a scalar variable), it returns its length. Whenever it is evaluated in list context, it returns the array itself. In this case grep works in the same way as an array, returning the length of the list returned from grep when evaluated in scalar context.

my $pname = grep { 
               !/create/i&&!/or/i &&!/replace/i&&!/package/i&&!/body/i&&!/as/i  
            } split / /, $str1[0]);
print $pname , "\n";

will return the size of the list returned from grep because $pname is a scalar variable.

my ($pname) = grep { 
               !/create/i&&!/or/i &&!/replace/i&&!/package/i&&!/body/i&&!/as/i  
            } split / /, $str1[0]);
print $pname , "\n";

Will return the first element of the list, because the assignment is performed in list context (notice the parens around $pname).

Here is a brief overview of context: http://perlmaven.com/scalar-and-list-context-in-perl

2 Comments

"Whenever a List is evaluated in scalar context (such as assigning to a scalar variable), it returns its length" - I can see why you might think this is true (and in this case that's certainly how grep acts) but this isn't true in the general case. Lists do not return their length in scalar context - that is arrays. Arrays and lists are not the same thing. I wrote this blog post to try and clarify this concept.
@DaveCross Thanks, I will correct it. I actually read your article a few weeks ago and I still get it wrong. doh!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.