Finally got around to some more json formatting activity!
- error messaging proof of concept via codespan diagnostics
- handle unexpected control characters
- handles whitespace as per the spec
- error messaging proof of concept via codespan diagnostics
- handle unexpected control characters
- handles whitespace as per the spec
November 12, 2025 at 6:38 AM
Finally got around to some more json formatting activity!
- error messaging proof of concept via codespan diagnostics
- handle unexpected control characters
- handles whitespace as per the spec
- error messaging proof of concept via codespan diagnostics
- handle unexpected control characters
- handles whitespace as per the spec
Even small short threads felt so tedious because you spent 10 mins formatting it
Like?? What happened to just,,,, writing and replying and calling it a day
I don’t want to sit there holding and italicising punctuation and every other vowel bro
Like?? What happened to just,,,, writing and replying and calling it a day
I don’t want to sit there holding and italicising punctuation and every other vowel bro
November 12, 2025 at 6:24 AM
Even small short threads felt so tedious because you spent 10 mins formatting it
Like?? What happened to just,,,, writing and replying and calling it a day
I don’t want to sit there holding and italicising punctuation and every other vowel bro
Like?? What happened to just,,,, writing and replying and calling it a day
I don’t want to sit there holding and italicising punctuation and every other vowel bro
And there was so much PRESSURE. To make your blog look nice and barely readable sometimes. Had to have a fancy theme, fancy edited icons with an overlay, fancy banners with outlines and frames…
Don’t get me STARTED on formatting replies… bold italic every other word , big font small font
Don’t get me STARTED on formatting replies… bold italic every other word , big font small font
November 12, 2025 at 6:24 AM
And there was so much PRESSURE. To make your blog look nice and barely readable sometimes. Had to have a fancy theme, fancy edited icons with an overlay, fancy banners with outlines and frames…
Don’t get me STARTED on formatting replies… bold italic every other word , big font small font
Don’t get me STARTED on formatting replies… bold italic every other word , big font small font
The keyboard command to paste text without formatting is the worst imo
November 12, 2025 at 6:20 AM
The keyboard command to paste text without formatting is the worst imo
Yeah! Formatting mostly. How to figure out my indesign doc so it prints for saddlestitch and figuring out how much/if i need bleed if i only have 8.5x11 paper to print on!
Ive made some progress!!
Ive made some progress!!
November 12, 2025 at 5:50 AM
Yeah! Formatting mostly. How to figure out my indesign doc so it prints for saddlestitch and figuring out how much/if i need bleed if i only have 8.5x11 paper to print on!
Ive made some progress!!
Ive made some progress!!
it’s good for formatting, i.e. take this huge data set and format it in a specific way for me
November 12, 2025 at 5:49 AM
it’s good for formatting, i.e. take this huge data set and format it in a specific way for me
I should prob either pratice handwriting or completely just slap text from my art app (my handwriting is the worst)
I wanted to make (serious) comics again but I don't know how to start as formatting isn't something I haven't done before
I wanted to make (serious) comics again but I don't know how to start as formatting isn't something I haven't done before
November 12, 2025 at 5:16 AM
I should prob either pratice handwriting or completely just slap text from my art app (my handwriting is the worst)
I wanted to make (serious) comics again but I don't know how to start as formatting isn't something I haven't done before
I wanted to make (serious) comics again but I don't know how to start as formatting isn't something I haven't done before
Unbelievably! And I'm not experienced at formatting any of this the way NZ schools are probably used to receiving CVs from prospective teachers.
November 12, 2025 at 5:04 AM
Unbelievably! And I'm not experienced at formatting any of this the way NZ schools are probably used to receiving CVs from prospective teachers.
This started off as just a fun comic/drawing idea, but I think I might make it into a short story, if I can figure out all the pieces.
Why I like people offering up their meat to be eaten, I do not know. But I do, we'll keep getting it :P
#horror #art #comic #meat #writing #blood
Why I like people offering up their meat to be eaten, I do not know. But I do, we'll keep getting it :P
#horror #art #comic #meat #writing #blood
November 12, 2025 at 4:35 AM
even the boring business documents need attention wrt making sure terminology is consistent and follows the company's preferences, as well as the other typical considerations when translating into another language
fwiw MT is still poor at handling formatting, particularly mid-sentence linebreaks
fwiw MT is still poor at handling formatting, particularly mid-sentence linebreaks
November 12, 2025 at 4:32 AM
even the boring business documents need attention wrt making sure terminology is consistent and follows the company's preferences, as well as the other typical considerations when translating into another language
fwiw MT is still poor at handling formatting, particularly mid-sentence linebreaks
fwiw MT is still poor at handling formatting, particularly mid-sentence linebreaks
"isn't that just reinventing the benchbook from first principles" yes but with immaculate formatting and referencing ✨ (to which I will invariably dedicate way too much time at the expense of, you know, rereading my submissions for clarity of language and argument)
November 12, 2025 at 4:29 AM
"isn't that just reinventing the benchbook from first principles" yes but with immaculate formatting and referencing ✨ (to which I will invariably dedicate way too much time at the expense of, you know, rereading my submissions for clarity of language and argument)
@SnoopJ have you yet encountered the subgenre of this Guy who will literally just paste GPT output at you with the formatting still intact
November 12, 2025 at 4:28 AM
@SnoopJ have you yet encountered the subgenre of this Guy who will literally just paste GPT output at you with the formatting still intact
Shout out also to the works of Edgar Cantero (This Body's Not Big Enough For the Both of Us) and Peter Carey (Amnesia), which tell America's way of formatting things to get out of the fucking way and focus on what it's actually here to say.
November 12, 2025 at 4:04 AM
Shout out also to the works of Edgar Cantero (This Body's Not Big Enough For the Both of Us) and Peter Carey (Amnesia), which tell America's way of formatting things to get out of the fucking way and focus on what it's actually here to say.
Trying Blogger to post longer pieces than I can fit on a microblogging platform. I think I'll call it "macromicroblogging."
I still need to figure out formatting and some other stuff but feel free to read this (if you can).
seanslaboratory.blogspot.com/2025/11/some...
I still need to figure out formatting and some other stuff but feel free to read this (if you can).
seanslaboratory.blogspot.com/2025/11/some...
Some thoughts on memory.
Douglas Hofstadter has some interesting bits about how we don't store memories like movies, but store "symbols" of the relevant things and w...
seanslaboratory.blogspot.com
November 12, 2025 at 3:42 AM
Trying Blogger to post longer pieces than I can fit on a microblogging platform. I think I'll call it "macromicroblogging."
I still need to figure out formatting and some other stuff but feel free to read this (if you can).
seanslaboratory.blogspot.com/2025/11/some...
I still need to figure out formatting and some other stuff but feel free to read this (if you can).
seanslaboratory.blogspot.com/2025/11/some...
Perl Weekly Challenge 347's tasks are formatting dates and phone numbers, so I'm offering up ELO's Telephone Line as this week's musical theme.
Doo-wop, doo-be-doo-doo-wop, doo-wah, doo-languages...
#PerlWeeklyChallenge #raku #perl #python #elixir
Doo-wop, doo-be-doo-doo-wop, doo-wah, doo-languages...
#PerlWeeklyChallenge #raku #perl #python #elixir
Perl Weekly Challenge: Oh, oh, formatted strings, give me some thing… | Packy’s Place
packy.dardan.com
November 12, 2025 at 3:03 AM
Perl Weekly Challenge 347's tasks are formatting dates and phone numbers, so I'm offering up ELO's Telephone Line as this week's musical theme.
Doo-wop, doo-be-doo-doo-wop, doo-wah, doo-languages...
#PerlWeeklyChallenge #raku #perl #python #elixir
Doo-wop, doo-be-doo-doo-wop, doo-wah, doo-languages...
#PerlWeeklyChallenge #raku #perl #python #elixir
Perl Weekly Challenge: Oh, oh, formatted strings, give me some thing…
Perl Weekly Challenge 347's tasks are formatting dates and phone numbers, so I'm offering up ELO's Telephone Line as this week's musical theme. Doo-wop, doo-be-doo-doo-wop, doo-wah, doo-languages...
https://packy.dardan.com/b/dp
Perl Weekly Challenge 347's tasks are formatting dates and phone numbers, so I'm offering up ELO's Telephone Line as this week's musical theme. Doo-wop, doo-be-doo-doo-wop, doo-wah, doo-languages...
https://packy.dardan.com/b/dp
Perl Weekly Challenge: Oh, oh, formatted strings, give me some thing…
Perl Weekly Challenge 347‘s tasks are formatting dates and phone numbers, so I’m offering up ELO’s Telephone Line as this week’s musical theme.
Doo-wop, doo-be-doo-doo-wop, doo-wah, doo-languages…
* Task 1: Format Date
* Approach
* Raku
* Perl
* Python
* Elixir
* Task 2: Format Phone Number
* Approach
* Elixir
* Raku
* Perl
* Python
# Task 1: Format Date
You are given a date in the form: `10th Nov 2025`.
Write a script to format the given date in the form: `2025-11-10` using the set below.
@DAYS = ("1st", "2nd", "3rd", ....., "30th", "31st")
@MONTHS = ("Jan", "Feb", "Mar", ....., "Nov", "Dec")
@YEARS = (1900..2100)
**Example 1**
Input: $str = "1st Jan 2025"
Output: "2025-01-01"
**Example 2**
Input: $str = "22nd Feb 2025"
Output: "2025-02-22"
**Example 3**
Input: $str = "15th Apr 2025"
Output: "2025-04-15"
**Example 4**
Input: $str = "23rd Oct 2025"
Output: "2025-10-23"
**Example 5**
Input: $str = "31st Dec 2025"
Output: "2025-12-31"
## Approach
Well, how difficult this will be to do depends on how much validation we want to do of the input. Do we want to accept days with the incorrect ordinal (`22th` instead of `22nd`)? Do we want to accept years outside the given year range (`2525`)?
I’m going to take the approach that I’m going to do some validation on the input first, then format the date, even though that’s going to wind up being most of the solution.
Validating the days **could** be done by building a list of `@DAYS` like shown above, or we could use a regular expression to grab the numeric portion and the ordinal, and then test to see if the number is 1, 21, or 31, the ordinal should be “st”, if the number is 2 or 22, the ordinal should be “nd”, if the number is 3 or 23, the ordinal should be “rd”. and otherwise the ordinal should be “th”. Similarly, the years we can just compare `1900 <= year <= 2100`. The months, however, make sense to enumerate in their entirety.
## Raku
But, because I need to not only check to see if the month provided is in the set of `@MONTHS`, but then translate that to a number, rather than storing the set as an array, I’m storing it as a hash, which allows me to test for membership AND translate to a numeric value.
One of the things I like about Raku is the ability to do a conditional like `1900 <= $year <= 2100`.
my %months = (
Jan => 1, Feb => 2, Mar => 3, Apr => 4, May => 5, Jun => 6,
Jul => 7, Aug => 8, Sep => 9, Oct => 10, Nov => 11, Dec => 12
);
sub formatDate($str) {
my ($day, $month, $year) = $str.split(" ");
my $m = $day ~~ /(\d+)(\D+)/;
return "$day has the incorrect ordinal"
unless
(($m[0] == 1 || $m[0] == 21 || $m[0] == 31) && $m[1] eq "st")
||
(($m[0] == 2 || $m[0] == 22) && $m[1] eq "nd")
||
(($m[0] == 3 || $m[0] == 23) && $m[1] eq "rd")
||
$m[1] eq "th";
$day = $m[0]; # grab just the numeric portion
return "Unknown month '$month'"
unless %months{$month}:exists;
$month = %months{$month}; # convert to numeric
return "Year must be between 1900-2100"
unless 1900 <= $year <= 2100;
my $date;
try {
$date = Date.new($year, $month, $day);
}
return $! if $!;
return qq/"$date"/;
}
my %months = (
Jan => 1, Feb => 2, Mar => 3, Apr => 4, May => 5, Jun => 6,
Jul => 7, Aug => 8, Sep => 9, Oct => 10, Nov => 11, Dec => 12
);
sub formatDate($str) {
my ($day, $month, $year) = $str.split(" ");
my $m = $day ~~ /(\d+)(\D+)/;
return "$day has the incorrect ordinal"
unless
(($m[0] == 1 || $m[0] == 21 || $m[0] == 31) && $m[1] eq "st")
||
(($m[0] == 2 || $m[0] == 22) && $m[1] eq "nd")
||
(($m[0] == 3 || $m[0] == 23) && $m[1] eq "rd")
||
$m[1] eq "th";
$day = $m[0]; # grab just the numeric portion
return "Unknown month '$month'"
unless %months{$month}:exists;
$month = %months{$month}; # convert to numeric
return "Year must be between 1900-2100"
unless 1900 <= $year <= 2100;
my $date;
try {
$date = Date.new($year, $month, $day);
}
return $! if $!;
return qq/"$date"/;
}
View the entire Raku script for this task on GitHub.
$ raku/ch-1.raku
Example 1:
Input: $str = "1st Jan 2025"
Output: "2025-01-01"
Example 2:
Input: $str = "22nd Feb 2025"
Output: "2025-02-22"
Example 3:
Input: $str = "15th Apr 2025"
Output: "2025-04-15"
Example 4:
Input: $str = "23rd Oct 2025"
Output: "2025-10-23"
Example 5:
Input: $str = "31st Dec 2025"
Output: "2025-12-31"
Example Year Too Big:
Input: $str = "31st Dec 2525"
Output: Year must be between 1900-2100
Example Year Too Small:
Input: $str = "31st Dec 1825"
Output: Year must be between 1900-2100
Example Bad Ordinal:
Input: $str = "31nd Dec 2025"
Output: 31nd has the incorrect ordinal
Example Bad Month:
Input: $str = "30th Avril 2025"
Output: Unknown month 'Avril'
Example Bad Date:
Input: $str = "31st Feb 2025"
Output: Day out of range. Is: 31, should be in 1..28
$ raku/ch-1.raku
Example 1:
Input: $str = "1st Jan 2025"
Output: "2025-01-01"
Example 2:
Input: $str = "22nd Feb 2025"
Output: "2025-02-22"
Example 3:
Input: $str = "15th Apr 2025"
Output: "2025-04-15"
Example 4:
Input: $str = "23rd Oct 2025"
Output: "2025-10-23"
Example 5:
Input: $str = "31st Dec 2025"
Output: "2025-12-31"
Example Year Too Big:
Input: $str = "31st Dec 2525"
Output: Year must be between 1900-2100
Example Year Too Small:
Input: $str = "31st Dec 1825"
Output: Year must be between 1900-2100
Example Bad Ordinal:
Input: $str = "31nd Dec 2025"
Output: 31nd has the incorrect ordinal
Example Bad Month:
Input: $str = "30th Avril 2025"
Output: Unknown month 'Avril'
Example Bad Date:
Input: $str = "31st Feb 2025"
Output: Day out of range. Is: 31, should be in 1..28
## Perl
There wasn’t much translation necessary going from Raku to Perl. I was able to directly capture the result of the regex match, instead of needing to put it in a match object. and my year conditional needed an and and repeating the variable: `1900 <= $year && $year <= 2100`.
I used `Time::Local` to translate the year, month, day into a epoch timestamp, and then `Time::Piece` to format that as a date string.
use Time::Local;
use Time::Piece;
my %months = (
Jan => 1, Feb => 2, Mar => 3, Apr => 4, May => 5, Jun => 6,
Jul => 7, Aug => 8, Sep => 9, Oct => 10, Nov => 11, Dec => 12
);
sub formatDate($str) {
my ($day, $month, $year) = split / /, $str;
my ($dnum, $dord) = $day =~ /(\d+)(\D+)/;
return "$day has the incorrect ordinal"
unless
(($dnum == 1 || $dnum == 21 || $dnum == 31) && $dord eq "st")
||
(($dnum == 2 || $dnum == 22) && $dord eq "nd")
||
(($dnum == 3 || $dnum == 23) && $dord eq "rd")
||
$dord eq "th";
$day = $dnum; # grab just the numeric portion
return "Unknown month '$month'"
unless exists $months{$month};
$month = $months{$month}; # convert to numeric
return "Year must be between 1900-2100"
unless 1900 <= $year && $year <= 2100;
my $date;
eval {
my $epoch = timelocal(0, 0, 0, $day, $month-1, $year);
$date = Time::Piece->new($epoch);
};
if (my $err = $@) { # get rid of line info in the error
$err =~ s{at .+ line \d+.\n}{};
return $err;
}
return qq/"@{[ $date->date ]}"/;
}
use Time::Local;
use Time::Piece;
my %months = (
Jan => 1, Feb => 2, Mar => 3, Apr => 4, May => 5, Jun => 6,
Jul => 7, Aug => 8, Sep => 9, Oct => 10, Nov => 11, Dec => 12
);
sub formatDate($str) {
my ($day, $month, $year) = split / /, $str;
my ($dnum, $dord) = $day =~ /(\d+)(\D+)/;
return "$day has the incorrect ordinal"
unless
(($dnum == 1 || $dnum == 21 || $dnum == 31) && $dord eq "st")
||
(($dnum == 2 || $dnum == 22) && $dord eq "nd")
||
(($dnum == 3 || $dnum == 23) && $dord eq "rd")
||
$dord eq "th";
$day = $dnum; # grab just the numeric portion
return "Unknown month '$month'"
unless exists $months{$month};
$month = $months{$month}; # convert to numeric
return "Year must be between 1900-2100"
unless 1900 <= $year && $year <= 2100;
my $date;
eval {
my $epoch = timelocal(0, 0, 0, $day, $month-1, $year);
$date = Time::Piece->new($epoch);
};
if (my $err = $@) { # get rid of line info in the error
$err =~ s{at .+ line \d+.\n}{};
return $err;
}
return qq/"@{[ $date->date ]}"/;
}
View the entire Perl script for this task on GitHub.
## Python
Python has a match object like Raku, and I was able to catch the exception from a bad date without much fuss.
from datetime import date
import re
months = {
'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12
}
def format_date(dstr):
day, month, year = dstr.split()
m = re.match(r'(\d+)(\D+)', day)
dnum = int(m.group(1)) # make sure it's an int
dord = m.group(2)
if not (
((dnum == 1 or dnum == 21 or dnum == 31) and dord == "st")
or
((dnum == 2 or dnum == 22) and dord == "nd")
or
((dnum == 3 or dnum == 23) and dord == "rd")
or
dord == "th"
):
return f"{day} has the incorrect ordinal"
day = dnum # grab just the numeric portion
if not month in months:
return f"Unknown month '{month}'"
month = months[month] # convert to numeric
year = int(year) # make sure it's an int
if not (1900 <= year <= 2100):
return "Year must be between 1900-2100"
try:
dateobj = date(year, month, day)
except ValueError as err:
return err
return f'"#{dateobj.strftime("%Y-%m-%d")}"'
from datetime import date
import re
months = {
'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12
}
def format_date(dstr):
day, month, year = dstr.split()
m = re.match(r'(\d+)(\D+)', day)
dnum = int(m.group(1)) # make sure it's an int
dord = m.group(2)
if not (
((dnum == 1 or dnum == 21 or dnum == 31) and dord == "st")
or
((dnum == 2 or dnum == 22) and dord == "nd")
or
((dnum == 3 or dnum == 23) and dord == "rd")
or
dord == "th"
):
return f"{day} has the incorrect ordinal"
day = dnum # grab just the numeric portion
if not month in months:
return f"Unknown month '{month}'"
month = months[month] # convert to numeric
year = int(year) # make sure it's an int
if not (1900 <= year <= 2100):
return "Year must be between 1900-2100"
try:
dateobj = date(year, month, day)
except ValueError as err:
return err
return f'"#{dateobj.strftime("%Y-%m-%d")}"'
View the entire Python script for this task on GitHub.
## Elixir
For Elixir, I offloaded most of the validation to guards on the `format_date/4` function, but I couldn’t think of a way to do the multipart `if` validation for the ordinal via a guard. Fortunately, I was able to make it a condition to return from `format_date/1` with an error. I also like that `Date.new/4` doesn’t throw an exception by default. If you want an exception, you use `Date.new!/4`.
def format_date(_, _, _, year) when year < 1900,
do: "Year must be between 1900-2100"
def format_date(_, _, _, year) when year > 2100,
do: "Year must be between 1900-2100"
def format_date(_, month, mnum, _) when is_nil(mnum),
do: "Unknown month '#{month}'"
def format_date(dnum, _, mnum, year) do
with {:ok, date} <- Date.new(year, mnum, dnum) do
"\"#{date |> Date.to_iso8601}\""
else
{:error, :invalid_date} -> "Invalid date"
end
end
def format_date(str) do
[day, month, year] = String.split(str)
m = Regex.named_captures(~r'(?<dnum>\d+)(?<dord>\D+)', day)
dnum = m["dnum"] |> String.to_integer # make sure it's an int
if not (
((dnum == 1 or dnum == 21 or dnum == 31) and
m["dord"] == "st")
or
((dnum == 2 or dnum == 22) and m["dord"] == "nd")
or
((dnum == 3 or dnum == 23) and m["dord"] == "rd")
or
m["dord"] == "th"
) do
"#{day} has the incorrect ordinal"
else
year = year |> String.to_integer # make sure it's an int
mnum = Map.get(%{
"Jan" => 1, "Feb" => 2, "Mar" => 3, "Apr" => 4,
"May" => 5, "Jun" => 6, "Jul" => 7, "Aug" => 8,
"Sep" => 9, "Oct" => 10, "Nov" => 11, "Dec" => 12
}, month)
format_date(dnum, month, mnum, year)
end
end
def format_date(_, _, _, year) when year < 1900,
do: "Year must be between 1900-2100"
def format_date(_, _, _, year) when year > 2100,
do: "Year must be between 1900-2100"
def format_date(_, month, mnum, _) when is_nil(mnum),
do: "Unknown month '#{month}'"
def format_date(dnum, _, mnum, year) do
with {:ok, date} <- Date.new(year, mnum, dnum) do
"\"#{date |> Date.to_iso8601}\""
else
{:error, :invalid_date} -> "Invalid date"
end
end
def format_date(str) do
[day, month, year] = String.split(str)
m = Regex.named_captures(~r'(?<dnum>\d+)(?<dord>\D+)', day)
dnum = m["dnum"] |> String.to_integer # make sure it's an int
if not (
((dnum == 1 or dnum == 21 or dnum == 31) and
m["dord"] == "st")
or
((dnum == 2 or dnum == 22) and m["dord"] == "nd")
or
((dnum == 3 or dnum == 23) and m["dord"] == "rd")
or
m["dord"] == "th"
) do
"#{day} has the incorrect ordinal"
else
year = year |> String.to_integer # make sure it's an int
mnum = Map.get(%{
"Jan" => 1, "Feb" => 2, "Mar" => 3, "Apr" => 4,
"May" => 5, "Jun" => 6, "Jul" => 7, "Aug" => 8,
"Sep" => 9, "Oct" => 10, "Nov" => 11, "Dec" => 12
}, month)
format_date(dnum, month, mnum, year)
end
end
View the entire Elixir script for this task on GitHub.
* * *
# Task 2: Format Phone Number
You are given a phone number as a string containing digits, space and dash only.
Write a script to format the given phone number using the below rules:
1. Removing all spaces and dashes
2. Grouping digits into blocks of length 3 from left to right
3. Handling the final digits (4 or fewer) specially:
- 2 digits: one block of length 2
- 3 digits: one block of length 3
- 4 digits: two blocks of length 2
4. Joining all blocks with dashes
**Example 1**
Input: $phone = "1-23-45-6"
Output: "123-456"
**Example 2**
Input: $phone = "1234"
Output: "12-34"
**Example 3**
Input: $phone = "12 345-6789"
Output: "123-456-789"
**Example 4**
Input: $phone = "123 4567"
Output: "123-45-67"
**Example 5**
Input: $phone = "123 456-78"
Output: "123-456-78"
## Approach
Really, this is the simpler of the two. The rules lay it all out: we strip all non-digits from the string, then we pull off three characters from the front of the string until the length of the string is 4 or less characters, then we group the remaining characters as directed.
## Elixir
Because I had an inspiration about how to do this recursively with multiple dispatch, I decided to do the Elixir solution first. One thing I knew was that I wanted to immediately break the string into a list of characters, because while you **can’t** test the length of a string in a function’s guard clause, you **can** test the length of a list. However, I wasn’t sure of how to pull elements off the left-hand side of the list. `List.first/2` would give me the first element, but it wouldn’t return the list with the first element removed. After a bit of searching, I found the functions I wanted… in the `Kernel` module!
* `Kernel.hd/1` returns the first element, or “head”, of a list
* `Kernel.tl/1` returns **all but** the first element of a list, or the “tail” of the list
Plus, because they’re `Kernel` modules, I wouldn’t need to qualify them with `Kernel.`, I could just use `hd()` and `tl()`.
I think this shows off the power of multiple dispatch pretty well: the `format_phone/1` function (lines 21-26) accepts the string, strips out all non-numeric digit characters, splits the string into a list of those characters, and then passes the list to `format_phone/2` with an empty `formatted` string.
We then have three multiple dispatch definitions of `format_phone/2`: one on lines 14-19 that handles all of the rule 2 processing (pulling the first three characters off the list, and then appending them to the formatted string along with a trailing dash, and then recursively calling `format_phone/2`), one on lines 8-12 that handles the list when it’s down to 4 elements (pulling the first two characters off the list, appending them to the formatted string, adding a dash to the formatted string, then joining and appending the remaining two characters to the formatted string and returning it), and one on lines 4-7 that handles the list when it’s less than 4 elements long (joining the remaining characters and appending them to the formatted string, which already has a trailing dash, and then returning that result).
def format_phone(list, formatted) when length(list) < 4 do
formatted <> Enum.join(list)
end
def format_phone(list, formatted) when length(list) == 4 do
{a, list} = {hd(list), tl(list)}
{b, list} = {hd(list), tl(list)}
formatted <> "#{a}#{b}-" <> Enum.join(list)
end
def format_phone(list, formatted) when length(list) > 4 do
{a, list} = {hd(list), tl(list)}
{b, list} = {hd(list), tl(list)}
{c, list} = {hd(list), tl(list)}
format_phone(list, formatted <> "#{a}#{b}#{c}-")
end
def format_phone(phone) do
phone
|> String.replace(~r/\D/, "")
|> String.graphemes
|> format_phone("")
end
def format_phone(list, formatted) when length(list) < 4 do
formatted <> Enum.join(list)
end
def format_phone(list, formatted) when length(list) == 4 do
{a, list} = {hd(list), tl(list)}
{b, list} = {hd(list), tl(list)}
formatted <> "#{a}#{b}-" <> Enum.join(list)
end
def format_phone(list, formatted) when length(list) > 4 do
{a, list} = {hd(list), tl(list)}
{b, list} = {hd(list), tl(list)}
{c, list} = {hd(list), tl(list)}
format_phone(list, formatted <> "#{a}#{b}#{c}-")
end
def format_phone(phone) do
phone
|> String.replace(~r/\D/, "")
|> String.graphemes
|> format_phone("")
end
View the entire Elixir script for this task on GitHub.
$ elixir/ch-2.exs
Example 1:
Input: $phone = "1-23-45-6"
Output: "123-456"
Example 2:
Input: $phone = "1234"
Output: "12-34"
Example 3:
Input: $phone = "12 345-6789"
Output: "123-456-789"
Example 4:
Input: $phone = "123 4567"
Output: "123-45-67"
Example 5:
Input: $phone = "123 456-78"
Output: "123-456-78"
$ elixir/ch-2.exs
Example 1:
Input: $phone = "1-23-45-6"
Output: "123-456"
Example 2:
Input: $phone = "1234"
Output: "12-34"
Example 3:
Input: $phone = "12 345-6789"
Output: "123-456-789"
Example 4:
Input: $phone = "123 4567"
Output: "123-45-67"
Example 5:
Input: $phone = "123 456-78"
Output: "123-456-78"
## Raku
And, as always happens when I do the Elixir solution first, it informs how I do the Raku version. Because Raku allows us to put `where` clauses testing string length into our function signatures, I didn’t need to pass the string around as a list of characters. And the `Str` class’ `.substr` routine let me pull the characters I wanted out of the string easily.
multi formatPhone($phone where $phone.chars < 4, $formatted) {
$formatted ~ $phone;
}
multi formatPhone($phone where $phone.chars == 4, $formatted) {
$formatted ~ $phone.substr(0..1) ~ "-" ~ $phone.substr(2..3);
}
multi formatPhone($phone, $formatted) {
formatPhone(
$phone.substr(3),
$formatted ~ $phone.substr(0..2) ~ "-"
);
}
multi formatPhone(Str $phone is copy) {
$phone ~~ s:global/\D+//;
formatPhone($phone, "");
}
multi formatPhone($phone where $phone.chars < 4, $formatted) {
$formatted ~ $phone;
}
multi formatPhone($phone where $phone.chars == 4, $formatted) {
$formatted ~ $phone.substr(0..1) ~ "-" ~ $phone.substr(2..3);
}
multi formatPhone($phone, $formatted) {
formatPhone(
$phone.substr(3),
$formatted ~ $phone.substr(0..2) ~ "-"
);
}
multi formatPhone(Str $phone is copy) {
$phone ~~ s:global/\D+//;
formatPhone($phone, "");
}
View the entire Raku script for this task on GitHub.
## Perl
Even though Perl doesn’t have multiple dispatch, I didn’t miss it that much. I just gave the recursive function a different name, and put all the clauses in an `if-elsif-else` block within that function.
sub formatPhone2($phone, $formatted) {
if (length($phone) < 4) {
$formatted . $phone;
}
elsif (length($phone) == 4) {
$formatted . substr($phone, 0,2) . "-" . substr($phone, 2,2);
}
else {
formatPhone2(
substr($phone, 3),
$formatted . substr($phone, 0, 3) . "-"
);
}
}
sub formatPhone($phone) {
$phone =~ s/\D+//g;
formatPhone2($phone, "");
}
sub formatPhone2($phone, $formatted) {
if (length($phone) < 4) {
$formatted . $phone;
}
elsif (length($phone) == 4) {
$formatted . substr($phone, 0,2) . "-" . substr($phone, 2,2);
}
else {
formatPhone2(
substr($phone, 3),
$formatted . substr($phone, 0, 3) . "-"
);
}
}
sub formatPhone($phone) {
$phone =~ s/\D+//g;
formatPhone2($phone, "");
}
View the entire Perl script for this task on GitHub.
## Python
The big thing I need to remember in Python after writing Elixir, Raku, and Perl solutions first is that I have to **explicitly** return values from functions.
import re
def format_phone2(phone, formatted):
if len(phone) < 4:
return formatted + phone
elif len(phone) == 4:
return formatted + phone[0:2] + "-" + phone[2:4]
else:
return format_phone2(
phone[3:],
formatted + phone[0:3] + "-"
)
def format_phone(phone):
phone = re.sub(r'\D', '', phone)
return format_phone2(phone, "")
import re
def format_phone2(phone, formatted):
if len(phone) < 4:
return formatted + phone
elif len(phone) == 4:
return formatted + phone[0:2] + "-" + phone[2:4]
else:
return format_phone2(
phone[3:],
formatted + phone[0:3] + "-"
)
def format_phone(phone):
phone = re.sub(r'\D', '', phone)
return format_phone2(phone, "")
View the entire Python script for this task on GitHub.
* * *
Here’s all my solutions in GItHub: https://github.com/packy/perlweeklychallenge-club/tree/master/challenge-347/packy-anderson
### _Related_
packy.dardan.com
November 12, 2025 at 3:02 AM
Perl Weekly Challenge: Oh, oh, formatted strings, give me some thing…
Perl Weekly Challenge 347's tasks are formatting dates and phone numbers, so I'm offering up ELO's Telephone Line as this week's musical theme. Doo-wop, doo-be-doo-doo-wop, doo-wah, doo-languages...
https://packy.dardan.com/b/dp
Perl Weekly Challenge 347's tasks are formatting dates and phone numbers, so I'm offering up ELO's Telephone Line as this week's musical theme. Doo-wop, doo-be-doo-doo-wop, doo-wah, doo-languages...
https://packy.dardan.com/b/dp
We have the skills and experience to showcase your work at its best. Just WRITE and leave the rest to us. ✍️ ♥️
📖 Visit us at thebookkhaleesi.com
#authorservices #authors #writingcommunity #thebookkhaleesi #bookcovers #Editing #formatting #publishing
📖 Visit us at thebookkhaleesi.com
#authorservices #authors #writingcommunity #thebookkhaleesi #bookcovers #Editing #formatting #publishing
November 12, 2025 at 2:46 AM
We have the skills and experience to showcase your work at its best. Just WRITE and leave the rest to us. ✍️ ♥️
📖 Visit us at thebookkhaleesi.com
#authorservices #authors #writingcommunity #thebookkhaleesi #bookcovers #Editing #formatting #publishing
📖 Visit us at thebookkhaleesi.com
#authorservices #authors #writingcommunity #thebookkhaleesi #bookcovers #Editing #formatting #publishing
We have the skills and experience to showcase your work at its best. Just WRITE and leave the rest to us. ✍️ ♥️
📖 Visit us at thebookkhaleesi.com
#authorservices #authors #writingcommunity #thebookkhaleesi #bookcovers #Editing #formatting #publishing
📖 Visit us at thebookkhaleesi.com
#authorservices #authors #writingcommunity #thebookkhaleesi #bookcovers #Editing #formatting #publishing
November 12, 2025 at 2:46 AM
We have the skills and experience to showcase your work at its best. Just WRITE and leave the rest to us. ✍️ ♥️
📖 Visit us at thebookkhaleesi.com
#authorservices #authors #writingcommunity #thebookkhaleesi #bookcovers #Editing #formatting #publishing
📖 Visit us at thebookkhaleesi.com
#authorservices #authors #writingcommunity #thebookkhaleesi #bookcovers #Editing #formatting #publishing
Kids using AI to write papers are missing out learning the critical formatting buggery I used to hit my page counts.
November 12, 2025 at 2:33 AM
Kids using AI to write papers are missing out learning the critical formatting buggery I used to hit my page counts.
Also (X) is better than X) formatting!
November 12, 2025 at 2:18 AM
Also (X) is better than X) formatting!
motivational poster for getting worse
November 12, 2025 at 2:10 AM
motivational poster for getting worse
And conversely, after starting with classier sf, my mind was blown by “The Stars My Destination,” which can be summed up as “This guy is a hall of fame hater; he is such a hater that his hate will break spacetime and even book formatting.”
November 12, 2025 at 1:49 AM
And conversely, after starting with classier sf, my mind was blown by “The Stars My Destination,” which can be summed up as “This guy is a hall of fame hater; he is such a hater that his hate will break spacetime and even book formatting.”
The deadline was ~1 month after my son was born so my memory is sort of hazy.
It does make me think about how many exception requests I get from my students though, and how in the real world you can literally have over a years worth of work disregarded because of a formatting error.
It does make me think about how many exception requests I get from my students though, and how in the real world you can literally have over a years worth of work disregarded because of a formatting error.
November 12, 2025 at 1:45 AM
The deadline was ~1 month after my son was born so my memory is sort of hazy.
It does make me think about how many exception requests I get from my students though, and how in the real world you can literally have over a years worth of work disregarded because of a formatting error.
It does make me think about how many exception requests I get from my students though, and how in the real world you can literally have over a years worth of work disregarded because of a formatting error.
*sudden realization*
Why am I concerned about my chapters? "Doctor Zhivago" has the EXACT same formatting style of massive chapters with numbered scenes; it's just intimidating for ME.
Why am I concerned about my chapters? "Doctor Zhivago" has the EXACT same formatting style of massive chapters with numbered scenes; it's just intimidating for ME.
November 12, 2025 at 1:41 AM
*sudden realization*
Why am I concerned about my chapters? "Doctor Zhivago" has the EXACT same formatting style of massive chapters with numbered scenes; it's just intimidating for ME.
Why am I concerned about my chapters? "Doctor Zhivago" has the EXACT same formatting style of massive chapters with numbered scenes; it's just intimidating for ME.