RSSAmplifier

Blog

Rob Napier

cocoaphony.micro.blogRSS feed ↗14 posts

Latest posts

"AI makes them slower."

METR just released another report , titled “Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity.” The pull quote is: Surprisingly, we find that when developers use AI tools, they take 19% longer than without—AI makes them slower. I’ve been pondering this one all morning. I generally like their methodology. Obviously you always want ever-more…

TIL:AI. Thoughts on AI

I use AI a lot for work, pretty much all day every day. I use coding assistants and custom agents I’ve built. I use AI to help code review changes, dig into bugs, and keep track of my projects. I’ve found lots of things it’s very helpful with, and lots of things it’s terrible at. If there’s one thing I have definitely learned: it does not work the way I imagined. And…

My AI distractions, hopefully a lesson, but maybe just a story

I feel there’s definitely a blog post in here. I don’t want to get distracted from my testing series, but my head’s just churning and I need to write stuff, so maybe I’ll just sketch a story until I can turn it into something more coherent. I’ve been working on this small program to convert close-scored choral music into separate rehearsal tracks. I currently do it by…

Why I struggle to use actors

Following up on some discussion about why I keep finding myself using Mutex (née OSAllocatedUnfairLock) rather than actors . This is kind of slapped together; eventually I may try to write up a proper blog post, but I wanted to capture it. Each of these is a runnable file using swift ... , with embedded commentary. // Actor to manage deferring execution on a bunch of things until requested //…

Dropped messages in for-await

Swift concurrency has a feature called for-await that can iterate over an AsyncSequence. Combine has a .values property that can turn Publishers into an AsyncSequence. This feels like a perfect match! But it is surprisingly subtle and makes it very easy to drop messages if you’re not careful. Consider the following example (full code is at the end). // A NotificationCenter publisher that…

Externalizing properties to manage retains

I have a very simple type in my system. It’s just an immutable struct: public struct AssetClass: Sendable, Equatable, Hashable, Comparable { public let name: String public let commodities: [String] public let returns: Rates public static func Bool { lhs.name Bool { lhs.name == rhs.name } public func hash(into hasher: inout Hasher) { hasher.combine(name) } } It has a unique name, a short…

A short anecdote on getting answers on the modern internet

This post is way off topic, and a bit in the weeds, and maybe even a bit silly, which is why I’m throwing it here rather than getting back to making my proper blog work. I really will do that, but… ok, not today. I’ve been trying to learn some abstract algebra. I never studied it in school, and sometimes I bump into people describing operations in “group-speak”…

A Reminder About NSRange and String

The NSRange for a full string is NSRange(location: 0, length: (text as NSString).length) . You cannot use text.count for this. NSRanges on strings are based on UTF-16 code points, not Swift Characters. A character like 👩‍👩‍👧‍👧 has a .count of 1, but a .length of 11. ObjC-based NSRange APIs (even ones ported to Swift) need the latter. Swift interfaces (which use Range rather than NSRange) need…

Big-O matters, but it's often memory that's killing your performance.

We spend so much time drilling algorithmic complexity. Big-O and all that. But performance is so often about contention and memory, especially when working in parallel. I was just working on a program that does Monte Carlo simulation. That means running the same algorithm over the same data thousands of times, with some amount of injected randomness. My single-threaded approach was taking 40…

Pull Requests are a story

I’ve been thinking a lot about how to make PRs work better for teams, and a lot of my thinking has gone into how to show more compassion for the reviewer. Tell them your story. What was the problem? What did you do to improve it? How do you know it is a working solution (what testing did you do)? Why do you believe it is the right solution? Why this way rather than all the other ways it…

Solving "Required kernel recording resources are in use by another document" in Instruments

So you have a Swift Package Manager project, without an xcodeproj, and you launch Instruments, and try to profile something (maybe Allocations), and you receive the message “Required kernel recording resources are in use by another document.” But of course you don’t have any other documents open in Instruments and you’re at a loss, so you’ve come here. Welcome.…

Time for something new

So, all my tweets about C++ and Rust brings me to a minor announcement. After nearly 6 years with Jaybird, learning so much about Bluetooth on iPhones and custom firmware and audio, it’s time for something new. Luckily, Logitech is large enough that I can change jobs without changing my health insurance. In October I’m moving to the Logitech Software Engineering team. My exact projects…

(untitled)

OK, I just fell in 😍 with stdlib’s Result(catching:) . extension Request where Response: Decodable { func handle(response: Result<Data, Error>, completion: (Result<Response, Error>) -> Void) { completion(Result { try JSONDecoder().decode(Response.self, from: response.get()) }) } }

(untitled)

Reminder: If you&rsquo;re running into limitations with default parameters (for example, the value can&rsquo;t be computed, they can&rsquo;t specialize a generic, defaults don&rsquo;t exist in literals), you can always replace a default with an explicit overload. func f(x: Int = 0) {} is the same as func f(x: Int) {} func f() { f(0) } stackoverflow.com/questions&hellip;