Perl, using the subtitle as an argument for another unpredictable context

I am using a subtitle as an argument for another sub. Code example:

test(isInString(), 'second parameter', 'third parameter'); sub test { my ($boolean, $second, $third) = @_; print "boolean: $boolean\n second: $second\n third: $third\n"; } sub isInString { my $searchFor = 'a'; my $searchIn = 'bcd'; return ($searchFor && $searchIn && ($searchIn =~ $searchFor)); } 

In the above example, I would expect the return statement in "isInString" to evaluate to false ('' or undef or something else that might be in perl) and this would be passed to “Test” as parameter # 1 , su, essentially

 Test(undef, 'second parameter', 'third parameter'); 

This is not what is happening. isInString returns an empty array, and essentially you get

 Test('second parameter', 'third parameter'); 

Returning from isInString in the perl debugger gives:

return context list from main :: isInString: empty array

I assume this is a perl context, I can assign a scalar variable first, and it works fine:

 my $bool = isInString(); Test($bool, 'second parameter', 'third parameter'); 

the debugger gives - the scalar context returns from main :: isInString: ''

EDIT I ​​deleted all parsers with the same result:

 sub isInString { my $searchFor = 'a'; my $searchIn = 'bcd'; return $searchFor && $searchIn && $searchIn =~ $searchFor; } 

The debugger still gives:

return context list from main :: isInString: empty array

Can someone explain why the list / empty array is returned in this scenario?

+4
source share
3 answers

If you want to force a "logical context", you can use a two-way "operator": !! , eg:

 test( !!isInString(), 'second parameter', 'third parameter' ); 

By calling it in the parameter list, you made it a "list context". You can make him return to something like that. One hack ( ! ) Evaluates it in a Boolean context and makes it either 1 or '' . But since you are not testing the add-on, but its value itself, adding another hit, you will get the desired value back.

However, since it is pretty clear from the function body that you are returning a boolean and you are calling it in a list context (a parameter list is a list context), you may need to force the value there. For instance:

 return ($searchFor && $searchIn && $searchIn =~ $searchFor) || 0; 

Any undef will result in a false value and it will go to the or character and return 0, which the list context will not ignore, since it can undef .

+2
source

Your return is evaluated in the context of the list, because the function is called in the context of the list. Boolean operators (e.g. && ) do not invoke a scalar context.

To quote perlop on && :

A scalar or list context extends down to the right operand, if evaluated.

Since the match statement returns an empty list on failure in the context of the list, this is what you get. If you want to force the use of a scalar context, use the scalar operator either in the return or when calling the function.

Also, the idea of ​​parentheses in a list of brackets (as suggested by some other answers) is a common misconception. They do not do this. The list context is the default; all that can be a list context is a list context. Therefore, there is no list operator matching scalar . The only place where parens "force" lists a context with a repeat statement. 'a' x 3 means 'aaa' , but ('a') x 3 means ('a', 'a', 'a') . But this does not actually cause the list context, it is just a special case for the x operator .

+7
source

Not relevant to your question, but index() is suitable for your isInString() function.

 index( $searchIn, $searchFor ); 
0
source

All Articles