Is Swift 6 a good first language?

Much of the Swift Concurrency design was also oriented around avoiding deadlocks! This is why, for instance, actors are reentrant.

6 Likes

Oh sure, my point there was more that the extent to which Swift Concurrency isn't 100% and varies somewhat depending on the type of bug. It's providing us all with airbags and a seatbelt, but it's not going to stop us from crashing or save us in every conceivable scenario so we still need to learn how to drive as safely as we would even without the protections. :slight_smile:

2 Likes

This comment made me laugh because, in my 30+ years experience mentoring new programmers and raising a young programmer kid, a plethora of global variables is a classic sign of a “young” programmer.

Requiring the maturity of novice programmers to not use global variables seems at odds with “easy” and “good as a first language.”

Cheers.

6 Likes

Great post!

1 Like

The way that "scripting mode" global variables work has been a longstanding design bug for reasons besides concurrency safety. If we were to change it, it would make sense to me to treat them more like local variables of the script itself, which would among other benefits avoid exposing scripters to concurrency problems.

15 Likes

Aside from one having a smaller scope than the entire script, is there a difference between:

private let X = 69_105

and

do {
  let x = 69_105
  ...
}

In top level code?

1 Like

The private let can still be referenced directly by locally-defined classes and structs, which "leaks" the script global back into shared mutable state:

private var foo = 17

public class Bar {
  public static func manipulateFoo() {
    foo = 38
  }
}

An alternative design might be to say that, without a visibility qualifier, let x = 17 is local to the top-level code, but you can write internal let x = 17 or private let x = 17 in order to declare a true global variable (which would then be initialized on first access like other global variables).

6 Likes

I think this pattern is still valuable when teaching new programmers. You can imagine this snippet illustrating how to adopt functions for code reuse:

var apples = 20

func takeApple() {
  apples -= 1
}

takeApple()
takeApple()
print("There are now \(apples) apples.")

(I haven’t checked, but I bet there’s something like this in the Learn to Code playground.)

That case would still be fine, since the function could act like a local function still and "capture" the variable from the outer scope.

4 Likes

This is very strange to hear because my impression is the exact opposite: Swift's concurrency ensures no deadlocks can occur (unless you resort to GCD or mix it with async/await), but it can't prevent logical data races!

If you disagree, could you provide an example in pure async/await how a program can reach a deadlock?

I might have got the two mixed up. I remember seeing some examples on Mastodon a while back during a discussion and I’ve had it in my head they were related to deadlocks, but it could have been data races. Either way, they were largely edge cases, but showed that Swift Concurrency is not a 100% solution and nobody has ever claimed it to be.

To bring it back to my original point: you need to be just as knowledgable about concurrent programming to use it correctly as you would with GCD (you just have a quicker feedback loop for most errors), and given concurrent programming is one of the most difficult things to understand, it’s something you would likely want to avoid teaching a new programmer (especially a kid) for months or even years. And right now it feels like you can’t avoid that in the Swift 6 language mode (though as Holly said, the team are looking at ways to improve that).

1 Like

To start write concurrent code that is more likely correct you have to know a few magnitudes less comparing to GCD, as Swift guards from tons of beginner and hidden mistakes – no thread explosion, no unsafe transfer between different threads, hard to deadlock, etc. And when you do something wrong, Swift will give you an error, rather then silently work incorrectly – and that's a major gain for the simplicity.

UPD. What you mostly end up with are logic errors. Yes, they are a significant part of getting concurrency right. Yet this is much lesser part of the things you have to worry about.

1 Like

I’m trying not to turn this into a discussion around GCD vs Swift Concurrency, that isn’t the point of the argument I’m making. My argument is that concurrent programming, regardless of whether you use Swift Concurrency, GCD, or raw threads, is something someone learning programming does not need to know until well into their journey on learning to code, and that currently the Swift 6 language mode does not do an ideal job of ensuring you won’t encounter Swift Concurrency until that point, which makes the language less suitable as a beginner language.

The only reason I brought up GCD vs Swift Concurrency is that I believe GCD does the progressive disclosure better (which is key to a complex language being easy to learn), but that is because it doesn’t have the compiler checks that need to be applied to all your code

4 Likes

I agree with this statement in general, but it is a bit out of sync with reality, where many of the developers start first writing SwiftUI apps and inevitably have to deal with it - by sending requests, loading images, etc.

Progressive disclosure isn’t about hiding wrong solutions, and that’s what you get with GCD[1]. You have to know a lot of details to avoid common pitfalls there, while Swift Concurrency allows to just write code that will work correctly without the need to understand its internals until you need to create more a complex solution. I think there is a bias towards GCD since it is much more familiar to many and we get used to it, and new concurrency is still something unknown.


  1. not that there is something wrong with GCD itself, it’s just different ↩︎

2 Likes

I wouldn't say it's too out of sync from reality when talking about someone who's new to coding. New coders don't jump right into coding UIs. When they do get to that point they often just do things that are synchronous ("make something happen when button pressed"). And when they do get to things like networking, that is largely asynchronous programming, which is different to concurrent programming, and (as I've said previously in the thread) is a lot easier to reason about, so is much easier to teach, and actually does have very good progressive disclosure in Swift.

Yes async/await is technically part of the overall Swift Concurrency package, but I consider it a separate feature to all the other stuff such as sendable, actors, etc

Regardless, it doesn't change the reality that your average new coder is going to be a fair way into their learning journey before they need to deal with this stuff and I'd argue if a language or API requires someone to learn it sooner then that makes the language/API less suitable for teaching new coders (though that doesn't necessarily mean such a design decision is bad if it offers benefits for existing coders).

Sure, but the point of progressive disclosure is to ensure you need to know nothing about a feature if you don't use it. If you don't use GCD then don't need to know GCD exists. But with Swift Concurrency in the Swift 6 language mode you will run into it. In fact it's near impossible to avoid it given the plethora of @MainActor, Sendable, @preconcurrency etc in the APIs and all the compiler checks.

And again, this isn't a bad thing. It means many classes of bugs are easier to find and harder to accidentally create. But to achieve this (incredibly impressive) feat requires it become a core and fundamental feature of the language that affects everything, rather than an API which you can ignore.

This means that, in my opinion, in the very specific case of whether a language is a good one to learn programming (i.e. the topic of the thread) Swift Concurrency is one of many features that makes it hard to recommend (again in that very specific case). Once you have learned the basics of coding and have the desire to build an app then yes, at that point, Swift is perfectly good as a language to learn to do that.

I love Swift and it's my favourite language, just as Obj-C was before it, but if someone comes up to me asking me to teach them to code I would not be using either language. Anyway… I think that's enough of my contributing to this thread, I'll leave it to others to continue :slight_smile:

3 Likes

I still disagree. For example, while SICP does introduce assignment of global variables early on, they mostly do it to say that it’s bad, and immediately pivot to better techniques: Structure and Interpretation of Computer Programs

From what I remember the rest of the book uses assignment a fair amount, but not with global variables.

You can nitpick the choice of programming language in SICP, but since all popular languages today support lexical scoping and closures, there’s no reason to rely on global variables when teaching another language either.

And of course Smalltalk—a language specifically designed to be taught to kids with no programming experience—does not have global variables at all.

6 Likes

That's a college level course text book. I don't think we're really talking about college level programming instruction in a thread entitled "Is Swift 6 a good first language."

"Kids these days" ;) are getting exposed to their first programming language as much as a decade before they go to college (if they go at all). We're talking about 8-12 year old kids (+/-).

Smalltalk may have been designed that way, but it's not suggested as a first programming language for kids by anyone I've run across in a long time.

I'm not suggesting ideal curriculum design. I'm mostly reporting on what I learned raising my own kid who wanted to learn to code. As well as helping other parents raising theirs. Also helping adults learning to code to try and move into a better field.

Also much Arduino coding (a common youth STEM entry point) seems to involve top level variables (often to define constants, but also data).

When one is learning to code from zero, it seems like folks generally learn from a single thread perspective because it's dramatically easier to do so. As a result, globals are not dangerous and easy to learn with before one moves on to structured data types and threading, etc.

All that said, this was largely a decade+ ago and maybe kids these days are starting with different desires and entry points.

However, today I would still recommend Python to parents looking to guide their (10-12 year old) kid regarding learning to program. Vastly simpler than Swift and not so fussy about complex concepts like multi-threading and data races and all that which are too much when a person is just getting started with the basic concepts of variables and control flow and writing simple functions.

(BTW, I agree that global variables are not good in professional code, of course. We're talking about people taking first steps in learning the basic concepts of coding - a "first [programming] language")


Anyway, thanks for the dialog. I'm ok with not everyone agreeing on this topic, of course :)

Fundamentally, I just think that Swift shouldn't slap folks with concurrency warnings until they're actually doing code that involves concurrency.

11 Likes

Is Swift 6 a good first language?

I would define "A good first language" to be one which prepares the learner for other languages they may have to learn later, languages such as C++, Rust, Go, and Swift.

Anyone who wants a smoother ride should start with C because it is not only small, but most importantly learning it first prepares the foundation required for grasping and appreciating what other languages such as C++, Rust, Go, and Swift are trying to achieve.

Original 2nd Paragraph

This is what I originally wrote, which caused upset in some people.

To clarify, the modal verb should as used above neither implies that one has to start with C, nor does it imply that one must start with C. It implies only some advice or suggestion. It does not mean that if you don't start with C, you are not going to be a competent programmer.

I acknowledge that it is not always what we say, but how say it.

5 Likes

Maybe try to avoid inflammatory language like "Anyone who is serious about becoming a competent programmer", it really doesn't support your position.

4 Likes

Not only that, C exposes how the computers actually work which yes, helps you better understand higher-level languages later. A chemist who understands molecular physics is a much better chemist compared to someone who doesn't.

1 Like