If you've discovered something amazing about Perl that you just need to share with everyone,
this is the right place.
This section is also used for non-question discussions about Perl, and for any discussions that are not specifically programming related. For example, if you want to share or discuss opinions on hacker culture, the job market, or Perl 6 development, this is the place. (Note, however, that discussions about the PerlMonks web site belong in PerlMonks Discussion.)
Meditations is sometimes used as a sounding-board — a place to post initial drafts of perl tutorials, code modules, book reviews, articles, quizzes, etc. — so that the author can benefit from the collective insight of the monks before publishing the finished item to its proper place (be it Tutorials, Cool Uses for Perl, Reviews, or whatever). If you do this, it is generally considered appropriate to prefix your node title with "RFC:" (for "request for comments").
As indicated here, Perl Monk BBQ arrived with us on Dec 24 1999, making him
the third ever non-insider Perl monk and, hailing from Brazil, the second ever international monk!
After making the first ever post in the Perl Monks Obfu section our intrepid pioneer hero
stayed on for a further ten years!
Accordingly, I would love to see the legendary BBQ appear today
whenever I browse Saints in our Book.
Though I could make a special plea to the PM gods to award BBQ the 95 XP required to reach sainthood,
I'd find it much more satisfying if we could all honour BBQ by upvoting enough of his praiseworthy historic nodes
to allow him to finally reach his richly deserved sainthood.
Last week, I hosted The Perl and Raku Conference (TPRC) 2023 in Toronto, Canada. We had under a hundred attendees, and we had a three day schedule of sessions with three tracks. There was also a hackathon Monday and Friday, and Dave Rolsky put on a one day course in Go on the Friday.
I've been going to these conferences on and off for about twenty years (2000, 2001, 2002, 2012, 2019 and 2022), so I had a pretty good idea how they work. Putting on my own conference was eye-opening, but what really moved me was the impressive number of volunteers that helped out. There were just people who didn't know much about Perl who came out, but I also had speakers jump in to help with A/V setup and all kinds of other details like making up badges. It was fabulous.
Our keynote speaker was Curtis Poe (Ovid) who talked about Cor, the new object layer that's an experimental feature in Perl 5.38 (just released). We also had Paul Evans (leonerd, the current pumpking) who gave a talk about what was new in this new version of Perl. The talks, as well as a pile of Lightning Talks are in the process of being edited together and uploaded to Youtube. And next year's conference is already planned for Las Vegas, Nevada in June, 2024.
Yeah, Perl's an old language. But it's still alive and well. :)
While I doubt Bod, hailing from (working-class) Coventry UK, would be permitted to enter
the hallowed Long Room at Lords
to hurl abuse at the Australian cricket team during the Ashes test match last weekend,
I'm sure he won't be stumped by this meditation's title ...
unlike monks from non-cricket-playing nations, doubtless unfamiliar with Bazball :).
Bodball, you may recall I once scolded you for asking "what should I test?" long after you'd released your module.
I similarly urge you to get into the habit of thinking long and hard about your module's error handling well before you release it,
and for the same reasons.
Like TDD, it's crucial to perform this error-handling analysis early
because doing so will likely change your module's interface.
Further to the excellent general advice you've already recieved from afoken,
I'm interested to learn more about the errors you commonly encounter in practice
when using your Business::Stripe::Webhook module.
I also urge you to add an expanded "Error Handling" section to your module's documentation.
General Error Handling Advice
Don't fail silently.
Failure is inevitable; failing to report failures is inexcusable. Failing silently causes the following problems:
Users wonder whether something has gone wrong. ("Why did my order not go through?")
Customer support wonders what caused a problem. ("The log file gave no indication of a problem")
Embrace your software's fallibility. Assume that humans will make mistakes using your software.
Try to minimize ways for people to misuse your software, but assume that you can't completely eliminate misuse.
Therefore, plan error messages as you design software.
return path of a function is made uglier by the need to return an error indicator
the function that found the error was a callback
an error requires an "undo" action (unlike RAII say)
This is not a black and white issue. Experience and good taste are required.
Business::Stripe::Webhook Error Handling
Though unfamiliar with your Business::Stripe::Webhook domain,
I briefly browsed your module's documentation.
Good to see you've already written a short "Errors and Warnings" section in its documentation;
I suggest you improve and expand this section for the next release.
AFAICT, your basic error handling strategy is for your methods to set the error
property, for example:
with the module user expected to check this error property after calling each method.
Is that right?
I think a clear statement of your overall error-handling strategy, combined
with a couple of real-world examples of handling common errors you've experienced when using your module,
would be invaluable to your users ... and may cause you to tweak your module's error-handling code
and interface ... which is why this step is ideally performed well before release. :)
My goal was keeping memory consumption low no matter if running a single thread or 20+ threads. Ideally, running more threads should run faster. It turns out that this is possible. Ditto, zero merge overhead as the keys are unique. Just move the elements from all the sub-maps over to a vector for sorting and output.
In a nut-shell, the following is the strategy used for the hash-map solutions in latest June 2023 refresh.
1. create many sub-maps and mutexes
2. parallel single-file via chunking versus parallel list of files
3. create a hash-value for the key and store the value with the key
4. determine the sub-map to use by hash-value MOD number-of-maps
5. there are total 963 sub-maps to minimize locking contention
6. randomness kicks in, allowing many threads to run
Thank you, Gregory Popovitch. He identified the last one-off error in my C++ chunking logic plus shared a couple suggestions. See issue 198. Thank you, eyepopslikeamosquito for introducing me to C++. Thank you, anonymous monk. There, our anon-friend mentioned the word parallel. So, we tried running parallel in C++. Eventually, chunking too. :)
This is a quick writeup about a half-forgotten urban legend I heard, just because it wasn't trivial for me to find information about it on the internet.
YAPC::Europe is a series of yearly perl conferences. An auction was held on these conferences to decide the color of the official shirt of the next conference. This was already a thing in 2001, though it's unclear to me if only the organizers wear those shirts or they're sold to any attendee.
Could you please take a look at the documentation for my new module and let me know if it makes sense? I always find that I am too close to the module and know what everything is supposed to do. In short, I have the Curse of Knowledge!
Why is it you only find typos after publishing?
The second raw_embedding method should read test_embedding in both the heading and the sample code. I've corrected this error now.
Thank you greatly for helping me get this right...
Edit:
Changed title from "RFC - Documentation Review" to "Please review documentation of my AI::Embedding module" as considered by erzuuli
Having written some code that uses Embeddings to compare pieces of text, I feel this would be useful to others. The Embeddings are generated from the OpenAI API at present.
I plan to package this up into a module for CPAN and would like some advice on the namespace for this module...
There is already OpenAI::API::Request::Embedding, which is just a thin wrapper to the API. I don't want to use the OpenAI namespace because my module will probably allow other Embedding providers to be used. For example, Hugging Face provides a cheaper but less precise Embeddings API. This may be better suited to some users.
As well as providing the connection to the API, my module will also have a method to allow two pieces of text to be compared. More functionality than just a thin wrapper.
As my module will connect to several different API providers, I am thinking AI::Embedding might be the right name for it but I am not convinced and your opinions and advice would be greatly appreciated.
You'll need to install the Roman module from CPAN
(or simply copy Roman.pm locally)
to generate the test data by running:
# gen-roman.pl
use strict;
use warnings;
use Roman;
for my $n (1..1000) {
for my $i (1..3999) {
my $r = int(rand(2)) ? uc(roman($i)) : lc(roman($i));
print "$r\n";
}
}
# rtoa-pgatram.pl
# Example run: perl rtoa-pgatram.pl t1.txt >pgatram.tmp
#
# Convert a "modern" Roman Numeral to its arabic (decimal) equivalent.
# The alpabetic input string may be assumed to always contain a valid
+Roman Numeral in the range 1-3999.
# Roman numerals may be upper or lower case.
# Error handling is not required.
# For example:
# input "XLII" should produce the arabic (decimal) value 42
# input "mi" should produce the arabic (decimal) value 1001
use 5.010; # Needed for state
use strict;
use warnings;
use List::Util qw(reduce);
sub read_input_files {
my $files = shift; # in: reference to a list of files containin
+g Roman Numerals (one per line)
my @list_ret; # out: reference to a list of the Roman Numer
+als in the files
for my $fname ( @{$files} ) {
open( my $fh, '<', $fname ) or die "error: open '$fname': $!";
while (<$fh>) {
chomp;
push @list_ret, uc($_);
}
close($fh) or die "error: close '$fname': $!";
}
return \@list_ret;
}
# Function roman_to_arabic
# Input: reference to a list of valid Roman Numerals in the range 1..
+3999
# Output: reference to a list of their arabic (decimal) values
sub roman_to_arabic {
my $list_in = shift; # in: reference to a list of valid Roman Nu
+merals
my @list_ret; # out: a list of their integer values
state %rtoa = ( M=>1000, D=>500, C=>100, L=>50, X=>10, V=>5, I=>1 )
+;
for (@{$list_in}) {
push @list_ret, reduce { $a+$b-$a%$b*2 } map { $rtoa{$_} } split
+//, uc($_);
}
return \@list_ret;
}
@ARGV or die "usage: $0 file...\n";
my @rtoa_files = @ARGV;
warn "rtoa pgatram start\n";
my $tstart1 = time;
my $aref1 = read_input_files( \@rtoa_files );
my $tend1 = time;
my $taken1 = $tend1 - $tstart1;
warn "read_input_files : $taken1 secs\n";
my $tstart2 = time;
my $aref2 = roman_to_arabic($aref1);
my $tend2 = time;
my $taken2 = $tend2 - $tstart2;
warn "roman_to_arabic : $taken2 secs\n";
my $tstart3 = time;
for my $n ( @{$aref2} ) { print "$n\n" }
my $tend3 = time;
my $taken3 = $tend3 - $tstart3;
my $taken = $taken1 + $taken2 + $taken3;
warn "output : $taken3 secs\n";
warn "total : $taken secs\n";
I was relieved that this ran a little faster than rtoa-roman.pl, which is just a copy of rtoa-pgatram.pl above
that uses Roman's arabic function instead of rtoa-pgatram.pl's pgatram algorithm; that is with:
Please feel free to reply with alternative Perl roman_to_arabic subroutines,
especially if they are faster.
Roman to Arabic subroutines in other languages are also welcome.
I've been a registered Monk for 14+ years, was a lurker for eight years before that, I have 60 CPAN distributions published, over 100 Open Source projects published, am co-author on a book about programming the Raspberry Pi with Perl, and for the first time, I'm booked to attend my first Perl conference!
I'm very excited. A client of mine asked if I'd be attending this year's Toronto Perl conference in a call today, and I thought... yeah, I think I will.
Tickets booked, hotel booked, flights booked, I'm on my way.
Best part is, is that Toronto is my hometown, so it'll back as a time that I can visit a bunch of people while I'm there.
I hope to see some of my fellow Monks there!!!
Update: Email me via my addresses found on my Github or CPAN page if you're going to attend and want to try to hook up.
Today, I failed to convince my team at work to use Perl instead of Python for a new scripting project on Linux...They went with Python2 instead, imagine that.
Oh yes and my work is pushing most of us Linux deployers to start using Windows now for our client machines, imagine that.
What is this world coming to? Maybe I should just go flipping burgers for a living.
Wouldn't it be nice to create automatic tests for all cases to create a nice lookup-table/cheat-sheet?
This table would have a worst case of 4 dimensions ( context, result, capture, /g ), which means many possible projections into a 2D table, here an attempt how it might look like, if the result is coded into the cell's value
(NB: this is untested guess work and turned out to be wrong I leave it to you to spot the errors)
So in an outbreak of ADHD, hubris, and too much time b/c of Easter holidays I started to write - well hack - test code:
These are my results so far, only as data structures.
Imperfect because I wanna leave the house still during daylight and risks are high that the code will remain unfinished on my disk without being shared. And it even seems to be wrong.
The task to condense it into a meaningful table which avoids unnecessary repetitions is even farther away...
Yesterday, one of the SSDs in my main computer suddenly died, from one second to the other. It simply disappeared from the system, leaving two very confused virtual machines behind that lost access to their virtual disks stored on that SSD. This way, I lost about one hour of work. That would have been annoying, but could have been fixed easily. Shut down, rip out the SSD, replace it with a fresh SSD or a harddisk, and restore the backup.
But: That SSD was added at the beginning of the Covid-19 pandemic, as a quick hack to have room for the VMs needed for working from home. It was never intended to work for more than a few weeks, and so I simply forgot to include that disk in the configuration of the backup software.
I tried about an hour to read the dead SSD using two other computers, but it is dead. It identifies correctly, but reports junk when reading SMART data, and reads not a single bit of user data. I reassembled my computer, added a temporary HDD, ordered a replacement SSD, and started a 17 hours copy job to get the required VMs as huge ZIP files from work to home. It will take another hour or two to unpack and reconfigure the VMs for the new environment. And one or two hours to resync some work data from a cloud service.
This is totally my fault, having no backup for that disk was stupid, period.
So, take this as a warning if you are - like me - used to get an audible warning from a failing disk. SSDs die silently and suddenly. You won't get that nasty metal workshop sounds you know from failing hard disks.
Check your backups, and check your backup configuration.
[L]et’s talk about SSD SMART stats. [...] we’ve been wrestling with SSD SMART stats for several months now, and one thing we have found is there is not much consistency on the attributes, or even the naming, SSD manufacturers use to record their various SMART data. For example, terms like wear leveling, endurance, lifetime used, life used, LBAs written, LBAs read, and so on are used inconsistently between manufacturers, often using different SMART attributes, and sometimes they are not recorded at all.
Alexander
--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Snippets of code should be wrapped in
<code> tags not<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).