frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

fp.

Open in hackernews

Approachable Swift Concurrency

https://fuckingapproachableswiftconcurrency.com/en/
58•wrxd•3h ago

Comments

seanalltogether•2h ago
One of the things that really took me a long time to map in my head correctly is that in theory async/await should NOT be the same as spinning up a new thread (across most languages). It's just suspending that closure on the current thread and coming back around to it on the next loop of that existing thread. It makes certain data reads and writes safe in a way that multithreading doesn't. However, as noted in article, it is possible to eject a task onto a different thread and then deal with data access across those boundaries. But that is an enhancement to the model, not the default.
jen20•53m ago
I'd argue the default is that work _does_ move across system threads, and single-threaded async/await is the uncommon case.

Whether async "tasks" move across system threads is a property of the executor - by default C#, Swift and Go (though without the explicit syntax) all have work-stealing executors that _do_ move work between threads.

In Rust, you typically are more explicit about that choice, since you construct the executor in your "own" [1] code and can make certain optimizations such as not making futures Send if you build a single threaded one, again depending on the constraints of the executor.

You can see this in action in Swift with this kind of program:

    import Foundation
    
    for i in 1...100 {
      Task {
        let originalThread = Thread.current
        try? await Task.sleep(for: Duration.seconds(1))
        if Thread.current != originalThread {
          print("Task \(i) moved from \(originalThread) to \(Thread.current)")
        }
      }
    }
    
    RunLoop.main.run()
Note to run it as-is you have to use a version of Swift < 6.0, which has prevented Thread.current being exposed in asynchronous context.

[1]: I'm counting the output of a macro here as your "own" code.

MORPHOICES•1h ago
How do you actually learn concurrency without fooling yourself?

Every time I think I “get” concurrency, a real bug proves otherwise.

What finally helped wasn’t more theory, but forcing myself to answer basic questions:

What can run at the same time here?

What must be ordered?

What happens if this suspends at the worst moment?

A rough framework I use now:

First understand the shape of execution (what overlaps)

Then define ownership (who’s allowed to touch what)

Only then worry about syntax or tools

Still feels fragile.

How do you know when your mental model is actually correct? Do you rely on tests, diagrams, or just scars over time?

mrkeen•57m ago
Share xor mutate, that's really all there is
halfmatthalfcat•1h ago
I loved the idea of Swift adopting actors however the implementation seems shoehorned. I wanted something more like Akka or QP/C++...
jen20•1h ago
> I wanted something more like Akka

https://github.com/apple/swift-distributed-actors is more like Akka, but with better guarantees from the underlying platform because of the first-class nature of actors.

troupo•49m ago
> the implementation seems shoehorned.

Because it's extremely hard to retrofit actors (or, really, any type of concurrency and/or parallelism) onto a language not explicitly designed to support it from scratch.

Someone•45m ago
I feel the reverse. I can see one can claim Swift has everything but the kitchen sink, but its actors, to me, don’t look shoehorned in.

Reading https://docs.swift.org/swift-book/documentation/the-swift-pr..., their first example is:

  actor TemperatureLogger {
      let label: String
      var measurements: [Int]
      private(set) var max: Int

      init(label: String, measurement: Int) {
          self.label = label
          self.measurements = [measurement]
          self.max = measurement
      }
  }
Here, the ‘actor’ keyword provides a strong hint that this defines an actor. The code to call an actor in Swift also is clean, and clearly signals “this is an async call” by using await:

  await logger.max
I know Akka is a library, and one cannot expect all library code to look as nice as code that has actual support from the language, but the simplest Akka example seems to be something like this (from https://doc.akka.io/libraries/akka-core/current/typed/actors...):

  object HelloWorld {
    final case class Greet(whom: String, replyTo: ActorRef[Greeted])
    final case class Greeted(whom: String, from: ActorRef[Greet])

    def apply(): Behavior[Greet] = Behaviors.receive { (context, message) =>
      context.log.info("Hello {}!", message.whom)
      message.replyTo ! Greeted(message.whom, context.self)
      Behaviors.same
    }
  }
I have no idea how naive readers of that would easily infer that’s an actor. I also would not have much idea about how to use this (and I _do_ have experience writing scala; that is not the blocker).

And that gets worse when you look at Akka http (https://doc.akka.io/libraries/akka-http/current/index.html). I have debugged code using it, but still find it hard to figure out where it has suspension points.

You may claim that’s because Akka http isn’t good code, but I think the point still stands that Akka allows writing code that doesn’t make it obvious what is an actor.

ModernMech•16m ago
This is my feeling as well. It feels to me that based on the current product, Swift had two different designers: one designer who felt swift needed to be a replacement for Objective C and therefore needed to feel like a spiritual successor to that language, which meant it had to be fundamentally OOP, imperative, and familiar to iOS devs; and another designer who wanted it to be a modern functional, concurrent language for writing dynamic user interfaces with an advanced type checker, static analysis, and reactive updates for dynamic variables.

The end result is a language that brings the worst of both worlds while not really bringing the benefits. An example I will give is SwiftUI, which I absolutely hate. You'd think this thing would be polished, because it's built by Apple for use on Apple devices, so they've designed the full stack from editor to language to OS to hardware. Yet when writing SwiftUI code, it's very common for the compiler to keel over and complain it can't infer the types of the system, and components which are ostensibly "reactive" are plagued by stale data issues.

Seeing that Chris Lattner has moved on from Swift to work on his own language, I'm left to wonder how much of this situation will actually improve. My feeling on Swift at this point is it's not clear what it's supposed to be. It's the language for the Apple ecosystem, but they also want it to be a general purpose thing as well. My feeling is it's never not going to be explicitly tied to and limited by Apple, so it's never really going to take off as a general purpose programming language even if they eventually solve the design challenges.

whalesalad•11m ago
Any sufficiently complicated concurrent program in another language contains an ad hoc informally-specified bug-ridden slow implementation of half of Erlang.

- Robert Virding

scottmf•1h ago
Concurrency issues aside, I've been working on a greenfield iOS project recently and I've really been enjoying much of Swift's syntax.

I’ve also been experimenting with Go on a separate project and keep running into the opposite feeling — a lot of relatively common code (fetching/decoding) seems to look so visually messy.

E.g., I find this Swift example from the article to be very clean:

    func fetchUser(id: Int) async throws -> User {
        let url = URL(string: "https://api.example.com/users/\(id)")!
        let (data, _) = try await URLSession.shared.data(from: url)
        return try JSONDecoder().decode(User.self, from: data)
    }

And in Go (roughly similar semantics)

    func fetchUser(ctx context.Context, client *http.Client, id int) (User, error) {
        req, err := http.NewRequestWithContext(
            ctx,
            http.MethodGet,
            fmt.Sprintf("https://api.example.com/users/%d", id),
            nil,
        )
        if err != nil {
            return User{}, err
        }
    
        resp, err := client.Do(req)
        if err != nil {
            return User{}, err
        }
        defer resp.Body.Close()
    
        var u User
        if err := json.NewDecoder(resp.Body).Decode(&u); err != nil {
            return User{}, err
        }
        return u, nil
    }

I understand why it's more verbose (a lot of things are more explicit by design), but it's still hard not to prefer the cleaner Swift example. The success path is just three straightforward lines in Swift. While the verbosity of Go effectively buries the key steps in the surrounding boilerplate.

This isn't to pick on Go or say Swift is a better language in practice — and certainly not in the same domains — but I do wish there were a strongly typed, compiled language with the maturity/performance of e.g. Go/Rust and a syntax a bit closer to Swift (or at least closer to how Swift feels in simple demos, or the honeymoon phase)

tidwall•59m ago
Or this.

    func fetchUser(id int) (user User, err error) {
        resp, err := http.Get(fmt.Sprintf("https://api.example.com/users/%d", id))
        if err != nil {
            return user, err
        }
        defer resp.Body.Close()
        return user, json.NewDecoder(resp.Body).Decode(&user)
    }
jtbaker•49m ago
I'm conflicted about the implicit named returns using this pattern in go. It's definitely tidier but I feel like the control flow is harder to follow: "I never defined `user` how can I return it?".

Also those variables are returned even if you don't explicitly return them, which feels a little unintuitive.

ragnese•11m ago
I haven't written any Go in many years (way before generics), but I'm shocked that something so implicit and magical is now valid Go syntax.

I didn't look up this syntax or its rules, so I'm just reading the code totally naively. Am I to understand that the `user` variable in the final return statement is not really being treated as a value, but as a reference? Because the second part of the return (json.NewDecoder(resp.Body).Decode(&user)) sure looks like it's going to change the value of `user`. My brain wants to think it's "too late" to set `user` to anything by then, because the value was already read out (because I'm assuming the tuple is being constructed by evaluating its arguments left-to-right, like I thought Go's spec enforced for function arg evaluation). I would think that the returned value would be: `(nil, return-value-of-Decode-call)`.

I'm obviously wrong, of course, but whereas I always found Go code to at least be fairly simple--albeit tedious--to read, I find this to be very unintuitive and fairly "magical" for Go's typical design sensibilities.

No real point, here. Just felt so surprised that I couldn't resist saying so...

hocuspocus•41m ago
Not defending Go's braindead error handling, but you'll note that Swift is doubly coloring the function here (async throws).
Invictus0•40m ago
@dang I think it's important that "fucking" remains in the title
JKCalhoun•28m ago
(It certainly makes it easier to find the topic some time after when going back to search for it on HN.)
mojuba•37m ago
It's a good article but I think you need to start explaining structured concurrency from the very core of it: why it exists in the first place.

The design goal of structured concurrency is to have a safe way of using all available CPU cores on the device/computer. Modern mobile phones can have 4, 6, even 8 cores. If you don't get a decent grasp of how concurrency works and how to use it properly, your app code will be limited to 1 or 1.5 cores at most which is not a crime but a shame really.

That's where it all starts. You want to execute things in parallel but also want to ensure data integrity. If the compiler doesn't like something, it means a design flaw and/or misconception of structured concurrency, not "oh I forgot @MainActor".

Swift 6.2 is quite decent at its job already, I should say the transition from 5 to 6 was maybe a bit rushed and wasn't very smooth. But I'm happy with where Swift is today, it's an amazing, very concise and expressive language that allows you to be as minimalist as you like, and a pretty elegant concurrency paradigm as a big bonus.

I wish it was better known outside of the Apple ecosystem because it fully deserves to be a loved, general purpose mainstream language alongside Python and others.

ragnese•4m ago
> It's a good article but I think you need to start explaining structured concurrency from the very core of it: why it exists in the first place.

I disagree. Not every single article or essay needs to start from kindergarten and walk us up through quantum theory. It's okay to set a minimum required background and write to that.

As a seasoned dev, every time I have to dive into a new language or framework, I'll often want to read about styles and best practices that the community is coalescing around. I promise there is no shortage at all of articles about Swift concurrency aimed at junior devs for whom their iOS app is the very first real programming project they've ever done.

I'm not saying that level of article/essay shouldn't exist. I'm just saying there's more than enough. I almost NEVER find articles that are targeting the "I'm a newbie to this language/framework, but not to programming" audience.

isodev•36m ago
I really don't know why Apple decided to substitute terms like "actor" and "task" with their own custom semantics. Was the goal to make it so complicated that devs would run out of spoons if they try to learn other languages?

And after all this "fucking approachable swift concurrency", at the end of the day, one still ends up with a program that can deadlock (because of resources waiting for each other) or exhaust available threads and deadlock.

Also, the overload of keywords and language syntax around this feature is mind blowing... and keywords change meaning depending on compiler flags so you can never know what a code snippet really does unless it's part of a project. None of the safeties promised by Swift 6 are worth the burnout that would come with trying to keep all this crap in one's mind.

hn-acct•25m ago
Do people actually believe that there are too many keywords? I’ve never met a dev irl that says this but I see it regurgitated on every post about Swift. Most of the new keywords are for library writers and not iOS devs.

Preventing deadlock wasn’t a goal of concurrency. Like all options - there are trade offs. You can still used gcd.

isodev•7m ago
> Do people actually believe that there are too many keywords?

Yes they do. Just imagine seeing the following in a single file/function: Sendable, @unchecked Sendable, @Sendable, sending, and nonsending, @conccurent, async, @escaping, weak, Task, MainActor.

For comparison, Rust has 59 keywords in total. Swift has 203 (?!), Elixir has 15, Go has 25, Python has 38.

> You can still used gcd.

Not if you want to use anything of concurrency, because they're not made to work together.

Public Sans – A strong, neutral typeface

https://public-sans.digital.gov/
109•mhb•1h ago•29 comments

Netflix: Open Content

https://opencontent.netflix.com/
369•tosh•6h ago•60 comments

Non-Zero-Sum Games

https://nonzerosum.games/
183•8organicbits•4h ago•48 comments

The British Empire's Resilient Subsea Telegraph Network

https://subseacables.blogspot.com/2025/12/the-british-empires-resilient-subsea.html
53•giuliomagnifico•3h ago•8 comments

Postgres extension complements pgvector for performance and scale

https://github.com/timescale/pgvectorscale
39•flyaway123•5d ago•1 comments

The Legacy of Undersea Cables

https://blog.sciencemuseumgroup.org.uk/the-legacy-of-undersea-cables/
12•teleforce•1h ago•0 comments

Times New American: A Tale of Two Fonts

https://hsu.cy/2025/12/times-new-american/
96•firexcy•3h ago•58 comments

Go away Python

https://lorentz.app/blog-item.html?id=go-shebang
173•baalimago•7h ago•125 comments

Hive (YC S14) Is Hiring a Staff Software Engineer (Data Systems)

https://jobs.ashbyhq.com/hive.co/cb0dc490-0e32-4734-8d91-8b56a31ed497
1•patman_h•1h ago

Approachable Swift Concurrency

https://fuckingapproachableswiftconcurrency.com/en/
58•wrxd•3h ago•23 comments

GOG is getting acquired by its original co-founder

https://www.gog.com/blog/gog-is-getting-acquired-by-its-original-co-founder-what-it-means-for-you/
787•haunter•23h ago•463 comments

No strcpy either

https://daniel.haxx.se/blog/2025/12/29/no-strcpy-either/
107•firesteelrain•3h ago•45 comments

Stranger Things creator says turn off "garbage" settings

https://screenrant.com/stranger-things-creator-turn-off-settings-premiere/
292•1970-01-01•16h ago•527 comments

Show HN: One clean, developer-focused page for every Unicode symbol

https://fontgenerator.design/symbols
102•yarlinghe•5d ago•45 comments

Tesla's 4680 battery supply chain collapses as partner writes down deal by 99%

https://electrek.co/2025/12/29/tesla-4680-battery-supply-chain-collapses-partner-writes-down-dea/
564•coloneltcb•22h ago•623 comments

Hacking Washing Machines [video]

https://media.ccc.de/v/39c3-hacking-washing-machines
169•clausecker•14h ago•35 comments

ManusAI Joins Meta

https://manus.im/blog/manus-joins-meta-for-next-era-of-innovation
278•gniting•17h ago•170 comments

Nicolas Guillou, French ICC judge sanctioned by the US and “debanked”

https://www.lemonde.fr/en/international/article/2025/11/19/nicolas-guillou-french-icc-judge-sanct...
204•lifeisstillgood•5h ago•145 comments

The future of software development is software developers

https://codemanship.wordpress.com/2025/11/25/the-future-of-software-development-is-software-devel...
313•cdrnsf•21h ago•337 comments

Concurrent Hash Table Designs

https://bluuewhale.github.io/posts/concurrent-hashmap-designs/
19•signa11•3d ago•0 comments

Charm Ruby – Glamorous Terminal Libraries for Ruby

https://charm-ruby.dev/
71•todsacerdoti•8h ago•10 comments

UNIX Fourth Edition

http://squoze.net/UNIX/v4/README
84•dcminter•1w ago•7 comments

AI is forcing us to write good code

https://bits.logic.inc/p/ai-is-forcing-us-to-write-good-code
251•sgk284•21h ago•186 comments

Turning an old Amazon Kindle into a eInk development platform (2021)

https://blog.lidskialf.net/2021/02/08/turning-an-old-kindle-into-a-eink-development-platform/
48•fanf2•4d ago•8 comments

Singapore Study Links Heavy Infant Screen Time to Teen Anxiety

https://www.bloomberg.com/news/articles/2025-12-30/singapore-study-links-heavy-infant-screen-time...
45•1vuio0pswjnm7•3h ago•19 comments

Graph Algorithms in Rayon

https://davidlattimore.github.io/posts/2025/11/27/graph-algorithms-in-rayon.html
32•PaulHoule•4d ago•0 comments

Google is dead. Where do we go now?

https://www.circusscientist.com/2025/12/29/google-is-dead-where-do-we-go-now/
974•tomjuggler•19h ago•770 comments

MongoDB Server Security Update, December 2025

https://www.mongodb.com/company/blog/news/mongodb-server-security-update-december-2025
99•plorkyeran•15h ago•40 comments

Win32 is the stable Linux ABI

https://loss32.org/
142•krautburglar•3h ago•109 comments

2025 Was Another Exceptionally Hot Year

https://e360.yale.edu/digest/2025-second-hottest-year
4•Brajeshwar•42m ago•0 comments