CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Bareword found/operator expected/missing semicolon?

 



cf8geek
Novice

May 28, 2016, 12:39 PM

Post #1 of 10 (6763 views)
Bareword found/operator expected/missing semicolon? Can't Post

Finally had to ask for help. I've done several Perl scripts before, and except for my very first few, I've always been able to find my answers with Google. Not this time; I'm stumped.

I'm trying to set a variable based on an input value, using case/switch. I'm confident (via working scripts and PerlDoc) that the syntax is correct... but obviously it's not, or I wouldn't be having this issue. :-)

I know that there are lots of errors in this script; I'm working through it line-by-line to fix them. The first ones are the ones getting me stuck listed below.


Code
Bareword found where operator expected at ./file.pl line 133, near "case" 
(Missing semicolon on previous line?)
Bareword found where operator expected at ./file.pl line 136, near "case"
(Missing semicolon on previous line?)
Bareword found where operator expected at ./file.pl line 139, near "case"
(Missing semicolon on previous line?)
Bareword found where operator expected at ./file.pl line 140, near "case"
(Missing semicolon on previous line?)
Bareword found where operator expected at ./file.pl line 141, near "case"
(Missing semicolon on previous line?)
Bareword found where operator expected at ./file.pl line 142, near "case"
(Missing semicolon on previous line?)
Bareword found where operator expected at ./file.pl line 143, near "case"
(Missing semicolon on previous line?)
Bareword found where operator expected at ./file.pl line 144, near "case"
(Missing semicolon on previous line?)
Bareword found where operator expected at ./file.pl line 145, near "case"
(Missing semicolon on previous line?)
Bareword found where operator expected at ./file.pl line 146, near "case"
(Missing semicolon on previous line?)
Bareword found where operator expected at ./file.pl line 147, near "case"
(Missing semicolon on previous line?)
Bareword found where operator expected at ./file.pl line 148, near "case"
(Missing semicolon on previous line?)
Bareword found where operator expected at ./file.pl line 149, near "case"
(Missing semicolon on previous line?)
Bareword found where operator expected at ./file.pl line 154, near "case"
(Missing semicolon on previous line?)



The full file can be found at https://raw.githubusercontent.com/HopeWDM/prod-autoserv_WDM/master/Server-side/file.pl, and the relevant snippet looks something like this:


Code
case m/sanyoPLC/ { 
switch ($value) {
case m/00/ { $status = 'on'; }
case m/80/ { $status = 'off'; }
case m/40/ { $status = 'Countdown'; }
case m/20/ { $status = 'Cooling Down'; }
case m/10/ { $status = 'Power Malfunction'; }
case m/28/ { $status = 'Cooling down at the temperature anomaly'; }
case m/02/ { $status = 'Unable to receive the RC232C command.'; }
case m/24/ { $status = 'Cooling down at Power Management mode'; }
case m/04/ { $status = 'Power Management mode after Cooling down'; }
case m/21/ { $status = 'Cooling down after the projector is turned off when the lamps are out.'; }
case m/81/ { $status = 'Stand-by mode after Cooling down when the lamps are out.'; }
case m/88/ { $status = 'Stand-by mode after Cooling down at the temperature anomaly.'; }
}

[:)][:)]


FishMonger
Veteran / Moderator

May 28, 2016, 1:50 PM

Post #2 of 10 (6757 views)
Re: [cf8geek] Bareword found/operator expected/missing semicolon? [In reply to] Can't Post

You're using a lot of poor/bad coding practices in that script.

To start with, you should not use the Switch module especially nested switch/case statements which will make the troubleshooting more difficult and is very likely the cause of a number of those warnings.

The Switch module is a source filter and is known to be fairly buggy. For awhile, the recommended alternative was to use a given/when block, but even that is no longer recommended and has been depreciated. The best practice is to use either an if/elsif/else block or a dispatch table instead of the Switch module.

Some of the other issues (poor coding practices) you have are:
1) Needlessly using global vars instead of lexical vars

2) Using prototype definitions

3) Using & when calling your subs, which circumvents the prototype checking and introduces other side effects.

4) Declaring the same var multiple times in the same scope

5) Using multiple hashes where an AoH (Array of Hashes) or HoH (Hash of Hashes) would be more appropriate.


FishMonger
Veteran / Moderator

May 28, 2016, 2:49 PM

Post #3 of 10 (6752 views)
Re: [cf8geek] Bareword found/operator expected/missing semicolon? [In reply to] Can't Post

If you remove the prototype definition from the parseLine() sub, most of the warnings will go away and you'll be left with these:

c:\test>perl -c cf8geek.pl

Code
Bareword found where operator expected at cf8geek.pl line 368, near "print 'var" 
(Might be a runaway multi-line '' string starting on line 367)
Global symbol "%rmX_mainCenter" requires explicit package name at cf8geek.pl line 251.
Global symbol "%rmX_mainCenter" requires explicit package name at cf8geek.pl line 252.
Global symbol "%rmX_mainCenter" requires explicit package name at cf8geek.pl line 253.
Global symbol "%rmX_mainCenter" requires explicit package name at cf8geek.pl line 254.
Global symbol "%rmX_mainCenter" requires explicit package name at cf8geek.pl line 255.
Global symbol "%rmRR1_mainCenter" requires explicit package name at cf8geek.pl line 314.
Global symbol "%rmRR1_mainCenter" requires explicit package name at cf8geek.pl line 315.
Global symbol "%rmRR1_mainCenter" requires explicit package name at cf8geek.pl line 316.
Global symbol "%rmRR1_mainCenter" requires explicit package name at cf8geek.pl line 317.
Global symbol "%rmRR1_mainCenter" requires explicit package name at cf8geek.pl line 318.
cf8geek.pl has too many errors.



cf8geek
Novice

May 28, 2016, 3:04 PM

Post #4 of 10 (6750 views)
Re: [FishMonger] Bareword found/operator expected/missing semicolon? [In reply to] Can't Post


In Reply To
The Switch module is a source filter and is known to be fairly buggy. For awhile, the recommended alternative was to use a given/when block, but even that is no longer recommended and has been depreciated. The best practice is to use either an if/elsif/else block or a dispatch table instead of the Switch module.

I didn't know if/else was recommended over switch/case. Not sure what it means to be a source filter. Will rewrite with if/else.


In Reply To
Some of the other issues (poor coding practices) you have are:
1) Needlessly using global vars instead of lexical vars

Yes, I tend to globalize for debugging. Often, I find that the scope is too limited using my $var versus our $var.



In Reply To
2) Using prototype definitions

I wasn't able to receive variables passed to the subroutine without it... perhaps I was doing something else wrong?


In Reply To
3) Using & when calling your subs, which circumvents the prototype checking and introduces other side effects.

I had the recommended practice backwards in my head. I'll fix that. Thanks!


In Reply To
4) Declaring the same var multiple times in the same scope

Yes, I was trying to debug. I know it's bad. :-)


In Reply To
5) Using multiple hashes where an AoH (Array of Hashes) or HoH (Hash of Hashes) would be more appropriate.

I didn't know this was a thing! Will definitely look into it, thanks!

It seems I have a fair bit of research to do.
Thanks for all the info.


cf8geek
Novice

May 28, 2016, 3:06 PM

Post #5 of 10 (6749 views)
Re: [FishMonger] Bareword found/operator expected/missing semicolon? [In reply to] Can't Post


In Reply To
If you remove the prototype definition from the parseLine() sub, most of the warnings will go away [..]

Thanks!

When would a prototype definition be appropriate? Is there a good guide for this? The PerlDoc documentation seemed rather minimal... perhaps I just wasn't understanding it?


EDIT: I don't know if there's a "solved" function here, but the original question/problem is solved. Now I just have the remaining question about prototype definitions, and I can likely find that on Google if I try.


(This post was edited by cf8geek on May 28, 2016, 3:11 PM)


FishMonger
Veteran / Moderator

May 28, 2016, 3:38 PM

Post #6 of 10 (6737 views)
Re: [cf8geek] Bareword found/operator expected/missing semicolon? [In reply to] Can't Post

Far More Than Everything You've Ever Wanted to Know about Prototypes in Perl
http://www.perlmonks.org/?node_id=861966


Quote
Yes, I tend to globalize for debugging. Often, I find that the scope is too limited using my $var versus our $var.

That's a bad habit. It actually makes troubleshooting and maintenance more difficult, especially for others that may need to read/maintain the code.


Quote
When would a prototype definition be appropriate?

Almost never. Usually used when you want to override one of perl's built-in functions with your own custom function.

I see that you updated your code in that link and removed the scalar prototype definition but left the () parens in the definition. An empty prototype definition is still a definition. Remove the parens.
Should be:

Code
sub parseLine {



BillKSmith
Veteran

May 28, 2016, 3:40 PM

Post #7 of 10 (6736 views)
Re: [cf8geek] Bareword found/operator expected/missing semicolon? [In reply to] Can't Post

Your snippet can be coded neatly in native perl by using the ternary operator:

Code
$_ = $value; 
$status
= m/00/ ? 'on'
: m/80/ ? 'off'
: m/40/ ? 'Countdown'
: m/20/ ? 'Cooling Down'
: m/10/ ? 'Power Malfunction'
: m/28/ ? 'Cooling down at the temperature anomaly'
: m/02/ ? 'Unable to receive the RC232C command.'
: m/24/ ? 'Cooling down at Power Management mode'
: m/04/ ? 'Power Management mode after Cooling down'
: m/21/ ? 'Cooling down after the projector'
.' is turned off when the lamps are out.'
: m/81/ ? 'Stand-by mode after Cooling down when the lamps are out.'
: m/88/ ? 'Stand-by mode after Cooling down at the temperature anomaly.'
: 'illegal value'
;

Good Luck,
Bill


FishMonger
Veteran / Moderator

May 28, 2016, 3:49 PM

Post #8 of 10 (6734 views)
Re: [BillKSmith] Bareword found/operator expected/missing semicolon? [In reply to] Can't Post

Another good option would be to put the statuses in a hash and do a simple (1 line) hash lookup to assign $status.


Laurent_R
Veteran / Moderator

May 29, 2016, 2:28 AM

Post #9 of 10 (6722 views)
Re: [cf8geek] Bareword found/operator expected/missing semicolon? [In reply to] Can't Post

Hi,

let me just provide an example where prototype definition might be useful.

Suppose you want to write in pure Perl your own custom version of the map (or grep or sort) builtin function.

You could do something like this:


Code
sub my_map { 
my $code_ref = shift;
my @d ;
push @d, $code_ref->($_) for @_;
return @d;
}


You would need to call it with something like this:


Code
print join " ", my_map (sub{$_ * 2}, 1..5);


The calling syntax is a bit ugly. If I put my_map in a module and make it available, it is doubtful that many people will want to use it with such a syntax.

With prototype, I can write:

Code
sub my_map (&@){ 
my $code_ref = shift;
my @d;
push @d, $code_ref->($_) for @_;
return @d;
}


Now, the calling syntax can be the same as the original map calling syntax:

Code
my @array = 1..5; 
print join " ", my_map {$_ * 2} @array;


Now, the calling syntax is a lot clearer, especially if you already know map and its calling syntax.

Of course, writing a my_map function that does the same thing as the original map function is not very useful (and less efficient for large input data), but you could think of versions of my_map that behave slightly differently and might be useful. For example, a version that does not modify the original array if you modify $_ within the code reference passed to my_map:


Code
sub my_map (&@){ 
my $code_ref = shift;
my @d = @_;
$_ = $code_ref->($_) for @d;
return @d;
}


Similarly, you could write a function looking like grep that exits as soon as it has found one element for which the code reference returns true (a sort of first function), except that it already exists in CPAN modules.

Note that for the examples above to work, the definition of my_map must come before its use, or, at least, you would need a prototype definition to occur before its use. For example the my_map version that does not modify the original array even if the code reference modifies $_:


Code
sub my_map(&@);  # the prototype must occur before the call 

my @array = 1..5;
print "New array: ", join " ", my_map {++$_} @array;
print "\nOriginal array: ", "@array", "\n";

sub my_map (&@){
my $code_ref = shift;
my @d = @_;
$_ = $code_ref->($_) for @d;
return @d;
}
# output:
# New array: 2 3 4 5 6
# Original array: 1 2 3 4 5


I hope this helps.


(This post was edited by Laurent_R on May 29, 2016, 3:13 AM)


BillKSmith
Veteran

May 29, 2016, 4:31 AM

Post #10 of 10 (6713 views)
Re: [cf8geek] Bareword found/operator expected/missing semicolon? [In reply to] Can't Post

I recommend the following paper on prototypes: Far More Than Everything You've Ever Wanted to Know about Prototypes in Perl. You will probably find your answer in the first few paragraphs.
Good Luck,
Bill

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives