52: In the next episode we'll fix the NPM ecosystem
We should start a podcast.
Let's get going. Do you want to start with the Python metadata stuff?
Yeah, sure. So I saw a blog post this week. In fact, it was passed to me by Peter Steinberger,
who passed over this blog post from Armin Ronacher, and he thought I might be interested in it.
And it's called Constraints are Good, Python's Metadata Dilemma. And it's basically a post
about a situation that they have in the Python package and dependency ecosystem at the moment,
where you can have this thing in Python. I haven't really used Python. I've done a tiny
little bit in Python, but nothing worth mentioning. And I wouldn't say that I know
the language or certainly don't know the dependency ecosystem very well in Python.
I believe, Sven, you have done more Python than me, right?
I've used it a fair bit, yeah.
Yeah, so maybe you can guide me through this. So basically, the dynamic metadata is
in the kind of dependency manifest for a Python package. You can execute effectively arbitrary
code. And that is now causing a few problems, a very slow dependency resolution, and
difficulty with cache invalidation, fragmented metadata storage. I'm reading some of the bullet
points here from the list of issues in the blog post. And so first of all, correct me on anything
that I've said that's wrong there.
I'd be struggling because setting up dependencies in Python has always been weird. Like, I remember,
now this has been a while, I stopped using Python as a development language, pretty much when
I started on server-side Swift, which was around, I think the last project I used Python ended
like five years ago now. So it's been a while. But I remember, it's always been a pain point
setting up a Python project, because there's pip to install stuff. Then there was another thing
that was kind of, I don't remember, there was also running Python setup.py, the setup file
was a means to install stuff.
Right, I remember doing that a couple of times, yeah.
And I don't remember there was another one that was controversial. Or it might have just been
a dependency that's, I think that might have been a dependency that was setting up. My memory's
hazy there. But the one thing I always remember, I was always happy when I had stuff set up,
and I was successful. It was succeeding to import stuff. That was always the benchmark.
Can I actually import matplotlib and not have a library failing to load? Because the problem
with Python is, if it's a pure Python package, that was never a problem, right? That was always
smooth. The problem was always the dependencies that compile C code.
Like a wrapper or a C library or something.
Exactly, a C library, which is sort of also a thing that we are used to in Swift land, right?
Yep, there's lots of that in Swift.
To the credit of Swift, that's way more reliable than the Python stuff. Just because Swift can
actually compile the C stuff directly. And in Python, you need to have the C compiler and what
not installed at the right versions and all that stuff. It always ended up us writing a Docker
thing to set up stuff. It was always a bit of a pain. And reading that blog post sort of
gave me the idea, oh, this is even worse in areas that I wasn't even aware of. So I think this is
where I hand it back to you to summarize.
Well, and the blog post does mention, it says the challenge with dynamic metadata in Python is vast.
But unless you're writing a resolver or a packaging tool, you're not going to experience
the pain as much. And so this is, we're not talking about the entire environment of writing
Python here. But what it did do was this, and we'll link to this blog post in the show notes.
But what it did do is it reminded me that we have a slightly similar approach in Swift package
manifest, which are Swift code and not metadata. In fact, the start of the blog post, you always
know it's going to be an interesting blog post when the start of the blog post admires the
JavaScript package ecosystem.
But there is something about the JavaScript package ecosystem, which is good. And in fact,
there's a few things and he lists them out here. And that is that the package.json file, which is
the kind of container manifest for a JavaScript dependency, or a package, is a JSON file. So it
is not executable code, it is just purely metadata. And there's a couple of other things here. So
there's a one to one relationship between a package and its metadata in JavaScript, every
single package has one package.json file, which is the entire source of truth in the metadata.
That's good.
Which is also quite a baffling thing to have to call out, right? You immediately ask, well,
hold on, is that are there packages, because this is where that isn't the case where it's a one to
n or n to one relationship.
Swift does also have that one. We're one to one with JavaScript at the moment. Yeah.
Well, kind of, there's a caveat there, but we will get to that, I suppose.
Are you talking about the Swift version specific manifests?
Yes, exactly. Yeah.
Yeah, yes. Yes. I mean, we're already we're already I mean, Swift still feels it's not
a new language anymore, but it still feels kind of new as a language. And already we have artifacts
of things like that. Anyway, so the point that I was making here was, there are certainly aspects
of a Swift package manifest that came to mind as I was reading this blog post about the Python
dynamic metadata. And when we've hit problems where the compiled nature of a package manifest
causes problems for us, when we run the dump package command, which is supposed to turn a
package meta manifest into a JSON file, which is what we can then pass. And that's how we
extract all the metadata for about a package that we can get. And I think one of the key things that
that jumped out to me, which is mentioned in this blog post as well, is that based on, for example,
platform or environment, you can have your package metadata is not consistent. It is it can change,
depending on where you're compiling or where you're running that dump package command. And I
know, I know, I know there's a whole can of worms around opening a discussion on whether making
package manifests code was a good idea or not. And, and I also know that changing it at this
point would also be really difficult. And again, this is mentioned in the blog post, like once you've
once you have Pandora's box open like this, people build all sorts of stuff into that relying on that
feature, and it becomes incredibly difficult to roll it back. I feel with Swift, is it is it too
late to roll it back yet? I think probably not. I mean, we're still I just read a blog post,
actually, just before we recorded this podcast, which is the, the plan on when to make the Cocoa
Pods repository trunk repository read only, which is their plan to sunset Cocoa Pods, basically.
And I think they've given it a two year timeline from now, before they'll make it read only and
finally kind of completely shut it down. But Swift VM has over the last few years has become
hugely popular. But it was around for many years before it became hugely popular. It was around
before it was it was really useful in iOS and Mac OS projects. As I wonder whether we haven't quite
got past that point, where everything of the manifest format might be at least an option.
Yeah, I'd love to see that at least discussed. And then, you know, kind of decided,
looking at pros and cons. I mean, I, I, I'm not sure I entirely see the pros there.
Like, just just to give some context, just today. Incidentally, I fixed a bug that resulted from
having to have a compiler installed to to render the package manifest as JSON,
right, we our builder needs to run finds out some stuff about a package, in order to know which
a build command to run. And on Linux, actually, we run that in a Docker container that didn't
have the Swift compiler installed. And this was new, it didn't need we didn't need this before,
but now we did. And I, I was completely blind to the fact I had forgotten that our Docker image
doesn't have the Swift compiler. So I, I called right Swift, I saw that yeah, describe package,
and it failed. And then because of the way it was done, it sort of failed silently. And,
or at least it printed something that wasn't immediately obvious why that happened. And I
think that's kind of, it's kind of a heavy requirement that you need a compiler to
understand about your package. And then also, it's, it's important, you know, what platform
do you run it on, as you said, and what compiler version you're using to do that.
That sort of feels like, is that is that that's a bit, that's a bit weird. And then
we probably see more manifests than, you know, the, the normal because of what we do,
like we see lots of packages and people ask, well, why isn't this working? And
there's some wild stuff going on in package manifests, because it's effectively a little
Swift script, right, a Swift program, and it's programmed in it. And you have to effectively,
sometimes I look at these things, and I have to pass that program, because you know, what else
can I do? Obviously, you can run Swift package describe, and then get the output. But then that
doesn't tell you why stuff isn't, isn't there as you expect. And then you sort of have to sift
through and people do stuff in there. They import foundation, look at environment variables,
imply logic, and you think, Oh, God, is this? I mean, it opens up possibilities, but
I feel like some, you know, as the post says, you know, constraints are good, right? If
would, how, what, what would we lose if that was was just a JSON file?
Well, that's it. And every time I see somebody doing something like that in a package manifest,
I think, I kind of wish you weren't doing that. Like, wouldn't it be better if this was just a
standard file? My go to example, and I hate to call out a specific, a specific example here.
But they're a big company. So I feel I feel less guilty about it. My go to example for this is the
AWS SDK Swift package from AWS, which is a 627 line program in a package manifest. Now,
to be fair to them, they have they have 300, no 422 lines of targets, which is a lot of targets.
But, but still, there's, there's, there's code after that, which is doing all sorts of stuff.
It's looking at paths on the file system, it's it's looking at processes and getting environment
variables. And it's doing it's doing more than you would probably like to think it was doing if it
was just a package manifest with some metadata in it. And that's why I'd be really curious to
have a proper discussion and see, well, what use cases aren't possible with a, you know, static
JSON file or whatever it is, what we lose? Or is there even, I mean, the dynamism could be just
done upstream, right? That the output is a is a JSON file, right? If Amazon could, in that case,
have a Swift script that assembles stuff and then, you know, outputs a JSON file instead,
rather than, you know, keep that logic, you know, there on the fly sort of in the manifest.
I can imagine that there's stuff that is really hard to do, then, you know, like super platform
specific, how would that look? Like, would you have sort of logical structures within a JSON
file that says, you know, like, this is the dependency tree, if it's on macOS and Linux,
you know, how would that work? I mean, I can see how, yeah, that can get complex. But
that's a theme, the complexity is there. And it's just a matter of how do you package it up?
Because, end of the day, it has to be a has to be rendered out at some point is that how, how,
how much do you obfuscate it up front sort of is, I think, my right, my view of it. And
there is benefit and having these files more machine readable off the bat without having to
transform them, right? Because we like, always have to make sure they have a Swift compiler
and run Swift package describe or Swift package dump package in order to get the JSON out of it.
And that's the thing, you know, the JSON that we get out is the thing that we're interested in.
That's what we're using. And I sometimes wonder if that's not the, if that wouldn't be the better
intermediate format to keep around.
- Well, so just kind of make that not a generated artifact, but a stored artifact.
- Yeah, exactly. I mean, and then, you know, discuss, should there be something that can
generate it if you really have a very dynamic use case where you sort of need to, you know,
you sort of need to generate them, but then also bake them into a package, you know, so you don't
have, you can still be dynamic and then also write them out so people can actually get metadata info
without having to run the process every time, which is something we need to do, right? We have
a nightly that looks at packages and what we do is we fetch all the package manifests in a package.
And by all, I mean, all the versioned ones as well. So we have to make multiple HTTP requests
to get all the package.swift files out of a package. And fortunately, it's enough to copy
these in an empty directory and then run Swift package describe. That actually works. It doesn't
look at any other thing, other things in your package. It doesn't verify that you have a source
directory and whatnot. So that's enough to actually dump the package info then. But what we do is then
we render JSON out of it. So that process would be much easier if all we had to do is just fetch
a JSON file to begin with or whatever format is the one that's picked. It's just a lot of
work that needs to happen to get that data out. Yeah. Yeah. Just to flip onto the other side of
the argument and play devil's advocate, even though I am on this side of the argument,
there is one advantage to this that we benefit from, which is if it was a pure metadata file,
it would be more likely that we would let badly formed packages into the system. Whereas the fact
that we have to run package, the dump package before we accept a package into the index,
we get that we do get that level of verification that at least the manifest compiles.
Yeah, but I mean, there's Jason, there's Jason.
You could validate that and make sure that all the keys.
I'm back on this side of the fence. I attempted an escape, but it failed.
Resistance is futile.
Exactly. Exactly. Well, next week, we'll fix the NPM ecosystem and set that right.
Great.
There was another interesting post that I see
come out last week. Thanksgiving post by Holly Baller. And it's called prospective vision,
improving the approachability of data race safety. I'm sure you've seen that, right?
I did. And in fact, before you before you go into it, I want to read. I want to read Holly's
Macedon post where she where she linked to this, because it really made me laugh.
My favorite Thanksgiving tradition is a good language design debate ahead of the holiday.
Nice.
This time on improving the approachability of data race safety.
Well, Holly, I'm so glad that that is that's what was on your mind around Thanksgiving.
I hope I hope you managed to at least have some time not thinking about data race safety over the
holiday.
Well, isn't the US thing that Thanksgiving you go home to argue with your family? And that's sort
of that's probably what she's kind of doing with the other family.
I guess.
Anyway, let me I interrupted you. Sorry. I did see it. Yes.
Yeah, it's I really like this. I loved seeing this. It sets out to tackle some of the problems
that have come up when people start using Swift concurrency. And I think it bears repeating that
we are in the early stage of that adoption. And there's been quite a bit of noise because people
struggle with it, right? There's stuff that doesn't go as they as they planned.
Some of it is is compiler related. There are some issues that are
just growing pain in in Swift six language mode. So there's some some false positives and stuff.
And, and largely it sets out a vision on how to better deal with
with this with this adoption. Let me just see. Yes.
If she has a yeah, so she says she opens up and I should say, I found this post super readable.
People often think of Swift language development. Super in the weeds and you you can't follow and
there's there's that right often there are parts of proposals that are really technical and and
you need to know a lot upfront to actually even be able to follow but
you need to at least be be on the same page as a compiler engineer. Yeah.
I don't think this falls in that category. There's certainly stuff that you sort of
need to know a little bit about at least I think it's a bit hard to judge I I'm not a
Swift concurrency expert by by a long shot. But I also don't want to I mean, I've used it a bit. So
I'm probably more exposed to it than someone who's, who's just starting out.
Writing Swift or even someone who's only just starting to convert a project over.
But I think I think I'm not too sort of in the weeds already to be blind to
to, you know, that that threshold. I think it's quite approachable. And yeah, I think it's,
it paints the picture of what's what the problem is and what they're trying to achieve here.
So she opens up saying Swift's built in support for concurrency has three goals. And that's to
extend the memory safety guarantees to low level data races, maintain progressive disclosure for
non concurrent code, and make basic use of concurrency simple and easy, and make advanced
uses of concurrency to improve performance natural to accomplish and reason about.
And then she goes into, you know, sort of what are the remaining pain points where
what this is about is mitigating false positive data rate safety errors in
in sequential code and what the thing boils down to, I think, can be summarized in
the default is is sort of to assume that stuff is going to be running concurrently. And then
the compiler analyzes everything you do with that in mind. So anytime you touch, you know,
like global variables, for instance, the compiler will immediately shout, Oh, hold on, hold on,
what are you doing here? Remember, if you do this, there might be other concurrent access,
and that's not safe what you're doing. And what this is proposing is to flip this around
on a module by module basis. So to open up a mode where the default is to assume
main actor isolated code. And that means effectively running a single threaded program
on the main thread. And then if you mess with the global variable, that's safe by default,
because there's only ever one thread that can deal with that, right? There's no there's no
concurrent access because there's no concurrency. And that the vision is that should deal with a
lot of the all of the false positives right now, that can happen. And the false positives are
really shortcomings where the compiler can't see everything that's happening. And then,
because it has to be safe by default, it says, Look, this, this could be problematic,
I can't prove otherwise. So I have to warn about it, or, you know, in Swift six mode,
raise an error about it. And it's for you to be really explicit about what you're trying to do.
And by flipping this around, sort of the, the premise goes away, right? The, the initial
assumption where there might be a concurrent access isn't actually a problem anymore, because
there isn't concurrent access. So it that eliminates the need to raise an error by default,
and then you can poke holes into that by saying, Alright, this is actually non isolated, or has
different isolation, and then you can open up to concurrency, and then you get the richer warnings.
But the you can put this in a mode. And this is a mode that's really interesting, for example,
for scripts, or like in general is proposed to use in executable targets where, where you're going to
be starting with on the main thread, you know, like, if you write a script, you're probably going
to be on the main thread the whole time, right? And then why even deal with all this? And that's
the proposal is sort of to flip this around, I can, I hope I didn't mess this up describing what's
what this is about. Again, read it, because I think it's really readable. The discussion around
it is that's more in depth, because people raise, you know, concerns, how would this affect this and
that. And there are certainly aspects that are more complicated when it comes to classes and
inheritance and protocols, and then it gets a bit in the weed. But I think the basic premise
is quite graspable. It's quite obvious what this is proposing. And I think it's really well laid
out. And hopefully that will be accepted, implemented, and then could could be one of
those things. Remember, when we discussed this last time, we said, this is early days, just don't
rush into adopting Swift 6 by next year, things might be very different and might be much easier.
And that actually might be one of those things where you have a much easier time adopting this
in Swift 6.2.3, whenever this comes out, or is implemented. This might be one of those things
where you won't have to sprinkle main actor all through your code base, because main actor is the
thing that's going to be assumed, you know, wholesale, and you don't need to annotate stuff,
because it's sort of baked in into the module by module assumptions. There's one other thing I
wanted to highlight. And that's from the comments in this thread. Because that's also something
I at least said before, and I was really glad to see this echoed. And this is Tim Condon's reply
to a common complaint that data race safety annotations are a chore. And this is what we
talked about. I'm not sure if it was last episode or the one before. Tim says, to provide an
alternative point of view of this, I've lost count of the number of issues and data race issues
that have been caught and fixed by adopting Sendable across Vapors code bases. Lots of GitHub
issues that were impossible to reproduce, subtle data race issues, and downright stupid coding from
myself. Once we adopted Sendable, and yes, it wasn't an easy process, especially doing it as
an early adopter, all of those issues went away. We've not had a single issue reporting a crash as
a result of data race issues. And I was really glad to see that because I hadn't heard many people
say that thing that I've said before about our concurrency crashes that we've seen and that
disappeared once we switched to Swift 6. I think it really bears looking at these examples and
highlighting those so it's clear what you're getting. That it's not just a chore that you
have to deal with errors, there's something that it buys you. But, and this is also important,
we touched on this as well, to some degree, iOS doesn't have this at the same level, right? It
hasn't doesn't have the same level of impact on iOS. And I vividly remember when I was managing
an iOS team, when we were triaging iOS crashes, one of the things I looked at specifically was the
number of crashes per device. So the most important thing to fix was, we didn't want to have crash
loops on a device. If someone has a crash every once in a while, that was all right. If someone
crashed, obviously looking at the logs, the crash reports repeatedly, that was a problem. Now,
server code is different because you essentially run all the devices, right? You aggregate all
the crashes across the whole install base at once. So you have much more incentive to fix that.
But, and Tim says that Swift is just more than an iOS programming language at this point, right?
Yes. And you're right that it is really nice to see Tim's comment there. I hadn't seen that until,
I just looked at it while you were talking about it. And it is great to see a story like that. But
you're absolutely right that this is a language that has many different uses now. And still the
main use is from iOS and MacOS applications. So I'm so happy to see this document from Holly.
First of all, and we knew that they were still thinking about this, but this is
proof that they're still thinking about it. And it's nice to see, like, if you just look through
some of the headings in this document, some of the headings are really, they really spoke to me
actually, easing incremental migration to data race safety. I mean, the fact that that is a title
in this document is, it lifts my heart. It's great that that's the kind of thing that they're
talking about here. And obviously there is that the idea that you could switch an application to be
single threaded because some applications don't need concurrency. It's fairly rare these days,
even an iOS application, a simple iOS application will probably make some kind of network call.
And as soon as you do that, you need to consider concurrency in there. But there are certainly apps
that don't need it. And especially as people are learning the language. And I think that's one
thing. I wrote a few weeks ago about optimism in iOS Dev Weekly. And I use the example of how easy
it is to get up and running with Swift on a new Mac, a brand new Mac, a friend of mine bought a
new Mac. And I wanted him to run some benchmarks on package index, but compiling it with the M4
chip to see how it compared to my very expensive M1 Macs that I bought a few years ago. And I was
struck by how incredibly easy it was for him as somebody who is not a developer to get that,
get Swift installed and have what is quite a complex project compile. It was trivial. And
in response to that, my optimism and kind of choosing to see the good things about the
language, I got some real colorful feedback saying that even people who are trying to learn Swift are
hitting these concurrency issues immediately. And so I'm so glad that they're really putting
this into something that will hopefully be implemented. Yeah, it sounds like it's really
going to take the edge off some of this, the early stuff and Holly highlights that in an
explicit example. I think that it's unfortunate that in some areas you immediately get hit with
these warnings when you're doing something like obvious, you know, in a script, you know,
like a global variable, stuff like that. And if this is the way of dealing with that, that's
fantastic because it'll open up these use cases to be much smoother. I mean, we run a script to
validate our packages and that's sort of one thing where we haven't transitioned over yet. And that's
going to be a bit painful. And that might actually be a reason to wait and wait until we have that
mode and then just do it do it there. Well, almost certainly that doesn't need concurrency.
Well, it does network requests, and we might pass some stuff. So it's, it's kind of
but in that script, it could it could absolutely wait for that.
In the single package validation. Yeah, for sure. I'm thinking about the validator that crawls,
you know, does all the packages. Yeah, that's that's another one. Yeah. Yeah. I mean,
all of this. It's just great. But we've talked far too long about, about this stuff. So we should get
to some packages before people just stop listening. Yes, let's do some packages. Do you want to start
us this week? I'll kick us off. My first package recommendation isn't a package recommendation,
per se. It's a it's a package search recommendation. I came across a social media post
a couple of weeks ago, about a project called LMDB, which I'd never heard of. So this is sort of a
key value store database, which has fast transactional asset transactions, support,
thread safe, crash proof, broad platform support. And the person wasn't posting about Swift,
this was just a general recommendation to look at LMDB. When you might be looking at SQLite as
sort of a similar project, but you know, SQLite is very relational. And this is a key value store
thing. So this might be if you have key values, that might be more fitting. And then I thought,
oh, it's interesting that I never heard of this. I wonder if we have wrappers, because it's a C
based project, I believe. I thought, well, maybe we do have wrappers. And I ran a search, and I was
really delighted to find quite a number of packages related like this, I'll name four.
There's a couple more even, and obviously just the plain C wrapper as well. So we got quick LMDB,
rapid LMDB, Swift LMDB, kind of a theme here in the names. And then Empire is a quite differently
named one. And these all, you know, wrap this and have various different APIs. I didn't try any of
them. But they looked well maintained and had different, you know, different ways of dealing
or adding an API on top of it. I thought that was really nice to see that this is represented. And I
think the database itself seemed quite interesting. So if you have a need for a key value store,
give this a try. When you normally perhaps would have chosen SQLite, I think that's a
nice alternative, if you need something like that.
And does it have any, you may not know this, but does it have any, any dependencies on other,
like, is it built on top of another SQL? Sorry, another key value store? Or is it
purely implemented inside this package?
I, well, the packages themselves probably pull in the C sources, but the LMDB itself, I think is a...
Ah, so LMDB is the underlying. Okay.
Yes. Yeah, that's a, that's a, it's sort of think of it as this is SQLite, an alternative to SQLite,
which has the same thing, right? You typically use, have SQLite interfaces by pulling in the
SQLite C sources and then building those and then adding richer APIs on top of it. And that's what
these packages are, I think, are generally doing. I haven't looked at all of them in detail,
but I've seen a couple, you know, explicitly call out that they're wrapping the
C sources or the, I think it's C under the hood. They're pulling, well, it must be C or C++,
I suppose. So yeah, there you go.
Great. My first package is called Fuzzi, F-U-Z-I, and the developer name is DimensionDev.
I'm not quite sure who's behind it, but it is actually a port or at least a,
it's based on a port of Matt Thompson's Ono library, which was, I think, an Objective-C
library back in the, well, yeah, I've just looked at it. It's more than 10 years old,
the Ono library, and the last commit was five years ago. So an abandoned library for parsing XML.
So obviously Swift can parse XML, but unlike JSON, XML has kind of died as an interchange
format these days, often for good reason. You know, JSON is very much more efficient in terms
of size and all the rest of it. So there are huge and significant reasons why JSON won that battle,
but certainly people still need to parse XML from time to time. And the APIs built into
Foundation for parsing XML are okay, but they're a little outdated compared to how we interact with
JSON. And what Ono and more recent Fousey library do is try to bring a more Swift-friendly syntax to
parsing and reading data from XML files. So it's still parsed, powered by libxml2 underneath the
covers. So very, very fast parsing from that, supports XPath and CSS queries,
auto conversion of dates and numbers. It can load HTML and XML documents from strings or
NSData. So it's got all the kind of basics, but then there are some things in Fousey that have
been improved as well. Mostly the Swift-style API, no more return types like in any object,
with so you're much more type safe with this new framework. Some customizable dates,
number four matters. So there's a few other things as well, but effectively it's a modernized
and easier way to access and parse XML, which if you still have to do that, you might be interested
in checking this out. - Nice. That looks great. And, you know, such a rich history,
nine years in development. That's amazing. And you see the sedimental layers. If you look through
the readme, there's pod install, there's Carthage update. It has all the different...
- Actually, I've... So I may have been slightly tricked by this. I've only just realized this,
the one that the dimension dev one that I've recommended here, and this is not the first
time I've done this. It's actually a fork. So Fousey itself, the original packet is by C. Zeng.
And what we'll do is we'll pop a link to both of these in the show notes, because what I didn't
realize is that this is a fork. So I'm not sure, I'm only just learning this now. I'm not sure how
different the version I saw in the new packages list is from that fork, but certainly either of
them are an enhancement over the standard XML document and XML parser classes.
- Great. Very nice. Right. My second pick is called Orb by Siddharth Mehta.
This is a lovely package. It creates Siri-like orbs. And by Siri-like orb, I mean that
that swirling, you know, like circle animation when you bring up Siri on your phone or on the
Mac, I think it's sort of universal thing. And it has many other variations as well. And the readme
is really nice in showing those off. So, you know, there's a number of this mystic nature,
sunset, minimal, different color themes, and I suppose different animations as well.
I don't think there's anything... No, it's not actually showing a video because I imagine the
animations might be slightly different depending on which one you pick, but you can, you get an
idea for what color they look like. So if you need an orb, and who doesn't, this is a package for you,
I suppose. - Well, who doesn't need an orb in these times? - Yes. - All right. My last package for
this week is called SolverCore, S-O-U-L-V-E-R, by Solver, the company who produced the Mac app,
Solver, which is a calculator app, which I've used for many, many years now. And I dearly,
dearly love it. And the unique thing about the app is that you... It's kind of like a cross between
a spreadsheet and a calculator. So you can type in lines of text which get evaluated. So you can
type in a mathematical kind of equation or something like that, and it will give you the
answer to that. Sorry, not equation, type in just, you know, three plus four, and it will give you
the answer to that. But then you can refer back to previous lines. So you can say, take the output
of line one and multiply it by 20, and then carry on like that. And over the years, it's become more
and more capable. You can bring currency conversions in there. It makes requests out to
get up-to-date currency conversion data. And the reason I noticed that in the package feed this
week is that they've just released a version three of this library, which I guess tracks a feature
they've just added in the application itself, which is that you can have place data inside
calculations now. So you can say, for example, what is the time in Ubud, Bali, and it will tell
you that. And it knows where places are. So you can say, what's the distance between London and,
you know, Anchorage or something like that. And it knows about places.
But what I really want to talk about with this is how this has been split out into, so mostly what
I've been talking about so far is the app called Solver, which you should absolutely check out if
you haven't used it already. But what Solver is built on top of is this Solver core package,
which gives you that calculation engine in a format that you can use, including all these
fancy features like places and currencies and all the rest of it, that you can embed into your apps.
And I've seen many apps now implement this. So for example, if you're in like a design application
and you wanted to say, well, this box that I'm editing is, you know, 10 pixels wide,
and I wanted to actually make it 10 plus eight pixels wide, because I'm adding eight to everything,
let's say, or a whole load of boxes. If you put Solver core behind those text boxes, they become
little calculators where you can just on the fly do calculations. And that's such a powerful feature.
Now, the one thing I should mention here is that this is not a completely free or open source
license. This is, I'll actually read you the bit from the bottom of the readme file,
because it's important to note this before you kind of go off and start using this project.
You may use Solver core in personal or private projects, but please email us if you wish to
use it in a publicly available or commercial project. So it's fine to play around with it.
It's fine to implement something, but before you actually ship anything with it,
you need to contact the company. And it is actually a binary, there is a binary target in there. So
it's also, you don't get the full source code for this calculation engine, but I still think it's
worth checking out because it's such a powerful concept, I think. I love it. Yeah. I mean,
Solver is just such a great app. If there's a library that allows you to do similar things in
your own code, and even if it's just a personal project, that's just great. I think that's a
fantastic tool. Well, I've spoken to, the developer is Zach Cohen, and I've spoken to him
on several occasions, actually. And as I understand it, Solver itself is built on this library. So
this is the real thing. This is not some pale imitation. This is it. Yeah. Very nice.
All right. My third and final pick is called Q by Matt Mazzicotte. And I think this time I actually
pronounced Matt's last name correctly. I've messed that up a couple of times in the past. Apologies,
Matt. Yeah, I saw a podcast with him. I think it was the Dev Diaries that we were on.
Yes. Yeah, exactly. And it was at that point that I realized that we've been
pronouncing his name wrong. Sorry, Matt. So we spoke about Swift 6 and concurrency earlier,
and this is a really nice package to give you an async queue. So, you know, one of the problems
with structured concurrency when you do task groups is you have no control over the execution
order of stuff. If you have async blocks and you enqueue them in these task groups, they can come
out in, you know, like not entirely random, I suppose. But, you know, you can't rely on the
order, really. And this fixes that. So it's effectively like a serial or concurrency,
concurrent queue, just like dispatch queue that you can enqueue async blocks on. And if you run
it serially, like you would in a serial dispatch queue, you really have execution order guarantees
what you get out of it. So that's really nice. It has a couple of other API extensions,
like something like a barrier. Have a look at the README. It gives examples. I think it's really
obvious what it does and how to use it. And it might be a really good tool, especially when
you look at transitioning over and you might have a serial queue and might not know how to
transition that over into Swift 6 concurrency. This might be the thing you need in that case.
So that's Queue by Matt Massicotte. And I think that brings us to the end of another episode
of the podcast. It does. So I think this will be the last podcast for this year,
because we're heading, we're absolutely careering towards the holidays. And I have a feeling this
will be the last one for 2024. So thank you so much for listening, even whether you just listened
to this, if this is your first episode you've listened to, or whether you've been with us
since the beginning. I really thank you for sticking with us. And we look forward to giving
you more of the same and even better in 2025. Yeah, exactly. Thank you. And yeah, see you next
time. Bye bye. All right see you next time. Bye bye.