Rust, Swift and C++
A simple Comparsion on Swift, Rust, C++’s syntax as a beginner on Rust after learning some swift and C/C++. Three static-typed, compiled programming language .
Besides, as swift 5.9 comes with C++ interoperability support I think it would be a good source to learn some C++ and Swift relationship and comparision.
Value and Types
It’s infact impossible to talk about value, without talking about how do functions, closure, structure, class, and ARC d
Swift value basics
1 | let x = 1 |
Rust with owership
After I write this code, I believe rust should be safer and faster with it’s ownership, reference and borrowing.
1 | fn main() { |
Swift Memory Operation
while in swift you don’t expecilitly have a reference for what ever value you want, but class, and ARC is a thing to talk about.
Someone said that swift don’t have directly access to Memory which makes it slower. I don’t know if it’s becaused my misundering, though uncommon, but we have for array:
1 | var arr = [10, 100, 1000, 10000] |
and
1 | let arr = [10, 20] |
Nothat these ptr are different, one is type method for array, with BufferPointer
; and another is Generic function and Pointer
.
This is not talked about in Swift Programming Language, but have a detailed explaination in Standard Library Documentation
These function would be helpful when coping with c code. But if not, you may not ever see these code in swift. Anyway, it’s a big topic, but a glimpses of it makes me have a better understanding of swift programming language. And I hope this would be helpful for anyone learn these language.
stored property, calculated property, and property observer.
1 | var stored: Int = 0 { |
I think swift struct and class should also be talked about in this phase, for accordance, and better understanding with let and val, and let, var for compound value and reference.
Type
Both in swift and rust, thougth staticly typed. Many times you don’t expilictly write type, and type Inferenced is the default behavior, unlike c/c++, thought you have auto and decltype, it’s not the default behavior, thus most times you still need to write types.
But still, swift and rust have some difference in type inference:
1 | use std::collections::HashMap; |
this phase is legal, as type of scores
is infered from line below.
How, similar code is impossible in swift, in swift these code are ok, as the type can but infered from literal after the assignment sign.
1 | let arr = [10, 100, 1000] // OK |
but in swift, type can’t be infered from line after
1 | var dict = Dictionary() //Error: Generic parameter 'Key' could not be inferred |
Believe, this won’t cause much trouble in swift, and I believe would your code more clear.
What’s more, I think this limited make’s swift repl
possible.
I think in Rust this type inference would cause trouble in implementation of repl, as you can do this when writing in a file, types are infered from line after, but in repl, when you write code line by line, this feature was impossible. But it seems Rust really have a repl thing, maybe they just disabled this feature in REPL
, I don’t know.
Struct, Class
Some Language have only struct like C, some only class like Java, maybe python, I don’t rememeber any python code with struct. Up to my knowledge know, Rust has only Struct. C++ have both struct and class, but it’s kind of redundancy. While in swift, struct and class have core difference, struct is value type and class is reference type, this is what I found unique for swift(up to my knowledge now), and thought that it’s for this reason, in swift, c++ interoperatability, c++ struct and class are both mapped to struct in swift, still swift struct and c++ class aren’t equivalent.
And in swift, thus comes ARC for Class.
In rust, struct
and impl
are seprated, while in swift, you can have methods defined inside struct.
And when it comes to c++, it’s awkwardly complicated, powerful, efficient.
Expressions, Statement, and semicolons
Functions and maybe Closure
1 | func foo(input val: Int) { |
1 | fn foo(s: String) { |
Enum
Option
1 | let some_number = Some(5); |
1 | var x: Int? = nil |
I’m not sure, but much thing beside for Option in Rust and Swift are same.
First when I saw, ?
, !
, ??
, try?
, try?
if let
, guard let
, in Swift Programmming Language, it’s makes me feel weird. I’ve now get used to it, and I thought this syntax is helpful and persures clarity.
Pattern Matching
- Rust is with match synatx
- Swift use switch/case
both with assocative value, and execustive match
Packages, Crates and Modules
Swift
In swift, we have swift package manager. We got Packages, targets and module is something your didn’t always talk about but used all the time.
One thing I like about this swift package manager is Package.swift that enable your to write swift directly in manifest.
1 | // swift-tools-version: 5.8 |
and you have import syntax
1 | import Foundation |
Rust
In rust, your have crago for Packages, crates and modules. You write cargo.toml for manifest.
and have syntax like
1 | use std::collections::HashMpa; |
C++
it’s like somewhat in c++
1 | using namespace std; |
and
1 |
|
in c/c++, get files into multiple files is something I don’t like, your need header and something iterative and replicatant.
Interlude
1 | let first = &v[0]; |
I didn’t releaize the problem with this code at first point, I’m far from being rusty. 🤕
Common Collections
Strings
Both Swift and Rust String are complicated because of Unicode and UTF-8/UTF-16 encoding, so unlike when you are coping with ASCII in C/C++, string indexing may not be as simple, but more power and multi-language friendly.
Array
Error Handling
Rust
In rust, you got
1 | enum Result<T, E> { |
it’s explicate enum, just like Option
, with functions like: .unwrap()
, .
expect(); Besides, you got
panic!, and
?` for Error propagation.
Let’s review some words in Rust and Swift
Rust | Swift |
---|---|
Cargo | Swift Package Manager |
crate | Target |
panic | fatalError |
trait | Protocol |
it seems rustaceans really like kind of naming. |
Swift
While in swift, you have got more some what jargon, keyword and syntax to know about. Optional is not really a part, but it’s something I found fit here.
First you got
1 | func functionThatThrows() -> throws Int { |
you have try
, throws
, throw
and rethrow
, combines with ?
, !
, ??
or without this postfix, to make a great number of combinations of easy to remember, intuitive and handy things.
1 | do { |
and some handy ones for optional, optional and error handling are something interconnection in swift.
1 | let val: Int? = 1 |
and another way to do error handling is just the programming crash.
for example some times you can write code let that but not recommanded.
1 | let val: Int? = nil |
and code run only for debug
1 | assert(1 == 0, "Only prints when debuging") |
you can see both Result
and Option
have mapping one to swift, but instead of explicitly using enum, swift introduces keywords to make it handy.
C++
C++ also have try, catch blocks and assert, static_assert. But not Optional, nullptr instead.
Generic & Trait, Generic & Protocols, Generic & Concept
Trait, Protocol are like interface in other languages, for example Java.
Core Difference of Rust and Swift Generics vs. C++ Generrics
let’s have a look at the code:
1 | // ❌ |
1 | // ❌ |
If you try to compile these two functions, you would get an error.
but in c++
1 | // ✅🧐 |
but in C++, it works.
The reason it doesn’t work is that in Rust, and Swift, >
is not garuranted to work on T
, the same is true for c++, but c++’s generic have maybe something like lazy evluation, so it’s not checkout until you write code that fill in some real concreate type in T
. It won’t cause error, but make troubles in developing. These we have
Concept in C++23
1 |
|
interlude
but I think it’s too late to add this feature, as long as it compiles without writing Concept, most programming won’t do the kind of stuff, and there are great bunch of legacy code in cxx. Besides, Rust and Swift comes with native Trait
and Protocol
and it doesn’t works only for Generic
but prevasive in language, thus, there’s no overhead for understanding. Concept
in cxx is like a bug fix or entending, that just bring more and more things to this language.
Now let’s refer to Python and type hinting,
1 | from typing import Dict |
but how many programers are using this feature? Just like for JavaScript and TypeScript, some times you must get off the legacy bundle and start somes from scratch.
Trait & Protocol
I will just list some usages of Trait Rust, as there’s a great deal of contents. And for swift, even more, as swift can be called as a Protocol Oriented Language
Define a trait, Define Protocol
1 | pub trait Summary { |
swift protocol and also define protocol access requirements. Remember properity with {get}
or {get set}
aren’t necessarily computed properity.
1 | protocol SomeProtocol { |
implementation and default implementation, conditional implementation
1 | impl Summary for NewsArticle { |
swift methods are normally defined inside struct, but can also be extended outside with extension
1 | struct someStrust: SomeProtocol, AnotherProtocol { |
it’s not inheritance, as still need to explicatedly implement for each struct rather than have methods and properity inherted from it’s parent.
with generics
as for code before, <
operate must be explicatly available, thus you write code like this:
1 | pub fn notify(item: &impl Summary) { |
1 | protocol Comparable { |
use as return type
1 | fn returns_summarizable(switch: bool) -> impl Summary { |
1 | func getLargest<T>(from items: [T] ) -> some T where T: Comparable { |
combination
1 | impl<T: Display + PartialOrd> Pair<T> { |
1 | protocol combinedProtocol: SomeProtocol, AnotherProtocol { |
Protocols can be inherated, which is infact combine and addition, but be carefully, as there can be problems like implementation conflictions. Anyway, compiler would get you notified.
and combines
1 | func wishHappyBirthday(to celebrator: Named & Aged) |
Generic and Lifetime in Rust
I haven’t got an soild understanding on this part.
Tests
I don’t know the most common way of doing test in cxx, make with cmake ctest.
In Rust, you test with and module marked #[cfg(test)], and in swift, you test with XCTest framework. XCTest I believe stands for Xcode Test, it does work without Xcode but got really terrible output sometimes.
Funtional Programming
I didn’t tell Procedural Programming and Functional Programming for a long time. 😣.
I first learn about Function Programming when learning python from CS61A with .map and .reduce.
Closures
Rust
1 | fn add_one_v1 (x: u32) -> u32 { x + 1 } |
Swift
1 | { (<#parameters#>) -> <#return type#> in |
the last one is Trailing closures which is really handy, espically with @resultBuilder
, in swift, you can explictly capture value by syntax.
1 | someFunctionWithEscapingClosure { [self] in x = 100 } |
and the type of closure is clear
1 | let x: (Int, Int) -> Bool = {$0 > $1} |
it’s handy to write type for a function as input and pass in a closure.
lambda in c++
1 | [capture-list](parameters) -> return-type { |
it also get closure like in c++, what not as easy to write and use.
Capture value
In rust, you need to worry about ownership and reference. In swift, closure it self is reference type, we haven’t yet talked about class and ARC in swift, but closure can cause problems with ARC.
both in swift and rust, functional programming codes looks simlar, while one comes with deep and shallow copy, anothor with fine grained control on reference. Funtional programming makes code concise and clear, and as swift and rust are both static typed, compiling programming, thanks to the developement of compiler in these years, the performance is guaranteed.
Smart Pointer, and ARC, RAII
class in swift
We haven’t introduced class in swift. There are languages that have struct only, and langauage have class only. In C++, you get both struct and class, but the only difference is the access level, I think it’s primarly for working with c and is infact some kind’s reduantly.
In swift, class has some core difference with struct, struct is value type in swift, class is reference type, and class have deinit, inhertance.
swift 5.9
swift 5.9 introduced c++ interoprablity, this changed that struct can’t have deinit.
you can now give a struct deinit by let comform to :~Copyable
this maybe be familar to c++ writters.
smart pointer
Both in rust and c++, you got smart pointers, and weak for reference cycle and break reference cycles.
RAII and ARC
In swift, you rarely use pointer directly as it’s unsafe, reference works with class and is implicate, but the class keyword should make you aware of it. I think it’s a gate that one start to understand swift. But ARC sometimes comes to problems with reference cycle as well and such program is easily created when using closure that captures class’s self.
Concurrency Support
Rust’s features on ownership and it’s integration with compiler’s check system.
And when it’s talking about Concurrency, Go is famous for it, I personally haven’t learn that language, but hear of it for it’s support for concurrency.
Rust’s Ownership module is the fundation of it’s concurrency support, and the left part to of the support isn’t in the language it self but in crates.
Swift on the other side bring’s some keyword for it.
C++ is a powerfully language that allows you to do many fine-grained control, I don’t if there’s language syntax level control on this, but I know many work you that you do with concurrency in C++ is using some specific libraries.
Object Oriented Programming
If a language must have inheritance to be an object-oriented language, then Rust is not one. The Rust programming langugage.
In swift, struct don’t directly have Inheritance by defination.
But wait, when we are talking about inheritance, as I remember learn Java, inheritance is something not easy to gasp and prone to make mistake, and do we really need them.
Protocol-Oriented Programming
Protocol-Oriented is as some level similar to Oriented Programming.
- Post title:Rust, Swift and C++
- Post author:Meqt
- Create time:2023-06-07 13:49:42
- Post link:https://meqtmac.github.io/2023/06/07/RustVsSwift/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.