Archive for April 2025

Thursday, April 3, 2025

Altair Basic Source Code

Bill Gates (via Slashdot):

It feels like just yesterday that Paul and I were hunched over the PDP-10 in Harvard’s computer lab, writing the code that would become the first product of our new company.

That code remains the coolest code I’ve ever written to this day—and you can see it for yourself at the bottom of this page.

[…]

Paul and I set out to create a BASIC interpreter, which would translate code into instructions the computer understood line by line as the program runs.

[…]

Paul and I decided to divide and conquer. We didn’t have the Intel 8080 chip that the Altair computer ran on, so Paul got to work writing a program that would simulate one on Harvard’s PDP-10 mainframe. This allowed us to test our software without needing an actual Altair. Meanwhile, I focused on writing the main code for the program while another friend, Monte Davidoff, worked on a portion called the math package. We coded day and night for the two months to create the software we had said already existed.

Richard Speed:

The source code is provided as a 157-page PDF [link] of scanned fan-fold paper rather than as source in a convenient repository. An annotated disassembly of Altair BASIC 3.2 can be found on GitHub.

Previously:

France Fines Apple Over App Tracking Transparency

Reuters (PDF, Slashdot):

Apple was hit with a 150 million euro ($162.4 million) fine by French antitrust regulators on Monday for abusing its dominant position in mobile app advertising on its devices via a privacy control tool.

[…]

“While we are disappointed with today’s decision, the French Competition Authority has not required any specific changes to ATT,” Apple said in a statement.

Coeuré told reporters the regulator had not spelled out how Apple should change its app, but that it was up to the company to make sure it now complied with the ruling.

Ben Lovejoy:

Both advertisers and developers of free ad-funded apps complained loudly at the impact of ATT, as it was estimated that it would cost social media companies alone tens of billions of dollars.

Complaints were made in a number of countries – some arguing that it was unfair because Apple exempts its own apps (which are in reality subject to even tighter controls), others saying the loss of revenue forced developers to raise prices to compensate.

Jon Brodkin (Hacker News):

The intent of ATT “is not problematic in terms of the likely benefits for users as regards privacy protection,” but “how the framework is implemented is abusive within the meaning of competition law,” the agency said. Apple’s “implementation methods artificially complicate the use of third-party applications and distort the neutrality of the framework to the detriment of small publishers financed by advertising,” it said.

Third-party publishers “cannot rely on the ATT framework to comply with their legal obligations,” so they “must continue to use their own consent collection solution,” the French agency said. “The result is that multiple consent pop-ups are displayed, making the use of third-party applications in the iOS environment excessively complex.”

[…]

The agency said there is an “asymmetry” in which user consent for Apple’s own data collection is obtained with a single pop-up, but other publishers are “required to obtain double consent from users for tracking on third-party sites and applications.”

[…]

Apple said in a statement that the ATT “prompt is consistent for all developers, including Apple[…]”

Is this actually true? It sounds like when Tim Cook told Congress that Apple’s own apps have to follow the same guidelines as third-party apps. I don’t think I’ve ever seen an Apple app display the “Allow ‘App’ to track your activity across other companies’ apps and websites?” prompt. Apple has defined tracking in such a way that it doesn’t count if you own the app store, so why would they ever show that prompt? I have seen Apple apps show different prompts, and the French Competition Authority includes a screenshot of one.

Nick Heer:

Because the ATT prompt does not allow developers to specify which third-parties are receiving tracking data, developers must include a second opt-in screen that provides more details about how their data will be used. This is fairly granular — arguably too much — but Apple’s version lacks detail. If a user agrees to third-party tracking, is their consent fully informed if they do not know with which advertisers their information is being shared, or even how many? I am not sure they do.

They also seemed to disagree with how Apple defines tracking. German regulators are also interested in what amounts to self-preferencing, even if that is not Apple’s intent. The authority has not yet published the text of the decision, which will hopefully answer many of the questions I have.

One thing I am curious about is how the regulator reconciles Apple’s apparently “not problematic” attempts at improving user privacy with the callous disregard toward the same shown by ad tech companies. Trade groups representing those companies, including the French offices of the IAB and MMA, were among those who filed this complaint. Both trade groups are loathsome; their inability and failure to self-govern is one reason for this very privacy legislation. Yet Apple’s particular definition of “tracking” is something only relevant to very large platform operators like itself. There is very clearly a conflict of interest in Apple trying to apply these kinds of policies to competitors, especially as Apple expands its ads business.

John Gruber (Mastodon):

It’s ostensibly “not necessary” because French and EU privacy laws are supposedly enough, and all that’s needed. And it’s unfair because now, under ATT, third-party surveillance advertisers who seek to track users across apps on iOS need to ask permission twice — first through the clear-as-a-bell “Ask App Not to Track” / “Allow Tracking” prompt required by Apple, and again through the byzantine but ultimately toothless permission requirements of France and the EU. ATT has had measurable effects because users understand it, and they prefer not to be tracked. EU and French privacy laws are largely ineffective because, in practice, they bury users with confusion.

I’m not sure these last two sentences are really true, as Heer also discusses.

Previously:

France Rejects Backdoor Mandate

Joe Mullin:

In a moment of clarity after initially moving forward a deeply flawed piece of legislation, the French National Assembly has done the right thing: it rejected a dangerous proposal that would have gutted end-to-end encryption in the name of fighting drug trafficking. Despite heavy pressure from the Interior Ministry, lawmakers voted Thursday night (article in French) to strike down a provision that would have forced messaging platforms like Signal and WhatsApp to allow hidden access to private conversations.

Via Irreal:

One of my favorite stories is the probably apocryphal story of some legislature trying to legislate the value of pi. The same mindset is in play with legislators who believe that they can simply will a secure backdoor into existence. The fact that experts everywhere say, “No you can’t.” makes no impression.

Alexander Martin (via Nick Heer):

The European Commission announced on Tuesday its intention to join the ongoing debate about lawful access to data and end-to-end encryption while unveiling a new internal security strategy aimed to address ongoing threats.

[…]

The aim is to “identify and assess technological solutions that would enable law enforcement authorities to access encrypted data in a lawful manner, safeguarding cybersecurity and fundamental rights,” said the Commission.

Previously:

Apple Intelligence Available in EU

Apple:

Starting today, with the availability of iOS 18.4, iPadOS 18.4, and macOS Sequoia 15.4, Apple Intelligence features are now available in many new languages, including French, German, Italian, Portuguese (Brazil), Spanish, Japanese, Korean, and Chinese (simplified) — as well as localized English for Singapore and India — and are accessible in nearly all regions around the world.

In addition, iPhone and iPad users in the EU have access to Apple Intelligence features for the first time[…]

I’m not sure why the Mac is absent from that list.

Norbert Heger:

Wasn’t macOS 15.4 supposed to bring support for additional languages like German to Apple Intelligence?

He has the system language set to English (which Apple Intelligence already supported) and is getting an error that Apple Intelligence is not available when Siri is set to German. But it works after changing the system language to German.

Nick Heer:

I remain skeptical that Apple Intelligence was ever “delayed” in the region. Until today, it was only available in variations of English. When Apple announced in November it would be bringing these features to the E.U., it sure seemed like it also needed the time to train its models on a range of new languages reflecting the regions where it would be used.

If Apple was so worried about the wrath of regulators, it could have made accessing Apple Intelligence in the E.U. as complicated as it does E.U.-specific features outside the region. But it did not.

Previously:

Update (2025-04-03): Steve Troughton-Smith:

[The] Mac doesn’t qualify as a VLOP, only iOS and iPadOS. Even if it did, though, it meets most if not all of the DMA requirements anyway, because it’s not locked down like iOS.

Wednesday, April 2, 2025

Moving Targets

Nick Lockwood:

Airdrop on macOS has this “great” feature where it displays receivers asynchronously as it finds them and they are sorted alphabetically, so the order shuffles randomly under the mouse as you are trying to click

Brought to you by the guy who sent a file to a random colleague when trying to share it between two machines 😩

Norbert Heger:

Hey Apple, I found a layout bug in Mail.app. The rightmost category button is always truncated…

I assume this is intentional because otherwise there would be no indication that you could scroll to find more buttons.

Mario Guzmán:

Lesson 1 in #UIUX… your buttons should not be moving targets. Especially if they’re toggles.

Look at how if I toggle on “Transactions” and then toggle it off, I am no longer in the bounds of that button. TF?!

I have a feeling this was designed for touch and touch only. It wouldn’t matter there because you lift your finger after tapping…

Previously:

Swift Testing: Return Errors From #expect(throws:)

Also new in Swift 6.1, ST-0006:

We offer three variants of #expect(throws:):

  • One that takes an error type, and matches any error of the same type;
  • One that takes an error instance (conforming to Equatable) and matches any error that compares equal to it; and
  • One that takes a trailing closure and allows test authors to write arbitrary validation logic.

The third overload has proven to be somewhat problematic. First, it yields the error to its closure as an instance of any Error, which typically forces the developer to cast it before doing any useful comparisons. Second, the test author must return true to indicate the error matched and false to indicate it didn’t, which can be both logically confusing and difficult to express concisely[…]

Note that, with Swift 6.0, only the third variant actually lets you access the thrown error. So that’s what I always used, but I found it awkward. I’d been using a helper method to make it a little better:

func expect<T, E>(sourceLocation: SourceLocation = #_sourceLocation,
                  _ performing: () throws -> T,
                  throws errorChecker: (E) -> Void) {
    // @SwiftIssue: Must write this separately or it won't type-check.
    func errorMatcher(_ e: any Error) throws -> Bool {
        let error = try #require(e as? E, sourceLocation: sourceLocation)
        errorChecker(error)
        return true
    }
    #expect(sourceLocation: sourceLocation, 
            performing: performing, 
            throws: errorMatcher)
}

This would do the cast, but I think it was still not great:

expect {
    try // something
} throws: { (error: MJTError) in
    // check `error`
}

With Swift 6.1, the first two variants return the matched error, so I can just write:

let error = try #require(throws: MJTError.self) {
    try // something
}
// check `error`

Much better! Note that I’ve switched from #expect to #require because it doesn’t really work to do:

if let error = #expect(throws: MJTError.self) // ...

The if doesn’t interact well with the trailing closure syntax, so I think I would have to write it like:

let error = #expect(throws: MJTError.self) {
    try // something
}
if let error {
    // check `error`
}

if I really wanted to continue after the error didn’t match.

Note that if you don’t care what the error is but do want to look at it, you can pass (any Error).self as the error type.

I was also wondering, now that we have typed throws, why doesn’t it check at compile time that the test code throws the right type of error? The answer:

If we adopted typed throws in the signatures of these macros, it would force adoption of typed throws in the code under test even when it may not be appropriate. For example, if we adopted typed throws, the following code would not compile[…]

Previously:

Severed Edits

Ernie Smith (via Hacker News):

But it of course raises the question: Do they make Apple‘s shows on Macs? As the second season of Severance ended in dramatic fashion, Apple decided to answer that question, and the answer was … surprisingly confusing.

[…]

In the video Apple released, which highlights the Mac-driven editing process that Ben Stiller's team is using, something stood out to me: Wait, the video is super-jittery—this makes the Mac Mini look rough. What's going on?

Then, after about 10 minutes of watching, I saw it: The show’s lead editor, Geoffrey Richman, was working on a remote Mac through Jump Desktop, a screen sharing tool known for its high-speed “fluid remote desktop” feature.

[…]

To me, though, it highlights a huge issue with Apple’s current professional offerings. They are built to work on a single machine. At least for high-end use cases, the remote workflow threatens to cut them out of the equation entirely, as cloud devices with access to nearly unlimited resources gradually outpace individual machines. In fact, there is a version of the editor he was using, Avid Media Composer, that is cloud-based and built specifically for this very use case.

See also: John Gruber.

Previously:

Rebuilding the Social Security Administration’s Codebase

Makena Kelly (Hacker News):

The project is being organized by Elon Musk lieutenant Steve Davis, multiple sources who were not given permission to talk to the media tell WIRED, and aims to migrate all SSA systems off COBOL, one of the first common business-oriented programming languages, and onto a more modern replacement like Java within a scheduled tight timeframe of a few months.

[…]

This proposed migration isn’t the first time SSA has tried to move away from COBOL: In 2017, SSA announced a plan to receive hundreds of millions in funding to replace its core systems. The agency predicted that it would take around five years to modernize these systems. Because of the coronavirus pandemic in 2020, the agency pivoted away from this work to focus on more public-facing projects.

[…]

As recently as 2016, SSA’s infrastructure contained more than 60 million lines of code written in COBOL, with millions more written in other legacy coding languages, the agency’s Office of the Inspector General found. In fact, SSA’s core programmatic systems and architecture haven’t been “substantially” updated since the 1980s when the agency developed its own database system called MADAM, or the Master Data Access Method, which was written in COBOL and Assembler, according to SSA’s 2017 modernization plan.

When the original X.com merged with PayPal, Musk wanted to rewrite the code and switch everything from Unix to Windows. Part of the thinking, if I recall, was that it would be easier to hire Windows developers. The original PayPal engineering team rejected this and maneuvered to have him replaced as CEO.

It probably is a good idea to modernize old government systems and get them off COBOL, but Musk is not known for the careful approach that doing this properly would require. Still, it’s interesting to think about how this should be done. I wonder if they could run the new system in a sandbox for a year, feeding it all the same inputs, and see whether it generates the same outputs.

Note that the existing system is tested but not problem-free. It seems to be pretty reliable about dispensing payments, but there have been multiple multi-month periods where I was not able to log into my account or I could log in but it wasn’t functional.

Previously:

Tuesday, April 1, 2025

Swift Testing: Test Scoping Traits

Holly Borla:

Swift 6.1 enables custom Swift Testing traits to perform logic before or after tests run in order to share set-up or tear-down logic. If you write a custom trait type which conforms to the new TestScoping protocol, you can implement a method to customize the scope in which each test or suite the trait is applied to will execute. For example, you could implement a trait which binds a task local value to a mocked resource:

struct MockAPICredentialsTrait: TestTrait, TestScoping {
  func provideScope(for test: Test, testCase: Test.Case?, performing function: @Sendable () async throws -> Void) async throws {
    let mockCredentials = APICredentials(apiKey: "fake")
    try await APICredentials.$current.withValue(mockCredentials) {
      try await function()
    }
  }
}

extension Trait where Self == MockAPICredentialsTrait {
  static var mockAPICredentials: Self { Self() }
}

@Test(.mockAPICredentials)
func example() {
  // Validate API usage, referencing `APICredentials.current`...
}

Because task locals cannot be separated into set-up and tear-down portions, they were previously only usable in Swift Testing if you repeated them within each test function. TestScoping gets rid of the indentation that entails and can also be applied at the suite level, so you don’t have to repeat it for each test. It’s great to have this functionality, though I think the implementation via traits feels a bit convoluted compared with XCTest’s invokeTest().

ST-0007:

Some test authors have expressed interest in allowing custom traits to access the instance of a suite type for @Test instance methods, so the trait could inspect or mutate the instance. Currently, only instance-level members of a suite type (including init, deinit, and the test function itself) can access self, so this would grant traits applied to an instance test method access to the instance as well. This is certainly interesting, but poses several technical challenges that puts it out of scope of this proposal.

It seems like a major limitation that any code factored out in this way can’t access properties or helper functions in the type that contains the test.

Some reviewers of this proposal pointed out that the hypothetical usage example shown earlier involving setting a task local value while a test is executing will likely become a common use of these APIs. To streamline that pattern, it would be very natural to add a built-in trait type which facilitates this. I have prototyped this idea and plan to add it once this new trait functionality lands.

Previously:

Update (2025-04-02): Christian Tietze:

I really like how Swift Testing Traits turns into how Emacs Lisp implements function advising.

You basically decorate a function call with a macro.

Unlike (Emacs) Lisp, you can't fiddle with the context of the called function and pass data along.

Xcode 16.3

Apple (security, downloads):

Clang now defines TARGET_OS_* conditionals as built-in macros based on the provided target triple.

[…]

Searching in the documentation viewer may start an indexing process which makes no progress. This may result in missing search results and increased CPU usage.

[…]

Fixed: Foundation encoders/decoders user info dictionaries now require Sendable values. This may cause build errors even in the Swift 5 language mode in small edge cases where the userInfo property is set to a value like init(myCustomInitializer:) where the initializer is defined in an extension on Dictionary with a Value == Any constraint.

[…]

Instruments 16.3 includes a new Processor Trace Instrument which uses hardware-supported, low-overhead CPU execution tracing to accurately reconstruct execution of the program.

[…]

In Xcode when you are in a test context you are now able to query for your test plan name and scheme name in the environment with the keys XCODE_TEST_PLAN_NAME and XCODE_SCHEME_NAME.

[…]

xcodebuild supports constraining the tests run through tests actions by tags. Use -only-testing-tags to include tests identified by a tags and -skip-testing-tags to omit tests identified by tags.

There are also lots of C++ and Swift/C++ improvements. It does not look like the issues with linking to certain frameworks on older versions of macOS (FB14667312) or calling async functions bridged from Objective-C (134442168) have been fixed yet.

Xcode Releases:

It is identical to RC2 that came out a couple of days ago.

Matt Massicotte (via Christian Tietze):

No, dynamic isolation is not bad.

But, I think we can also agree that static isolation is preferable. If you find yourself using dynamic isolation solely because it is a familiar pattern, that’s something to think about more deeply. Static isolation is a safer, clearer way to express what you need. That doesn’t mean you can always or even should start with it. Adopting concurrency will be a long process. Dynamic isolation is a very handy tool for getting there, I just don’t think it should typically be an end-state.

Rob Napier:

I’m wondering if there are changes to how DynamicActorIsolation works in Xcode 16.3. I’m seeing crashes due to running on a background thread that I don’t have with 16.2. The closure in question isn’t intended to be MainActor even though it’s defined in a View. With DynamicActorIsolation turned on, it seems to be getting MainActor assertions added, even if I mark it Sendable.

Paul Hudson:

If you upgraded to Xcode 16.3, be warned: there appears to be a simulator bug that causes network access to fail regularly. It doesn’t affect devices, just the simulator. You can work around it by using URLSession(configuration: .ephemeral) rather than URLSession.shared.

Previously:

Update (2025-04-02): Sean Heber:

Xcode 16.3 is seemingly refusing to remember the width of the canvas panel where SwiftUI previews live between tab switches and it is driving me bonkers and I’ve only had this version of Xcode a few hours.

SpamSieve 3.1.2

SpamSieve 3.1.2 improves the filtering accuracy of my Mac e-mail spam filter, amongst other enhancements and fixes.

Some interesting issues were:

Previously:

xAI Acquires X/Twitter

Elon Musk (Hacker News):

@xAI has acquired @X in an all-stock transaction. The combination values xAI at $80 billion and X at $33 billion ($45B less $12B debt).

Since its founding two years ago, xAI has rapidly become one of the leading AI labs in the world, building models and data centers at unprecedented speed and scale.

X is the digital town square where more than 600M active users go to find the real-time source of ground truth and, in the last two years, has been transformed into one of the most efficient companies in the world, positioning it to deliver scalable future growth.

xAI and X’s futures are intertwined. Today, we officially take the step to combine the data, models, compute, distribution and talent. This combination will unlock immense potential by blending xAI’s advanced AI capability and expertise with X’s massive reach.

CNBC:

Musk launched xAI less than two years ago with a stated goal to “understand the true nature of the universe.” The startup has been trying to compete directly with OpenAI, the richly valued AI startup that Musk co-founded in 2015 as a non-profit research lab. He later left OpenAI and has recently been involved in a public relations and legal spat with the company and CEO Sam Altman over the direction that it’s taken.

[…]

X and xAI have already been intertwined, with xAI’s Grok chatbot available to users of the social media app.

It’s not clear to me whether this is essentially just a clever refinancing or whether something material has changed. On paper, Twitter is now profitable, and the business was sold for more than the original acquisition price. But the investors haven’t actually made a profit yet. They just own untradeable shares in a different private company. xAI, which seemed to come out of nowhere, is propped up by even more capital that it raised on the back of the AI boom, probably at more favorable terms. The ownership is now different, and perhaps the corporate structure and control are, too.

Richard Speed:

Looking into the future requires speculation. More Grok is likely, although Musk had already been heavily promoting xAI’s chatbot on X. As such, the service would have been further integrated regardless of the acquisition.

The main beneficiaries of the acquisition are X investors, who have endured years of turbulence since Musk acquired the platform. Owning shares in a growing AI startup is far more appealing than shares in a declining – though still significant – social media platform.

According to Gartner, worldwide generative AI spending is set to hit $644 billion in 2025, up 76.4 percent from 2024.

Previously: