Poll: what do you strongly dislike about Swift?

If you mean this asymmetry:

func foo(_ a: Int)              ---> foo(1)
func foo(a: Int)                ---> foo(a: 1)
func foo(at a: Int)             ---> foo(at: 1)
vs
subscript(_ a: Int) -> Int      ---> foo[1]
subscript(a: Int) -> Int        ---> foo[1]
subscript(at a: Int) -> Int     ---> foo[at: 1]

then I am with you, this is quite odd.

Subscript labels themselves - I like.

8 Likes

I agree that "hate" feels too severe, but...

As someone else mentioned above, I really wish if and switch were expressions.

And I REALLY wish cross-platform Swift had more momentum.

9 Likes

Do you have any examples of projects using result builders to good effect? They don't appear to be remotely widely used, and the few things I've seen that have used them have been just experiments to see if they're a net benefit for something (and to my eyes, most of those experiments have had the answer "not really, no"). I certainly haven't seen anything that makes me think that criticizing them for being too SwiftUI-specific is misplaced.

1 Like

Well, the regex builder DSL is the obvious current example. Quite a lovely option for somebody trying to break a large regex into fluent, readable, documentable chunks without sacrificing performance.

6 Likes

To me that is mostly another example of the feature just being a very complicated way to avoid having to separate things with commas so that code snippets in a presentation look slightly nicer. If there were no downsides then that'd be fine, but my experience with SwiftUI has been that when actually writing code and not just admiring its aesthetics there have been a lot of downsides (e.g. incredibly bad error messages, and the syntax regularly misleads me into writing things which look like they should work but actually don't).

You are correct. I just stated my concern as an observer from afar.

It's not a language feature at all, but the fact Swift is always seen as just an app dev language for Apple-platform in a lot of people's perspectives.

It is already a great language for general-purpose programming - especially for server development - but not a lot of people seem to care.

9 Likes

That's still too much magic and abstraction. People should start with the untyped lambda calculus so they learn how computers actually work.

9 Likes

While mostly a lurker here, this is a great place to enumerate some of the things I would hope for. I may be ignorant of some workarounds for these and if so please share solutions. I also understand that many of these are tied to Objective-C or NSObject requirements.

  • Codable: Translated property names. For example the server I use returns IDs such as 'userId' but I use 'userID' in my app. To do that mapping requires coding keys, etc. even if only one property name has changed. What about an attribute such as @JSON(name: "UserId")?
  • Enums: Defining an enum uses 'case someValue' but in use its 'Enum.someValue'. It would be great if we allowed '.case someValue'.
  • String: Constantly having to do 'String(someStringLikeEntity)'. Any time I have to drop to NSString to get functionality (NSString.pathComponents, .substring(with: match.range(at: 2))). Shouldn't String be complete on it's on? And what about attributed strings?
  • NSPrefix: Anything with the NSPrefix seems extremely weird and out of place. NSPredicate, NSDecimalNumber, NSNumber, NSString, NSAttributedString, etc.
  • CoreData: Anywhere you have a mismatch between what primitive types can be stored in CoreData as a NSPrefixedType but not a standard Swift type. For example 'Decimal' vs 'NSDecimalNumber'.
  • Access Levels: I sorely wish for a 'protected' access.
  • Extension Access: I would love to be able to access private properties/methods from an extension. I don't like having all my variables/methods internal just so an extension can use them.
  • Build Issues: I have no idea why I can't build projects sometimes. Xcode spits out some cryptic message. I clean the build folder it still doesn't compile. I restart Xcode it still doesn't compile. The only thing that works is to exit Xcode and then remove derived data. I do this so often I have an alias: rdd='rm -rf ~/Library/Developer/Xcode/DerivedData'.
  • Debugging: The debugger is sometimes useless. It takes forever to populate the local properties and even then the content displayed for a property is confusing. Using the command line to print a variable (p someArray.count) works about 50% of the time.

@tgoyne DL4S and S4TF’s Sequential constructs are examples of result builders. They mirror the Python Keras API for machine learning.

This is an example of what we could have had instead of result builders. Consider this API:

func foo(_ x: Int, _ y: Int, _ z: [Int]) {...}

called like so:

foo(x, y, [1, 2, 3])

First, we can drop commas when elements are put on separate lines:

foo(x, y, [
    1
    2
    3
])

Then we can do a minor syntax optimization very similar to the trailing closure optimization:

foo(x, y) {
    x
    y
    z
}

which would have the same effect of what result builders do, without having them explicitly.

Likewise the same could work for sets & dictionaries:

foo(x, y) {
    "x" : 1
    "y" : 2
    "z" : 3
}

as a shallow syntax sugar for foo(x, y, ["x" : 1, "y" : 2, "z" : 3])

2 Likes

I was able to rename the tread to “strongly dislike”. I think so far this is a productive thread to collect the many pain points in swift for folks.

3 Likes

This is the same journey that c# is going tru and swift will have the uphill battle unless more companies adopt swift for nonapple platforms. With c# it took mono to make c# popular in Linux for some things. I wonder who would do the same for swift on Linux. This reminds me of the following video

4 Likes

It's been mentioned and discussed on this forum a few times, but: abstract methods that force you to implement a method in a subclass at compile time is what I miss in Swift.

Currently the only workaround to this is preconditionFailure() in the body of the abstract method which shifts the check to run-time. Not that I "hate" this but relying on runtime testing of something that could be done at compile time just doesn't feel right for a static language.

The argument against this is that Swift is a protocol-oriented language and a lot of the times you could achieve the same effect by using protocols. Basically you define your class as a typealias to a union of some class (that shouldn't be used directly) and a protocol that defines your abstracts. You point the user of your library at the type alias and say: "This is what you should use because I have some abstract methods in the protocol that will force you to define them. Sorry!"

This requires significantly more typing (and later reading), and multiplying entities (class = internal class & protocol) compared to just the abstract keyword and a single class declaration.

Why Swift resists to this is not entirely clear to me.

11 Likes

Although less important than the missing “.”, shell access.

That's missing the crucial feature of result builders though: You can have elements of different types, and propagate information about those types out of the result builder closure and into the rest of the program. SwiftUI in particular obscures this a bit with pervasive opaque type usage, but unless I misunderstand, this feature is a big part of the SwiftUI performance story.

And with the recently reviewed enhancements, you can even define pretty advanced rules for what sequences of types are allowed in your DSL.

I do agree omitting the commas in multi-line literals would be nice, and I'm also vaguely sympathetic to the idea of a "generalized trailing literal syntax" (I would think square brackets would be more appropriate though, if that doesn't clash with subscripts (and quotes for trailing strings maybe?)). But that would not replace what result builders can do.

1 Like

When the compiler becomes flaky and cryptic instead of deterministic and educational, crumbling under all the features the language wants to have, when the official book gets thicker yet less complete, then I feel like the language evades definition and thereby ceases to exist.

5 Likes

Arrays can have elements of different typesÂč...

Have a look
import Foundation

protocol Some { // : Equatable or similar <- since on Swift 5.7
  func bark()
}

struct C: Some {
  func bark() { print("C ", terminator: "") }
}
struct D: Some {
  func bark() { print("D ", terminator: "") }
}

func foo(_ a: [any Some]) {
  a.forEach {
    $0.bark()
  }
  print()
}

foo([])
foo([C()])
foo([C(), C()])
foo([C(), D()])

print("done")

Âč even when elements have Self or associated type requirement, this is allowed since Swift 5.7

1 Like

A post with productive intent may have looked like: “What are some things that can be improved in Swift?” with perhaps an area of focus.

Instead, this has just invited wide-ranging complaints, many that are not even about the Swift language.

9 Likes

There's nothing wrong with a thread once in a while that lets people vent a little in a non-destructive way.

12 Likes