Distribution · Perl 5 compatibility
P5lcfirst
WorksPerl's lcfirst and ucfirst — which uppercase the first character where Raku's .tc titlecases it.
- Version
0.0.12zef:lizmat- Depends
none beyond the core- License
- Artistic-2.0
- Its own test suite
- 3 files, green
- Checked
- 2026-09-15 against Raku++ 3.28.0 and Rakudo 2026.08
Install it #
$ rakupp install P5lcfirstzef install P5lcfirst writes the same store; either installer leaves the module usable by both engines.
What it is for #
Lower-casing or upper-casing just the first character, leaving the rest alone. Raku has .tc and .lc, but .tc is titlecase, which is not the same operation — and Perl code says ucfirst.
Using it #
File
use P5lcfirst;
say 'lcfirst("HELLO") = ', lcfirst('HELLO').raku;
say 'ucfirst("hello") = ', ucfirst('hello').raku;
say 'lcfirst("hello") = ', lcfirst('hello').raku;
say 'ucfirst("HELLO") = ', ucfirst('HELLO').raku;
say '';
say 'the REST of the string is untouched, which is the whole point:';
say ' ucfirst("mcDONALD") = ', ucfirst('mcDONALD').raku;
say ' lcfirst("XMLParser") = ', lcfirst('XMLParser').raku;
say '';
say 'edges:';
for '', 'a', '1abc' -> $s {
say sprintf(' ucfirst(%-8s) = %-10s lcfirst(%-8s) = %s',
$s.raku, ucfirst($s).raku, $s.raku, lcfirst($s).raku);
}Output
lcfirst("HELLO") = "hELLO"
ucfirst("hello") = "Hello"
lcfirst("hello") = "hello"
ucfirst("HELLO") = "HELLO"
the REST of the string is untouched, which is the whole point:
ucfirst("mcDONALD") = "McDONALD"
lcfirst("XMLParser") = "xMLParser"
edges:
ucfirst("" ) = "" lcfirst("" ) = ""
ucfirst("a" ) = "A" lcfirst("a" ) = "a"
ucfirst("1abc" ) = "1abc" lcfirst("1abc" ) = "1abc"The one thing to know #
ucfirst uppercases where Raku's .tc titlecases. For the handful of Unicode characters where those differ, the two give different answers.
File
use P5lcfirst;
my $dz = "\c[LATIN SMALL LETTER DZ WITH CARON]";
say 'the digraph dž (U+01C6):';
say ' ucfirst -> ', ucfirst($dz).raku, ' ', ucfirst($dz).substr(0, 1).uniname;
say ' .tc -> ', $dz.tc.raku, ' ', $dz.tc.substr(0, 1).uniname;
say '';
say 'Unicode gives that character three cases, not two: a lowercase dž, a';
say 'titlecase Dž and an uppercase DŽ. ucfirst picks the uppercase one and';
say '.tc picks the titlecase one, and for a word-initial letter the';
say 'titlecase form is the correct typography.';
say '';
say 'the same split applies to the other digraphs:';
for "\c[LATIN SMALL LETTER LJ]", "\c[LATIN SMALL LETTER NJ]",
"\c[LATIN SMALL LETTER DZ]" -> $c {
say sprintf(' %s : ucfirst %-4s .tc %-4s differ ? %s',
$c, ucfirst($c).raku, $c.tc.raku, ucfirst($c) ne $c.tc);
}
say '';
say 'for ASCII, and for every ordinary accented letter, the two agree:';
say ' ucfirst("hello") eq "hello".tc : ', ucfirst('hello') eq 'hello'.tc;
say ' ucfirst("élan") eq "élan".tc : ',
ucfirst("\c[LATIN SMALL LETTER E WITH ACUTE]lan") eq "\c[LATIN SMALL LETTER E WITH ACUTE]lan".tc;Output
the digraph dž (U+01C6):
ucfirst -> "DŽ" LATIN CAPITAL LETTER DZ WITH CARON
.tc -> "Dž" LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON
Unicode gives that character three cases, not two: a lowercase dž, a
titlecase Dž and an uppercase DŽ. ucfirst picks the uppercase one and
.tc picks the titlecase one, and for a word-initial letter the
titlecase form is the correct typography.
the same split applies to the other digraphs:
lj : ucfirst "LJ" .tc "Lj" differ ? True
nj : ucfirst "NJ" .tc "Nj" differ ? True
dz : ucfirst "DZ" .tc "Dz" differ ? True
for ASCII, and for every ordinary accented letter, the two agree:
ucfirst("hello") eq "hello".tc : True
ucfirst("élan") eq "élan".tc : TrueWhere the two engines differ #
Nothing. Both names, both operations and the digraph split behave identically.
File
use P5lcfirst;
say 'the end state of a port is core Raku:';
say ' "hello".tc = ', 'hello'.tc.raku, ' <- titlecase the first character';
say ' "HELLO".lcfirst — no such method; use a substr:';
sub lc-first(Str $s) { $s.chars ?? $s.substr(0, 1).lc ~ $s.substr(1) !! $s }
say ' lc-first("HELLO") = ', lc-first('HELLO').raku;
say '';
say 'and if you specifically want the uppercase rather than the titlecase';
say 'first character, say so:';
sub uc-first(Str $s) { $s.chars ?? $s.substr(0, 1).uc ~ $s.substr(1) !! $s }
my $dz = "\c[LATIN SMALL LETTER DZ WITH CARON]";
say ' uc-first(dz) = ', uc-first($dz).raku, ' .tc = ', $dz.tc.raku;
say '';
say 'that is the decision this module makes for you, and the reason to';
say 'make it deliberately when the port is finished.';Output
the end state of a port is core Raku:
"hello".tc = "Hello" <- titlecase the first character
"HELLO".lcfirst — no such method; use a substr:
lc-first("HELLO") = "hELLO"
and if you specifically want the uppercase rather than the titlecase
first character, say so:
uc-first(dz) = "DŽ" .tc = "Dž"
that is the decision this module makes for you, and the reason to
make it deliberately when the port is finished.