[32696] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 3960 Volume: 11

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Fri Jun 7 00:09:21 2013

Date: Thu, 6 Jun 2013 21:09:07 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Thu, 6 Jun 2013     Volume: 11 Number: 3960

Today's topics:
    Re: BEGIN, eval and $^S <adrien.barreau@live.fr>
    Re: BEGIN, eval and $^S <ben@morrow.me.uk>
    Re: BEGIN, eval and $^S <adrien.barreau@live.fr>
    Re: BEGIN, eval and $^S <ben@morrow.me.uk>
    Re: BEGIN, eval and $^S <adrien.barreau@live.fr>
    Re: BEGIN, eval and $^S <ben@morrow.me.uk>
    Re: BEGIN, eval and $^S <adrien.barreau@live.fr>
        index($str, [but with regex here]) <embe8573@student.uu.se>
    Re: index($str, [but with regex here]) <ben@morrow.me.uk>
    Re: index($str, [but with regex here]) <jurgenex@hotmail.com>
    Re: index($str, [but with regex here]) <embe8573@student.uu.se>
    Re: Is there a better way than this? <tzz@lifelogs.com>
    Re: Is there a better way than this? <ben@morrow.me.uk>
    Re: Is there a better way than this? <tzz@lifelogs.com>
    Re: Is there a better way than this? <rweikusat@mssgmbh.com>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: Wed, 05 Jun 2013 17:36:51 +0200
From: Adrien BARREAU <adrien.barreau@live.fr>
Subject: Re: BEGIN, eval and $^S
Message-Id: <konlm1$9fb$1@dont-email.me>

On 06/05/2013 04:20 PM, Ben Morrow wrote:
>
> Quoth Adrien BARREAU<adrien.barreau@live.fr>:
>> Hi all.
>>
>> If I run that piece of code:
>>
[ code skipped ]
>>
>> It prints:
>> False
>> Done
>>
>> Well, that, I understand.
>
> Hmm, well, that's the one that doesn't quite make sense to me. Perl
> isn't parsing that BEGIN block,

Aren't BEGIN block resolved during compilation phase?
I mean:

$ echo 'BEGIN { print "hello world\n" }' | perl -c -
hello world
- syntax OK


> it's running it

I can not say otherwise, but it's what you called 
'running-at-compile-time', and I thought that "compile-time" won.

, so I would expect $^S
> to be true. (Defined because we're running code, true because we're
> inside an eval{} so exceptions are being caught.)
>
>> If I change eval { die } to eval 'die', it prints:
>> Defined
>> True
>> Done
>>
>> Which I don't get.
>>
>> My only guess: since eval "" is described as a "little Perl program",
>> $^S is set to 1 because it refers to the "running" part of the eval,
>> after it has been successfully parsed. But, my "main" program is in
>> compilation time, so it seems strange.
>
> Yes, that's basically right. Not entirely right, since that would mean
> the first example should have $^S true as well,

That's precisely what troubles me :).

> but I suspect that's an
> inconsistency or an accident of some kind.
>
> You can have as many layers of BEGIN{}/eval"" as you like, each invoking
> a new level of running-at-compile-time or compiling-at-runtime. I think
> this covers all the important cases:
>
[ skipped code ]
>
> The BEGIN entries don't entirely make sense to me: I would have said,
> before trying it, that you could only get $^S=undef during a __DIE__
> handler handling an exception from a syntax error. That's certainly what
> the documentation implies, not to mention the blue Camel.

Your exemple is really interesting, though I don't get understand 
everything either.

>
> If you have 5.14 you can use ${^GLOBAL_PHASE} to get the 'main'
> interpreter state. On earlier perls you can use Devel::GlobalPhase to
> emulate the core variable.

I can not use one of those, I'll have to find something else (but I'll 
remember that module, didn't knew it).

>
>> Did I missed something about all that in the documentation?
>
> Yes, you missed the bit in perlvar that says 'don't use $SIG{__DIE__} or
> $^S' :). What are you actually trying to do here? There's probably an
> easier way to do it.

I do agree with that, but I have to deal with existing stuff that has to 
stay. So I'm trying to fix insidious issues in it.

Adrien.


------------------------------

Date: Wed, 5 Jun 2013 22:05:19 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: BEGIN, eval and $^S
Message-Id: <fpl48a-41q.ln1@anubis.morrow.me.uk>


Quoth Adrien BARREAU <adrien.barreau@live.fr>:
> On 06/05/2013 04:20 PM, Ben Morrow wrote:
> > Quoth Adrien BARREAU<adrien.barreau@live.fr>:
> >>
> >> If I run that piece of code:
> >>
> [ code skipped ]
> >>
> >> It prints:
> >> False
> >> Done
> >>
> >> Well, that, I understand.
> >
> > Hmm, well, that's the one that doesn't quite make sense to me. Perl
> > isn't parsing that BEGIN block,
> 
> Aren't BEGIN block resolved during compilation phase?
> I mean:
> 
> $ echo 'BEGIN { print "hello world\n" }' | perl -c -
> hello world
> - syntax OK
> 
> > it's running it
> 
> I can not say otherwise, but it's what you called 
> 'running-at-compile-time', and I thought that "compile-time" won.

Well, yeah, I think that's part of the problem here: 'at compile-time'
is an ambiguous phrase. Certainly, the BEGIN block is being run while
some piece code is being compiled, but at that moment the interpreter is
in 'run' mode, not 'compile' mode.

> , so I would expect $^S
> > to be true. (Defined because we're running code, true because we're
> > inside an eval{} so exceptions are being caught.)

This is really where I started my reasoning. The English.pm name of $^S
is $EXCEPTIONS_BEING_CAUGHT, and that is what it was intended for: to
tell you, in a __DIE__ handler, whether the exception you have just
intercepted was going to be fatal or not. Having $^S be undefined in
eval{}-in-BEGIN rather defeats that purpose, since in that case
exceptions most definitely are being caught, yet $^S is false.

It is probably possible to get a reliable indication of this using
caller: running up the call stack looking for a sub called "(eval)" will
tell you if you are inside some type of eval; some of the other elements
returned by caller will tell you what sort of eval (require/use,
eval-string, eval-block) you're dealing with. If you try this you need
to be aware that BEGIN blocks (and other magic blocks like DESTROY and
(I think) tie magic) are always wrapped in an implicit eval{}.

> >> If I change eval { die } to eval 'die', it prints:
> >> Defined
> >> True
> >> Done
> >>
> >> Which I don't get.
> >>
> >> My only guess: since eval "" is described as a "little Perl program",
> >> $^S is set to 1 because it refers to the "running" part of the eval,
> >> after it has been successfully parsed. But, my "main" program is in
> >> compilation time, so it seems strange.
> >
> > Yes, that's basically right. Not entirely right, since that would mean
> > the first example should have $^S true as well,
> 
> That's precisely what troubles me :).

Yeah. I don't think the behaviour is entirely consistent, or necessarily
terribly well thought-through.

> > If you have 5.14 you can use ${^GLOBAL_PHASE} to get the 'main'
> > interpreter state. On earlier perls you can use Devel::GlobalPhase to
> > emulate the core variable.
> 
> I can not use one of those, I'll have to find something else (but I'll 
> remember that module, didn't knew it).

You can get a rather crude 'runtime-indicator' like this:

    my $Phase;
    BEGIN { $Phase = "COMPILING" }
    INIT { $Phase = "RUNTIME" }

The sooner in the program you compile that code the closer to the true
start of runtime you will get.

> >> Did I missed something about all that in the documentation?
> >
> > Yes, you missed the bit in perlvar that says 'don't use $SIG{__DIE__} or
> > $^S' :). What are you actually trying to do here? There's probably an
> > easier way to do it.
> 
> I do agree with that, but I have to deal with existing stuff that has to 
> stay. So I'm trying to fix insidious issues in it.

So, explain :). There might be a better answer than fighting with
__DIE__ and $^S.

Ben



------------------------------

Date: Thu, 06 Jun 2013 10:12:31 +0200
From: Adrien BARREAU <adrien.barreau@live.fr>
Subject: Re: BEGIN, eval and $^S
Message-Id: <kopg0s$37n$1@dont-email.me>

[skip]

> This is really where I started my reasoning. The English.pm name of $^S
> is $EXCEPTIONS_BEING_CAUGHT, and that is what it was intended for: to
> tell you, in a __DIE__ handler, whether the exception you have just
> intercepted was going to be fatal or not. Having $^S be undefined in
> eval{}-in-BEGIN rather defeats that purpose, since in that case
> exceptions most definitely are being caught, yet $^S is false.
>
> It is probably possible to get a reliable indication of this using
> caller: running up the call stack looking for a sub called "(eval)" will
> tell you if you are inside some type of eval; some of the other elements
> returned by caller will tell you what sort of eval (require/use,
> eval-string, eval-block) you're dealing with. If you try this you need
> to be aware that BEGIN blocks (and other magic blocks like DESTROY and
> (I think) tie magic) are always wrapped in an implicit eval{}.

As far as you know, is there any doc about what triggers "implicit eval{}"s?

[skip]

>>
>> I do agree with that, but I have to deal with existing stuff that has to
>> stay. So I'm trying to fix insidious issues in it.
>
> So, explain :). There might be a better answer than fighting with
> __DIE__ and $^S.
>

Well, at first, it is work-related, so I am not that free.

The code that uses to check $^S in a __DIE__ signal is a custom Logger 
(no link to anythin in CPAN).
It has to catch when a die occurs in order to run some stuff (some dumps 
of our environment, CGI related stuff if run in that context, etc).

So basically: catch, do stuff, rethrow.
Rethrow basic idea: if ($eval) { return } else { exit -1 }
(so it is that "if ($eval)" that made me start that thread).

So, it doesn't try to achieve something with that __DIE__ signal, it 
just have to run stuff if a die occurs.
I doubt I can do that in a relaly different way. But I'd love to get 
ideas if you have some :). "Rewrite it" or "use CPAN stuff instead" are 
not available options, sadly.


Adrien.


------------------------------

Date: Thu, 6 Jun 2013 11:50:39 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: BEGIN, eval and $^S
Message-Id: <v4668a-7ea1.ln1@anubis.morrow.me.uk>


Quoth Adrien BARREAU <adrien.barreau@live.fr>:
> [skip]
> 
> > This is really where I started my reasoning. The English.pm name of $^S
> > is $EXCEPTIONS_BEING_CAUGHT, and that is what it was intended for: to
> > tell you, in a __DIE__ handler, whether the exception you have just
> > intercepted was going to be fatal or not. Having $^S be undefined in
> > eval{}-in-BEGIN rather defeats that purpose, since in that case
> > exceptions most definitely are being caught, yet $^S is false.
> >
> > It is probably possible to get a reliable indication of this using
> > caller: running up the call stack looking for a sub called "(eval)" will
> > tell you if you are inside some type of eval; some of the other elements
> > returned by caller will tell you what sort of eval (require/use,
> > eval-string, eval-block) you're dealing with. If you try this you need
> > to be aware that BEGIN blocks (and other magic blocks like DESTROY and
> > (I think) tie magic) are always wrapped in an implicit eval{}.
> 
> As far as you know, is there any doc about what triggers "implicit eval{}"s?

Anything calling call_sv with G_EVAL. I don't think there's any
comprehensive list of Perl constructions, but essentially anything
called implicitly by perl. So, signal handlers, BEGIN/END/INIT/CHECK/
UNITCHECK, source filter subs, PROPAGATE methods on exception objects,
DESTROY methods, overloaded constant handlers. Interestingly it seems I
was wrong about tie magic: these methods are called without an eval,
presumably because the call is entirely within the normal control flow.

Of course, the point is that exceptions are actually being caught in all
these cases. Some of them (signal handlers) will rethrow anything they
catch; some (BEGIN) will abort the current compilation unit, and some
(INIT) will abort the whole program.

> >> I do agree with that, but I have to deal with existing stuff that has to
> >> stay. So I'm trying to fix insidious issues in it.
> >
> > So, explain :). There might be a better answer than fighting with
> > __DIE__ and $^S.
> >
> 
> Well, at first, it is work-related, so I am not that free.
> 
> The code that uses to check $^S in a __DIE__ signal is a custom Logger 
> (no link to anythin in CPAN).
> It has to catch when a die occurs in order to run some stuff (some dumps 
> of our environment, CGI related stuff if run in that context, etc).
> 
> So basically: catch, do stuff, rethrow.
> Rethrow basic idea: if ($eval) { return } else { exit -1 }
> (so it is that "if ($eval)" that made me start that thread).
> 
> So, it doesn't try to achieve something with that __DIE__ signal, it 
> just have to run stuff if a die occurs.
> I doubt I can do that in a relaly different way. But I'd love to get 
> ideas if you have some :). "Rewrite it" or "use CPAN stuff instead" are 
> not available options, sadly.

Have you considered the obvious option: wrapping the code in a top-level
eval? The huge advantage of that is that if the exception is caught and
handled along the way you don't ever get as far as your top-level
handler. The most important disadvantage is that you can't get a stack
trace (or any other information about the immediate environment when the
exception was thrown), since the stack's been unwound, but there are
other ways of doing that. 

The cleanest is to write an exception class that takes a stack trace
when it's created, and make sure you only throw exceptions of that
class. If you already have an exception class you can obviously modify
it to do this fairly easily; Devel::StackTrace will give you a decent
realisation of a stack trace. 

If you can't do that you could use a CORE::GLOBAL::die override to stuff
appropriate information into globals and hand the exception back to
CORE::die to throw normally. Then you can pull the information out again
in your top-level handler, but *only* if the exception actually ends up
getting that far.

If for some reason you don't want to wrap the program in eval, you could
install an END block instead. END blocks are called before a top-level
exception exits, and they are called with $? == 255 since that is the
exit code perl is going to use. This is rather less reliable that an
eval, though, and there isn't any way of recovering and deciding not to
exit after all, so it's something of a last resort. (Of course, if
you're interesting in 'logging stuff', you may well want to log non-zero
exits in any case.)

The point here is to avoid trying to predict the future: it's extremely
difficult to guess whether a given exception will end up being fatal or
not, especially given that even if it is caught it might be rethrown, so
rather than guess just have the 'inner handler' stash the information
the 'outer handler' will need to do the proper reporting.

Ben



------------------------------

Date: Thu, 06 Jun 2013 13:23:24 +0200
From: Adrien BARREAU <adrien.barreau@live.fr>
Subject: Re: BEGIN, eval and $^S
Message-Id: <kopr6n$1rn$1@dont-email.me>


>
> Anything calling call_sv with G_EVAL. I don't think there's any
> comprehensive list of Perl constructions, but essentially anything
> called implicitly by perl. So, signal handlers, BEGIN/END/INIT/CHECK/
> UNITCHECK, source filter subs, PROPAGATE methods on exception objects,
> DESTROY methods, overloaded constant handlers. Interestingly it seems I
> was wrong about tie magic: these methods are called without an eval,
> presumably because the call is entirely within the normal control flow.
>
> Of course, the point is that exceptions are actually being caught in all
> these cases. Some of them (signal handlers) will rethrow anything they
> catch; some (BEGIN) will abort the current compilation unit, and some
> (INIT) will abort the whole program.

Interesting, thanks :).
For now, I not fluent in perlguts stuff, but I'll take a look to the C 
API to better understand that.

>
>>>> I do agree with that, but I have to deal with existing stuff that has to
>>>> stay. So I'm trying to fix insidious issues in it.
>>>
>>> So, explain :). There might be a better answer than fighting with
>>> __DIE__ and $^S.
>>>
>>
>> Well, at first, it is work-related, so I am not that free.
>>
>> The code that uses to check $^S in a __DIE__ signal is a custom Logger
>> (no link to anythin in CPAN).
>> It has to catch when a die occurs in order to run some stuff (some dumps
>> of our environment, CGI related stuff if run in that context, etc).
>>
>> So basically: catch, do stuff, rethrow.
>> Rethrow basic idea: if ($eval) { return } else { exit -1 }
>> (so it is that "if ($eval)" that made me start that thread).
>>
>> So, it doesn't try to achieve something with that __DIE__ signal, it
>> just have to run stuff if a die occurs.
>> I doubt I can do that in a relaly different way. But I'd love to get
>> ideas if you have some :). "Rewrite it" or "use CPAN stuff instead" are
>> not available options, sadly.
>
> Have you considered the obvious option: wrapping the code in a top-level
> eval? The huge advantage of that is that if the exception is caught and
> handled along the way you don't ever get as far as your top-level
> handler. The most important disadvantage is that you can't get a stack
> trace (or any other information about the immediate environment when the
> exception was thrown), since the stack's been unwound, but there are
> other ways of doing that.
>
> The cleanest is to write an exception class that takes a stack trace
> when it's created, and make sure you only throw exceptions of that
> class. If you already have an exception class you can obviously modify
> it to do this fairly easily; Devel::StackTrace will give you a decent
> realisation of a stack trace.
>
> If you can't do that you could use a CORE::GLOBAL::die override to stuff
> appropriate information into globals and hand the exception back to
> CORE::die to throw normally. Then you can pull the information out again
> in your top-level handler, but *only* if the exception actually ends up
> getting that far.
>
> If for some reason you don't want to wrap the program in eval, you could
> install an END block instead. END blocks are called before a top-level
> exception exits, and they are called with $? == 255 since that is the
> exit code perl is going to use. This is rather less reliable that an
> eval, though, and there isn't any way of recovering and deciding not to
> exit after all, so it's something of a last resort. (Of course, if
> you're interesting in 'logging stuff', you may well want to log non-zero
> exits in any case.)
>
> The point here is to avoid trying to predict the future: it's extremely
> difficult to guess whether a given exception will end up being fatal or
> not, especially given that even if it is caught it might be rethrown, so
> rather than guess just have the 'inner handler' stash the information
> the 'outer handler' will need to do the proper reporting.

Once again, I fully agree with you, but I can not something else than 
predicting the future.

That logger is a core module to us, so it is used in thousands of 
scripts: wrapping all scripts in eval{}s can not be done, neither 
changing all uses of die to use an exception class or overridding 
CORE::GLOBAL::die (because I can not do that in all scripts so nothing 
will ever ensure me that it is loaded).
END{} stuff is great, but as you said, only for logging purposes.

I'll, of course, keep all that in mind if big changes have to be done 
one day.


Adrien.


------------------------------

Date: Thu, 6 Jun 2013 14:03:48 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: BEGIN, eval and $^S
Message-Id: <kud68a-9ob1.ln1@anubis.morrow.me.uk>


Quoth Adrien BARREAU <adrien.barreau@live.fr>:
> [ ben@morrow.me.uk wrote: ]
> >
> > If you can't do that you could use a CORE::GLOBAL::die override to stuff
> > appropriate information into globals and hand the exception back to
> > CORE::die to throw normally. Then you can pull the information out again
> > in your top-level handler, but *only* if the exception actually ends up
> > getting that far.
> 
> Once again, I fully agree with you, but I can not something else than 
> predicting the future.
> 
> That logger is a core module to us, so it is used in thousands of 
> scripts: wrapping all scripts in eval{}s can not be done, neither 
> changing all uses of die to use an exception class or overridding 
> CORE::GLOBAL::die (because I can not do that in all scripts so nothing 
> will ever ensure me that it is loaded).

And you really can't arrange to call these scripts through a wrapper
something like this?

    #!/usr/bin/perl

    my @stack;
    *CORE::GLOBAL::die = sub {
        @stack = ();
        while (my @frame = caller @stack) {
            push @stack, \@frame;
        }
        # or just save away Carp::longmess, or whatever
    };

    my $script = shift @ARGV;
    # do is a form of string eval, so it catches exceptions
    unless (do $script) {
        # emit logs based on $@, @stack and other information
    }

ISTM all that should take is a minor adjustment to the webserver
configuration, or something like that, but I suppose the situation might
be more complicated than that.

Ben



------------------------------

Date: Thu, 06 Jun 2013 15:24:58 +0200
From: Adrien BARREAU <adrien.barreau@live.fr>
Subject: Re: BEGIN, eval and $^S
Message-Id: <koq2an$ecg$1@dont-email.me>

On 06/06/2013 03:03 PM, Ben Morrow wrote:
>
> Quoth Adrien BARREAU<adrien.barreau@live.fr>:
>>
>> That logger is a core module to us, so it is used in thousands of
>> scripts: wrapping all scripts in eval{}s can not be done, neither
>> changing all uses of die to use an exception class or overridding
>> CORE::GLOBAL::die (because I can not do that in all scripts so nothing
>> will ever ensure me that it is loaded).
>
> And you really can't arrange to call these scripts through a wrapper
> something like this?
>
>      #!/usr/bin/perl
>
>      my @stack;
>      *CORE::GLOBAL::die = sub {
>          @stack = ();
>          while (my @frame = caller @stack) {
>              push @stack, \@frame;
>          }
>          # or just save away Carp::longmess, or whatever
>      };
>
>      my $script = shift @ARGV;
>      # do is a form of string eval, so it catches exceptions
>      unless (do $script) {
>          # emit logs based on $@, @stack and other information
>      }
>
> ISTM all that should take is a minor adjustment to the webserver
> configuration, or something like that, but I suppose the situation might
> be more complicated than that.
>

That gives me some ideas of things I can try, but I can do something 
like that, no.
The main thing is that I have to cover *every* ways the issue can 
appear, and I'll never be able to do that by adding something. I can 
only do changes in existing things, "paths" that are always used and 
will stay.

Thanks for your answers Ben :).

Adrien.


------------------------------

Date: Thu, 06 Jun 2013 23:02:03 +0200
From: Emanuel Berg <embe8573@student.uu.se>
Subject: index($str, [but with regex here])
Message-Id: <87wqq7vtpw.fsf@VLAN-3434.student.uu.se>

I have this line:

my $end = index($end_str, " ");

What I need, is the same (an integer position), only the first
word delimiter should be taken from a set of possible chars: not
only whitespace, but end of line, parenthesis, etc.

I need to be able to define this char by char: for example, I
*don't* want the slash to be such a delimiter.

What do you think?

-- 
Emanuel Berg - programmer (hire me! CV below)
computer projects: http://user.it.uu.se/~embe8573
internet activity: http://home.student.uu.se/embe8573


------------------------------

Date: Thu, 6 Jun 2013 22:22:13 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: index($str, [but with regex here])
Message-Id: <55b78a-qbh1.ln1@anubis.morrow.me.uk>


Quoth Emanuel Berg <embe8573@student.uu.se>:
> I have this line:
> 
> my $end = index($end_str, " ");
> 
> What I need, is the same (an integer position), only the first
> word delimiter should be taken from a set of possible chars: not
> only whitespace, but end of line, parenthesis, etc.
> 
> I need to be able to define this char by char: for example, I
> *don't* want the slash to be such a delimiter.
> 
> What do you think?

You want $-[0], which returns the character position of the start of the
last successful match. So

    if ($end_str =~ /[\s\n()]/) {
        my $end = $-[0];
    }

You need the 'if', or something equivalent, because if the pattern
didn't match @- will have something random in it.

Ben



------------------------------

Date: Thu, 06 Jun 2013 14:35:34 -0700
From: Jürgen Exner <jurgenex@hotmail.com>
Subject: Re: index($str, [but with regex here])
Message-Id: <muv1r8to4tak8bh73h4afiq70ct9noj58k@4ax.com>

Emanuel Berg <embe8573@student.uu.se> wrote:
>I have this line:
>
>my $end = index($end_str, " ");
>
>What I need, is the same (an integer position), only the first
>word delimiter should be taken from a set of possible chars: not
>only whitespace, but end of line, parenthesis, etc.
>
>I need to be able to define this char by char: for example, I
>*don't* want the slash to be such a delimiter.

If nothing else you can always do it in two steps (error handling
omitted):

	$end_str =~ m/([MyReClass])/;
	$end = index($end_str, $1);

Replace MyReClass with whatever character set you like.

jue


------------------------------

Date: Thu, 06 Jun 2013 23:41:36 +0200
From: Emanuel Berg <embe8573@student.uu.se>
Subject: Re: index($str, [but with regex here])
Message-Id: <87obbix6gf.fsf@VLAN-3434.student.uu.se>

Thanks both. I only tried Ben's solution, as he was first and it
worked like a charm. I appreciate the crisp explanations.
-- 
Emanuel Berg - programmer (hire me! CV below)
computer projects: http://user.it.uu.se/~embe8573
internet activity: http://home.student.uu.se/embe8573


------------------------------

Date: Wed, 05 Jun 2013 11:53:40 -0400
From: Ted Zlatanov <tzz@lifelogs.com>
Subject: Re: Is there a better way than this?
Message-Id: <8738swzh8b.fsf@lifelogs.com>

On Tue, 4 Jun 2013 20:15:33 +0100 Ben Morrow <ben@morrow.me.uk> wrote: 

BM> If you have 5.14 you can squash this particular bit of stupidity with
BM> the /a switch. /\d/a, /\w/a and /\s/a all match what they used to in
BM> 5.6. (Except that I believe in 5.18 \s matches \v, that is, vertical
BM> tab, both with and without /a.)

BM> You can also turn on /a for all patterns in a lexical scope with 

BM>     use re "/a";

Neat, I didn't notice that one.

Is there a way to test for this feature, or do I just have to require 5.14?

Ted


------------------------------

Date: Wed, 5 Jun 2013 20:22:05 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Is there a better way than this?
Message-Id: <tnf48a-c7o.ln1@anubis.morrow.me.uk>


Quoth Ted Zlatanov <tzz@lifelogs.com>:
> On Tue, 4 Jun 2013 20:15:33 +0100 Ben Morrow <ben@morrow.me.uk> wrote: 
> 
> BM> If you have 5.14 you can squash this particular bit of stupidity with
> BM> the /a switch. /\d/a, /\w/a and /\s/a all match what they used to in
> BM> 5.6. (Except that I believe in 5.18 \s matches \v, that is, vertical
> BM> tab, both with and without /a.)
> 
> BM> You can also turn on /a for all patterns in a lexical scope with 
> BM>     use re "/a";
> 
> Neat, I didn't notice that one.

Thanks. (I pushed quite hard for this...)

> Is there a way to test for this feature, or do I just have to require 5.14?

That, actually, is annoyingly difficult, because 're' doesn't fail when
you pass a bad switch, it just throws a warning with Carp. I think that
means the best you can do is

    BEGIN {
        require re;
        $SIG{__WARN__} = sub {};
        re->import("/a");
    }

which isn't exactly tidy. Of course, you could wrap this up in the
import method of another module if you thought it was worth it.

If you're happy relying on perl versions rather than the re module
itself (probably pretty safe) you could use

    use if $] >= 5.014, re => "/a";

Ben



------------------------------

Date: Thu, 06 Jun 2013 09:10:42 -0400
From: Ted Zlatanov <tzz@lifelogs.com>
Subject: Re: Is there a better way than this?
Message-Id: <87y5anv0z1.fsf@lifelogs.com>

On Wed, 5 Jun 2013 20:22:05 +0100 Ben Morrow <ben@morrow.me.uk> wrote: 

BM> If you're happy relying on perl versions rather than the re module
BM> itself (probably pretty safe) you could use

BM>     use if $] >= 5.014, re => "/a";

That's really useful, thanks.

Ted


------------------------------

Date: Thu, 06 Jun 2013 19:04:48 +0100
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: Is there a better way than this?
Message-Id: <87y5anglof.fsf@sapphire.mobileactivedefense.com>

Ben Morrow <ben@morrow.me.uk> writes:
> Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:

[code using $1]

>> The obivious other way to write this is
>> 
>> ($oc) = $outcode =~ /^([A-Z]{1,2})\d/;
>
> I would consider this better style; there's no point mucking about with
> magic globals if you don't need to.

In this case, the point would be 'they are available and using them is
convenient'. Eg, assuming some kind of error handling was intended,
this could be written as

	if ($outcode =~ /^([A-Z]{1,2})\d/) {
		# use the captured value here
	} else {
		# complain
	}

Of course, 

	if (($oc) = $outcode =~ /^([A-Z]{1,2})\d/) {
		# use the captured value here
	} else {
		# complain
	}

would work as well but it is more complicated expression and IMO,
if-expressions with side-effects should be avoided. Also, a variable
needs to be declared for everything which is supposed to be captured
via return value but the individual captured expression might not be
useful on their own. Contrived example:

sub hton_postcode
{
        return $_[0] =~ /(...)\s+(...)/ && "$2 $1";
}

This is even 'safe' in the sense that it won't affect the $n of the
caller because the capture-variables are always automatically local to
the enclosing block.


------------------------------

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

Back issues are available via anonymous ftp from
ftp://cil-www.oce.orst.edu/pub/perl/old-digests. 

#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V11 Issue 3960
***************************************


home help back first fref pref prev next nref lref last post