I made a mistake in my design waaay back when and am now under the gun to make a change that highlights the mistake. The mistake is convoluted, but basically depends on the fact that I assumed a given string will never have spaces in it, thus ucfirst will always handle it correctly.

What I should have done is to have a standard formatting function that handles things correctly.

The hackish fix is conceptually simple - put the following in my startup.pl

BEGIN { CORE::GLOBAL::ucfirst = sub { join ' ', map { s/^(.)/uc $1/e; $_ } split ' ', shift }; }

Replies are listed 'Best First'.
Re: Globally change ucfirst in mod_perl
by antirice (Priest) on May 20, 2004 at 06:20 UTC

    Two things:

    1. Redefining symbol table entries requires a leading asterick.
    2. The original ucfirst still exists as CORE::ucfirst.

    So that gives us:

    BEGIN { *CORE::GLOBAL::ucfirst = sub { join ' ', map CORE::ucfirst, split ' ', shift; } }

    antirice    
    The first rule of Perl club is - use Perl
    The
    ith rule of Perl club is - follow rule i - 1 for i > 1

      The first rule of Perl club is - use Perl
      The ith rule of Perl club is - follow rule i - 1 for i > 1

      Don't you mean:

      "The first rule of Perl club is - use Perl
      The $i".(int($i%100/10)-1?$i-3?$i-2?$i-1?'th':'st':'nd':'rd':'th' ." rule of Perl club is - follow rule \$i - 1 for \$i > 1"

      :-)

      cLive ;-)

      ps - it's late, and untested :)

      A couple of nits:
      1. Should default to $_
      2. using split ' ' replaces newlines and multiple spaces with single spaces
      Update: Brain-fart code deleted. See reply below for correct code.
      Update: Just discovered you don't even have to specify CORE:: on ucfirst. Perl knows:
      BEGIN { *CORE::GLOBAL::ucfirst = sub { join ' ', map ucfirst, split / /, @_ ? $_[0] : $_ } }

      The PerlMonk tr/// Advocate

        A couple of points:

        1. There's a slight bug as is shown in the code below:
          BEGIN { *CORE::GLOBAL::ucfirst = sub { join ' ', map CORE::ucfirst, split / /, defined $_[0] ? $_[0] : $ +_; } } $_ = "I shouldn't be printing this, but I am anyway."; my $var = undef; print ucfirst $var;

          Perhaps you should be checking for the number of parameters passed instead?

          BEGIN { *CORE::GLOBAL::ucfirst = sub { join ' ', map CORE::ucfirst, split / /, @_ ? $_[0] : $_; } }
        2. The reason I used split ' ' was because the OP used it. Perhaps it's the behavior he wanted. Maybe not? Either way, there are benefits in both approaches.

        antirice    
        The first rule of Perl club is - use Perl
        The
        ith rule of Perl club is - follow rule i - 1 for i > 1

Re: Globally change ucfirst in mod_perl
by Roy Johnson (Monsignor) on May 19, 2004 at 21:56 UTC
    Wouldn't it be easier to do
    join ' ', map {ucfirst} split / /, shift;
    Can't use ucfirst when you're redefining it, can you?
    Update: Actually, you can!
    I'll take my Bonehead Award anytime it's ready. Make it:
    join ' ', map { s/^(.)/\U$1/; $_ } split / /, shift
    That should work, right, since it's using uc instead of ucfirst.

    To do it with pure s///:

    (my $f=shift)=~s/(^| )(\w)/$1\U$2/g; # Doing it with lookbehind gets a little ugly: # s/(?:(?<=^)|(?<= ))(\w)/\U$1/g; $f;

    The PerlMonk tr/// Advocate
Re: Globally change ucfirst in mod_perl
by dragonchild (Archbishop) on May 20, 2004 at 01:34 UTC
    If you read the docs for ucfirst and \U, you'll notice that \U is implemented in terms of ucfirst. Can't use that, either. :-)

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

      No, \u is ucfirst, \U is uc. Interestingly, either will work in redefining ucfirst. Perl knows that \u means Perl's own ucfirst, even if ucfirst has been redefined.
      BEGIN { *CORE::GLOBAL::ucfirst = sub { join ' ', map "\u$_", split / /, @_ ? $_[0] : $_; } } $_ = "one two 'three' four\n"; print "\u$_"; print ucfirst;
      And in fact, my original suggestion even works! Perl is way ahead of the DWIM curve.
      BEGIN { *CORE::GLOBAL::ucfirst = sub { join ' ', map ucfirst, split / /, @_ ? $_[0] : $_; } } $_ = "one two 'three' four\n"; print "\u$_"; print ucfirst;
      Update: fixed default-as-$_ code.

      The PerlMonk tr/// Advocate