[HN Gopher] Mixing Swift and C++
___________________________________________________________________
Mixing Swift and C++
Author : oumua_don17
Score : 76 points
Date : 2023-07-23 14:04 UTC (8 hours ago)
(HTM) web link (www.swift.org)
(TXT) w3m dump (www.swift.org)
| chunkyguy wrote:
| > A C++ class or structure becomes a standalone type in Swift.
| Its relationship with base C++ classes is not preserved in Swift.
|
| C++ `class Fern: public Plant` becomes two different types in
| Swift `struct Plant` and `struct Fern`, how is this supposed to
| help anyone?
|
| https://www.swift.org/documentation/cxx-interop/#accessing-i...
| dagmx wrote:
| It still allows you to use them for interop. The only
| functionality that would be impaired is checking for
| inheritance with an `as?` type check/conform.
| fooker wrote:
| No, this blocks a fundamental concept of OOP: Liskov
| Substitution Principle.
|
| The idea is that you should be able to use a derived object
| anywhere the base one is required.
| dagmx wrote:
| It impairs that principle, yes. But it doesn't block
| similar patterns that give you similar end results. Swift
| has very flexible generics programming and type abstraction
| that still lets you use it with a little extra work.
|
| Yes, it won't be as ergonomic as the ideal, but it's better
| than many binding solutions from C++ to compiled languages,
| while providing most of the usability.
|
| Plus the footnote says that they plan to resolve this in
| future Swift versions.
| dwaite wrote:
| It does not import the relationship, but you can still
| model it via protocols.
| mgaunard wrote:
| Interop isn't magic. It can't make the C++ model transparently
| compatible with that of Swift when the two languages deviate.
| kubb wrote:
| C++ interop is impressive, and notoriously hard to get right.
| This seems like it would be able to cover a lot of APIs.
|
| Swift and C# are the well-designed languages I'd rather use at my
| work instead of Go. It's a real shame both are effectively locked
| into a specific platform.
|
| You can really tell that they had years of attention and careful
| design by experts in PL poured into them. Go seems like an
| amateur hobby project in comparison.
| metaltyphoon wrote:
| >It's a real shame both are effectively locked into a specific
| platform.
|
| This view of C# will be wrong for a almost a decade very soon!
| (if you don't count mono)
| wilg wrote:
| I'm not sure why you're saying Swift is locked in to Apple
| platforms, it's definitely cross-platform. It's no problem to
| run Swift on Linux or Windows. Of course, Apple's UI libraries
| aren't cross-platform. And they're putting a bunch of effort
| into making it better for servers and such. I wish more people
| realized how usable it is cross-platform, I think this is a
| misconception that hampers Swift adoption.
|
| Swift is definitely my favorite programming language from a
| language standpoint. I really like the way Swift works. It's
| safe, concise without being terse, and easy to extend.
|
| Sure, some people can argue there's some "bloat", but I think
| that's inevitable in a language that was designed to
| immediately be usable within Apple's existing APIs and
| frameworks. There's going to be complexity with Objective-C
| interop, C++ interop, etc. But that stuff is necessary for
| Swift to be usable for big projects. And I think Apple has done
| quite a good job of evolving Swift to be cleaner, clearer, more
| ergonomic, etc.
|
| I'm very excited that there's a lot of effort behind an open-
| source, cross-platform type-safe, compiled language that also
| prioritizes ergonomic high-level programming.
| SubjectToChange wrote:
| I don't trust Apple to care about platforms or developers
| that aren't directly benefiting them.
| duped wrote:
| They barely care about developers for their own platforms.
| Their docs are atrocious.
| t0ps0il wrote:
| > I'm not sure why you're saying Swift is locked in to Apple
| platforms, it's definitely cross-platform
|
| I think the key word in OPs comment is "effectively".
|
| The tools for building cross platform Swift exist and work in
| various levels but they aren't at the point where you would
| want to choose Swift over existing cross platform tools.
| coryrc wrote:
| IMO Go would have been 70% better with Result instead of
| (*type, error). So, so much duplicative code would have been
| avoided. It's not even a different paradigm. What a wasted
| opportunity.
| tempodox wrote:
| I'm using F# via the .NET SDK on macOS (i.e. I could also use
| C#), so it seems to have less platform lock-in than Swift at
| this point. It does have its limitations, for instance I can't
| for the life of me figure out how to make the F# REPL
| UTF8-capable. As ludicrous as that is, it's not really my use
| case, so I can live with that for now.
| bsaul wrote:
| Currently developing both in swift and go and i have the exact
| inverse feeling.
|
| Go seems to have been developped by true masters that really
| understand that less is more. They've also kept a laser sharp
| focus on working on things that really matters and took the
| time to do things right.
|
| Swift on the other hand looks like more and more bloated every
| day, without adressing the main pain points of the experience
| of coding in swift in the real world.
| SubjectToChange wrote:
| _Go seems to have been developped by true masters that really
| understand that less is more._
|
| "The key point here is our programmers are Googlers, they're
| not researchers. They're typically, fairly young, fresh out
| of school, probably learned Java, maybe learned C or C++,
| probably learned Python. They're not capable of understanding
| a brilliant language but we want to use them to build good
| software. So, the language that we give them has to be easy
| for them to understand and easy to adopt." - Rob Pike
|
| Ignoring complexity on the language level simply passes the
| buck to application code, and developers end up paying that
| price across the ecosystem in perpetuity.
|
| _They 've also kept a laser sharp focus on working on things
| that really matters and took the time to do things right._
|
| Go's async model is underspecified, its implementation of
| generics incurs runtime overhead, much of the "wonderful
| tooling" only exists because of severe shortcomings in the
| language design and/or compiler implementation, its FFI is...
| difficult, etc.
|
| To be blunt, the values that Go embraces are none of the
| values I seek in a programming language or community. And I
| feel sorry for anyone too heavily invested in Go to turn
| back.
| bsaul wrote:
| golang concurrent programming is by far the best i've ever
| used _for its application domain_ which is mainly
| infrastructure middlewares running in a connected
| environment.
|
| The tradeof between language features and maintainability
| is also IMHO the best in class. Never before have i ever
| looked at a stdlib sourcecode and told myself "hu, yeah i
| see how that works".
| saagarjha wrote:
| Depends on what you think they're masters of. Developer
| experience? Sure. Modern programming languages design?
| Absolutely not.
| ori_b wrote:
| What is the purpose of modern language design, if not to
| improve developer experience?
| saagarjha wrote:
| Developer experience is just one facet of writing
| software. It means that it is pleasant to write code, but
| you can also focus on:
|
| * Language features that make it so that you don't have
| to write code at all
|
| * Tooling that makes it easier to find bugs in the code
| you do write
|
| * Expressiveness and portability that allows the code to
| be used in more places
|
| * Approachability, so that new people can pick up the
| language quickly
|
| * "Batteries", so that people can rely on your high-
| quality libraries instead of having to manage their own
|
| * Documentation and community, to handle the hardest
| parts of programming: people
|
| * Performance, so that the code can use fewer resources
|
| ...among many other things.
| jb1991 wrote:
| It's a subjective issue, but sometimes the end results
| can be better even if the experience of getting there is
| not as nice as a simpler language that is more bug-prone.
| Consider Rust, which is notoriously difficult to learn,
| but that offers improved end results in many cases re:
| security, safety, reliability.
| ori_b wrote:
| Can you explain how that's not an aspect of developer
| experience? It seems to be like trading off between type
| system correctness (you can go all the way to needing
| full formal proofs of correctness, resource use, etc) and
| ease of getting stuff done is the core of developer
| experience.
| worik wrote:
| With Rust it is the learning curve that is hard.
|
| I find every other aspect of "developer experience"
| excellent
| jb1991 wrote:
| Does your idea of a good developer experience include
| programs that are reliable, won't crash in production,
| won't be compromised, and save you lots of time later on
| so you can just focus on writing code the first time? In
| the absence of these guarantees, your developer
| experience can include some very frustrating and/or
| stressful debugging.
| ori_b wrote:
| Yes. Does yours not?
|
| Tools like Agda, Spark, Idris, and Coq move the tradeoff
| around towards "probably correct", and I welcome seeing
| some of their features become gradually available.
| Getting things right the first time is useful.
|
| But these features can also make it hard to get anything
| done quickly.
|
| Good developer experience means finding a balance between
| the quick and dirty, and the provably correct.
| jb1991 wrote:
| You just made my point for me.
| geodel wrote:
| Same as purpose of modern arts. True masters know its
| worth. Will it look good in my living room? Doesn't
| matter.
| tempodox wrote:
| I think Go is made for writing a certain kind of software
| that is important for Google, and for a certain kind of
| developer Google wants to have writing this software. That
| the result is not the kind of language I would want to use
| is immaterial. I'm quite sure Go is masterfully targeted
| for the purposes Google wants it for.
| pjmlp wrote:
| Go was designed by a couple of well known UNIX folks that
| dislike C++.
|
| With exception of Kubernetes, most of Google's software
| keeps being written in Java, C++, Kotlin, and nowadays
| Rust.
|
| Its use is much more widespread outside Mountain View
| walls than inside them.
| seabrookmx wrote:
| And remember that unlike Amazon does with AWS, Google
| doesn't use GCP/Kubernetes to run it's infrastructure.
|
| Google's software runs on Borg, which is _not_ written in
| GoLang.
|
| Google's three OS projects all eschew GoLang as well.
| Someone wrote:
| But developer experience is a factor that should weigh
| heavily in evaluating the quality of a programming
| language.
|
| I also fear Swift is going a step too far. For example, IMO
| Swift's compilation speed isn't good enough.
|
| If that's a matter of lack of tooling, I won't blame the
| language, but is it, or is its slowness unavoidable for a
| language that is so flexible? If the latter, I would rather
| have a bit less flexibility and more compilation speed.
|
| Similarly, there's quality of error messages. Swift has
| gotten better there, but still has some weird ones. Are
| they unavoidable for the current language?
| cvwright wrote:
| I would be fine with slow, if the Swift compiler could
| actually compile all valid Swift programs. It's pretty
| commonplace for me to have to break a large or
| complicated function into smaller bite-size pieces
| because the compiler can't type check it all at once.
| refulgentis wrote:
| I had several years in the ObjC ecosystem, embraced Swift
| whole-heartedly immediately at 1.0, and was surprised by
| people nitpicking like this.
|
| It's been humbling to come back to it over the
| intervening 7 years and realize they weren't nitpicks
| that would be resolved shortly, and people would
| understand if they just read the swift-evolution mailing
| list. They were fundamental flaws.
| novok wrote:
| If they removed the few small features that are
| responsible for 80% of the slowness and called it
| optimized swift I bet many would embrace it fairly
| quickly, especially considering they are functionally
| cosmetic features.
| math_dandy wrote:
| When will "Swift: The Good Parts" be available for
| preorder?
| saagarjha wrote:
| Not really. These are pretty critical features for the
| language.
| refulgentis wrote:
| Not type inference, rather, whatever is so pathological
| about the fundamental algorithm for doing Swift type
| inference that it can become an infinite loop.
|
| This is a Swift-only feature in major languages with type
| inference.
| newZWhoDis wrote:
| If you are writing functions that the current/latest
| Swift compiler can't handle on modern hardware then I
| feel sorry for anyone who has to someday read your code.
| bsaul wrote:
| just try using state machines modelled with enums and
| you'll fairly quickly reach those limits.
| jwells89 wrote:
| This used to irritate me, but now that I'm in the habit
| of breaking functions up I've come to prefer it. It makes
| for code that's easier for myself to read and follow
| further down the road, which I think is a reasonable
| proxy for readability by others.
| cachvico wrote:
| Writing modular code is good but that's a ridiculous
| reason to need to do so.
|
| Xcode also trips on simple type errors and sometimes
| fails to even provide a line number where the error lies.
| As someone who just wrote a Swift app after no prior
| exposure, it's oddly immature in some basic ways after
| nearly a decade from launch.
| jwells89 wrote:
| Yeah I won't defend it too much, Xcode/SourceKit/etc are
| clearly written in a way that assumes devs are writing
| perfectly idiomatic, smell-free code which isn't very
| aligned with reality. I've more or less got a feel for
| what makes it grumpy so I don't trip it up too often any
| more but it's annoying on the odd occasion I do.
| dagmx wrote:
| When discussing compiler speed, Go specifically
| prioritizes compilation speed over optimization of the
| resulting code.
|
| Swift and Rust both suffer from slower compilation than
| Go, primarily because LLVM prioritizes optimization over
| speed.
|
| There are of course other reasons like complexity of
| language, size of compilation units etc... but
| optimization tends to be the biggest hit in my
| experience.
|
| Hence why Rust is adopting/investigating cranelift as a
| debug compiler to improve speed.
| Someone wrote:
| > There are of course other reasons like complexity of
| language, size of compilation units etc... but
| optimization tends to be the biggest hit in my
| experience.
|
| I _guess_ you don't have much experience with Swift. LLVM
| code generation may be slower than alternatives, but
| that's more or less by a constant factor.
|
| Swift's type inference, on the other hand, can lead to a
| combinatorial explosion.
|
| For example,
| https://www.hackingwithswift.com/articles/11/how-to-make-
| swi... claims that let sum = [1, 2,
| 3].map { String($0) }.flatMap {
| Int($0) }.reduce(0, +)
|
| takes over 11 seconds to compile, while
|
| compare this code: let sum = [1, 2,
| 3].map { (num: Int) -> String in String(num)
| }.flatMap { (str: String) -> Int? in Int(str)
| }.reduce(0, +)
|
| takes about 75ms, and let numbers = [1,
| 2, 3] let stringNumbers = numbers.map {
| String($0) } let intNumbers =
| stringNumbers.flatMap { Int($0) } let
| sum = intNumbers.reduce(0, +)
|
| compiles in 71ms.
|
| Of course, all of these use LLVM, and likely even
| generate highly similar intermediate code.
|
| Also, you'll see these slowdowns even in debug builds
| that don't ask LLVM to optimize code much.
| dagmx wrote:
| Pretty rude to start your comment with the assumption
| that I'm not experienced with Swift. The rest of your
| comment would be more useful without the unnecessary
| condescension.
|
| But nothing you said contradicts what I said either. Yes
| it's easy to get into slow paths with Swift, but it's
| also easy not to. Granted it takes a lot of up front
| knowledge to do so.
|
| But even if you just stick to the LLVM portion, llvms
| debug mode is slower than cranelift and other toolchains
| debug modes. Debug doesn't mean "no optimizations"
| whatsoever, nor does it mean efficient paths through the
| toolchain either.
| jb1991 wrote:
| What pain points are you referring to? Beyond the lack of
| meaningful cross-platform abilities, what "real world" issues
| do you find painful in Swift?
| bsaul wrote:
| indeed that would be number 1 by a VERY high margin. It's
| pretty ridiculous to start with "world domination" as an
| objective and end up 10 years later without a portable
| stdlib (aka foundation).
|
| Another issue would be a coherent concurrency system. Today
| we have a mix of gcd and actor system, declarative task,
| async await, etc which when put together makes me totally
| unable to understand what's going on in a real world
| program, unless you're doing like i do in my team : i
| specifically ban all modern concurrency apis in favor of
| the old ones.
|
| The same could be said with protocol extension + generics +
| class + structs.
|
| For each problem, there are approximately 4 possible
| designs with subtle tradeoffs. Swift team advocates for
| "expressiveness". My personnal experience is that all
| patterns and technics will ultimately end up showing in the
| codebase, depending on the mood of the developer.
|
| In the end, i've started to do like C++ developers end up
| doing : write guidelines on which language features are
| allowed, and which are forbidden.
|
| Compare that to go, where there's (at most) one satisfying
| way to design the problem in the typesystem. As a
| sideeffect people have to think more about the problem
| they're trying to solve, and how to simplify it to the
| maximum.
|
| The end result is that go pushes you toward simple and
| maintainable code. Swift pushes you toward being fancy for
| no good reasons.
| KerrAvon wrote:
| It doesn't sound like you actually understand Swift or
| the Mac platform you claim it's tied to.
|
| (a) Foundation is portable and available on Windows and
| Linux.
|
| (b) You are confusing language features and OS features.
| Async/await is part of the language. GCD is part of the
| OS.
|
| (c) Banning modern concurrency primitives is not viable
| forever -- you'll be left behind as the native APIs adopt
| them.
| slavapestov wrote:
| > Another issue would be a coherent concurrency system.
| Today we have a mix of gcd and actor system, declarative
| task, async await, etc which when put together makes me
| totally unable to understand what's going on in a real
| world program, unless you're doing like i do in my team :
| i specifically ban all modern concurrency apis in favor
| of the old ones.
|
| There's a layering:
|
| - gcd is the lowest level
|
| - async/await lets you write tasks with suspension points
| (they wait for events to happen); but an async function
| is still conceptually executed serially
|
| - the Task API let's you spin up async functions into
| various arrangements of parallel tasks and wait for those
| tasks to complete
|
| - 'async let' is sugar for creating a Task to compute a
| single expression
|
| - for async functions and Tasks to share data there is a
| Sendable model and various static isolation checks
|
| - actors build on everything else; actors are classes
| whose state is completely isolated to the actor, and all
| method calls are posted on the actor's executor
|
| Memory-safe concurrency is hard. There's a lot of ground
| to cover to replace the kind of things people do with
| shared state concurrency, and just actors alone are not
| enough.
|
| > Compare that to go, where there's (at most) one
| satisfying way to design the problem in the typesystem.
| As a sideeffect people have to think more about the
| problem they're trying to solve, and how to simplify it
| to the maximum.
|
| I like the aesthetics of small languages too, but I think
| Go picked the wrong small subset. It reminds me of Java
| in the 1.x days, for x <= 4, where the language had
| fundamental expressiveness constraints that created a
| huge amount of unavoidable boilerplate and type unsafety
| in even the most basic programming situations.
| bsaul wrote:
| "... reminds me of java"
|
| i was having doubts before go introduced generics. But
| the fact that they managed to add it so perfectly while
| maintaining the unambiguous focus on simplicity and
| structs made me confident they've really nailed it.
|
| The only feature i don't get why they haven't added yet
| is proper enum to get some kind of ADT. It looks super
| orthogonal to the language and quite convenient. However
| at this point i fully trust their taste. If they think
| it's going to lead to catastrophic design decisions, i
| fully believe them.
| jb1991 wrote:
| > protocol extension + generics + class + structs
|
| you are referring to basic languauge features... you
| consider classes and structs pain points? these are the
| basic building blocks of the language, if you find them
| painful this is definitely not the language for you.
| fauigerzigerk wrote:
| It seems to me that their threshold for introducing new
| language features is extremely low. If something cannot
| be made to look flawlessly pretty using existing syntax
| they will go to any length to fix it, regardless of how
| much extra complexity they have to introduce.
|
| Result builders are a case in point. Essentially, they
| didn't like the bracket and the comma between array items
| in the special case where a function returns only a
| single array. // So rather than this
| let items = makeUgly { [ Item("One"),
| Item("Two"), Item("Three") ] }
| // It had to look like this let items = makePretty
| { Item("One") Item("Two")
| Item("Three") }
|
| Yes, it's prettier. There's a bit less clutter. But
| there's a cost too. makePretty uses entirely different
| language semantics without any syntactical clue at the
| call site.
|
| So now there are essentially two separate syntax modes in
| Swift, and every time you look at some code you have to
| make up your mind on whether to read it in normal mode or
| in result builder mode. Sometimes that's easy to know in
| context. But it's another thing you have to pay attention
| to at all times.
| bsaul wrote:
| I feel swift really makes it impossible to learn as a
| language. The number of idioms has grown exponentially at
| the detriment of orthogonality. I think the red line was
| crossed with result builders indeed.
|
| Looks like a manager once said "we've got to look like
| jsx/html, now !" and the poor devs had to obey. It makes
| absolutely no sense from a language design POV.
| bsaul wrote:
| i wonder if this isn't going to have the side effect of making
| some people write more cross platform code in c++.
| pjmlp wrote:
| The reason why many of us still reach out to C++, is that in
| many cases the option is only between C or C++, and from both,
| at least C++ provides some safety knobs.
| fooker wrote:
| People are going to keep writing libraries in C++ until there's
| a better option.
| dagmx wrote:
| I think that's fine as long as there's no performance penalty.
|
| People were doing it anyway. This just eases the friction, and
| potentially increases performance since many wrappers are
| really inefficient with regards to data marshalling
| meisel wrote:
| I've been bitten enough by Objective-C++ compiler bugs (Apple's
| attempt at mixing Objective-C and C++), as well as bugs in
| Apple's code in the Swift ecosystem, not to trust the stability
| here for at least several years. I also don't see how this is
| much better than just creating a C or ObjC wrapper around a C++
| library, rather than needing to keep C++'s complicated language
| features, and Swift's interop with it, in my head as I use the
| library. Were there people clamoring for this? I can't really see
| the point.
| pjmlp wrote:
| History class, Objective-C++ was created by NeXT.
| gumby wrote:
| You might have better luck using g++ rather than clang for
| Objective-C++. We originally developed it on gcc (there was no
| llvm and the NeXT used gcc). By the time Apple switched to llvm
| I imagine they weren't as interested in Objective-c++
| eschaton wrote:
| Your imagination is incorrect.
| pjmlp wrote:
| GCC isn't that compatible with everything post Objective-C
| 2.0, there is only a kind of partial support.
|
| At WWDC 2023 there were a couple of sessions with
| Objective-C++ content, e.g. how to extend PyTorch on macOS.
| dagmx wrote:
| Going from C++ through ObjC++ to ObjC to Swift is pretty
| onerous. There's a lot of type reduction and conversion along
| the way and a lot of manual binding generation. Performance and
| safety footguns are plentiful through that route.
|
| If you have large existing C++ libraries, this (in theory)
| would really help simplify the process and reduce that mental
| overhead you mention.
|
| I'm not sure how your suggestion of creating wrappers is better
| because you'd have to still keep the C++ side for those
| wrappers and introduce a new intermediary layer to manage as
| well. Surely having one less layer is desirable?
| KerrAvon wrote:
| Actually compiler bugs or just badly documented interactions
| between the two models, leading to misunderstandings?
| meisel wrote:
| Address sanitizer violations caused when using C++ containers
| with ObjC objects
| eschaton wrote:
| This is a lot of what folks refer to as compiler bugs when
| dealing with ObjC++, yeah, usually when they not asking for
| help and instead just cobbling together their own
| workarounds.
| ashvardanian wrote:
| On a related topic of hybrid Swift and C++ tooling - has anyone
| used Doxygen/Sphinx to generate HML docs for modern Swift,
| similar to how people do it for pure C++ projects?
| dagmx wrote:
| Swift does have docc that does the same
|
| https://swift.org/blog/swift-docc/
|
| I've never had good luck getting documentation working cross
| language and so I use docc for Swift, doxygen for C++, rustdoc
| for Rust and Sphinx for Python. Then I just link between them
| if a project uses more than one language
| ashvardanian wrote:
| Sure, but how do you style and host those docs? Can you style
| them identically? We use a combo of Furo + Sphinx + Doxygen
| for C/C++, Python, JavaScript, Java here: https://unum-
| cloud.github.io/docs/usearch
|
| For ObjC, Swift, Rust, and other languages we couldn't make
| it work for now.
___________________________________________________________________
(page generated 2023-07-23 23:03 UTC)