Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Parse error with subroutines and <

by TedYoung (Deacon)
on Dec 14, 2007 at 19:28 UTC ( [id://657098]=perlquestion: print w/replies, xml ) Need Help??

TedYoung has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

In my application framework I have packages that export subroutines. These subroutines are effectively treated as enumerations, however, behind the scenes they lazily load complex data from a database (these are not constants -- no () prototype).

I noticed a parsing problem with Perl:

use strict; use warnings; sub AL_CORP_MIN { 1 }; my $level = 1; if (AL_CORP_MIN < $level) { print 1 };

Gives me the following error:

Unterminated <> operator at index.app line 6.

If I change the code to the following:

use strict; use warnings; sub AL_CORP_MIN { 1 }; my $level = 1; if ($level > AL_CORP_MIN) { print 1 };

It parses and works just fine. I can live with this. However, in the real version the objects returned from these subroutines are overloaded to return numeric values so I often like to express ranges in the following format:

AL_CORP_MIN <= $level && $level <= AL_CORP_MAX

Another situation in which Perl improperly parses subroutine calls is the following:

use strict; use warnings; sub AL_CORP_MIN { 1 }; my $level = 1; my $foo = $level == AL_CORP_MIN ? 'a' : 'b';

Error:

Search pattern not terminated at index.app line 6.

Again, I can work around this with:

my $foo = $level == AL_CORP_MIN() ? 'a' : 'b';

None of these issues arise if the subs were defined as constant -- () prototype and simple bodies. I assume because the definitions are folded in.

My Perl version:

Summary of my perl5 (revision 5 version 8 subversion 8) configuration: Platform: osname=linux, osvers=2.6.22-3-amd64, archname=i486-linux-gnu-threa +d-multi uname='linux deneb 2.6.22-3-amd64 #1 smp thu oct 11 15:23:23 utc 2 +007 i686 gnulinux ' config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dccc +dlflags=-fPIC -Darchname=i486-linux-gnu -Dprefix=/usr -Dprivlib=/usr/ +share/perl/5.8 -Darchlib=/usr/lib/perl/5.8 -Dvendorprefix=/usr -Dvend +orlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/ +local -Dsitelib=/usr/local/share/perl/5.8.8 -Dsitearch=/usr/local/lib +/perl/5.8.8 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/ma +n3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man +3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs - +Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dlibperl=libperl.so.5.8.8 -Dd_ +dosuid -des' hint=recommended, useposix=true, d_sigaction=define usethreads=define use5005threads=undef useithreads=define usemulti +plicity=define useperlio=define d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS +-DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE +_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2', cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN +-fno-strict-aliasing -pipe -I/usr/local/include' ccversion='', gccversion='4.1.2 20061115 (prerelease) (Debian 4.1. +1-21)', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=1 +2 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', + lseeksize=8 alignbytes=4, prototype=define Linker and Libraries: ld='cc', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt perllibs=-ldl -lm -lpthread -lc -lcrypt libc=/lib/libc-2.3.6.so, so=so, useshrplib=true, libperl=libperl.s +o.5.8.8 gnulibc_version='2.3.6' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E' cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib' Characteristics of this binary (from libperl): Compile-time options: MULTIPLICITY PERL_IMPLICIT_CONTEXT PERL_MALLOC_WRAP THREADS_HAVE_PIDS USE_ITHREAD +S USE_LARGE_FILES USE_PERLIO USE_REENTRANT_API Built under linux Compiled at Nov 5 2007 06:11:48 @INC: /etc/perl /usr/local/lib/perl/5.8.8 /usr/local/share/perl/5.8.8 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.8 /usr/share/perl/5.8 /usr/local/lib/site_perl .

Ted Young

($$<<$$=>$$<=>$$<=$$>>$$) always returns 1. :-)

Replies are listed 'Best First'.
Re: Parse error with subroutines and <
by chromatic (Archbishop) on Dec 14, 2007 at 19:51 UTC

    With predeclaration or importing, Perl knows that your bareword is a function call. Without a prototype or parentheses around the argument list, Perl doesn't know its arity. There's no simple way to disambiguate between a <> glob call and your expression.

    I recommend using a prototype or parentheses.

      Good call on the arity! The reason I didn't want to give them a () prototype is because I will find it convenient to call them like:
      $enumClass->$enumName
      sometimes. I was getting ready to respond, it occurred to me that -> notation ignores prototypes! Yay! I get the best of both words. I guess it helps to talk things out!

      Thanks!

      Ted Young

      ($$<<$$=>$$<=>$$<=$$>>$$) always returns 1. :-)

        Just be careful you don't shadow one of your packages with a sub of the same name.

        use strict; use warnings; package Foo; sub bar { print "Foo::bar\n"; } package Bar; sub bar { print "Bar::bar\n"; } package main; sub Foo { "Bar" } Foo->bar(); "Foo"->bar(); exit 0; __END__

        The cake is a lie.
        The cake is a lie.
        The cake is a lie.

        The problem isn't that you're missing the prototype. The problem is that you're missing parens. Omitting parens leads to a lot of problem. Simply put, omitting parens is broken. You must be prepared to add them when necessary.
Re: Parse error with subroutines and <
by Fletch (Bishop) on Dec 14, 2007 at 19:55 UTC

    I don't think the issue is that the constants are inlined when you've given the () prototype, it's that it knows not to expect any arguments. Because it doesn't know how many arguments to expect (since you haven't prototyped and you're not using parens to demarcate where the argument list starts and stops) Perl thinks it's looking for a LIST of EXPRs to pass as arguments to your sub. You can also unconfuzzle by explicitly giving empty parens after your subroutine name (e.g. AL_CORP_MIN()).

    Update: Not that I don't agree that it's a little non-intuitive at first glance, and although I understand why it's working this way I can't come up with a better explanation that above offhand.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://657098]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (2)
As of 2024-04-24 14:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found