Najlepsza odpowiedź
Zdecydowanie „Nie” dla Swift 1, 2, 3. Ale może tak dla Swift 4 . W każdym razie, nadal nie jestem zbyt pozytywnie nastawiony.
Zakładam, że rynkiem docelowym Rusta są programiści C / C ++.
Kluczową cechą Rusta jest ekstremalne bezpieczeństwo bez narzutów . Do tej pory Swift nie działa tutaj. Swift zawsze wiąże się z pewnym narzutem zarówno w przestrzeni, jak i czasie, gdy używasz typów ref. Jest to obowiązkowe i nieuniknione.
Narzut jest ważny, ponieważ samo „bezpieczeństwo” jest już zapewniane w wielu językach. Na przykład C #. Co moim zdaniem jest prawdziwym konkurentem Swifta. C # już zapewnia pewien poziom bezpieczeństwa. I już z powodzeniem zastąpiono C / C ++ w pewnym segmencie rynku, ale nie całkowicie, ponieważ wprowadza sporo narzutów. Zarówno w przestrzeni, jak iw czasie. Chociaż kompilator Swift może wyeliminować część kosztów związanych z RC, ale zależy to od szczęścia w optymalizacji. W jakiejś niefortunnej sytuacji koszty ogólne stają się ogromne.
A poziom bezpieczeństwa też się różni. To samo, co oba języki nie gwarantują żadnego wiszącego wskaźnika w bezpiecznym kontekście. Ale to wszystko, co może zapewnić Swift, i jest to bardzo słaba gwarancja w porównaniu z tym, co zapewnia Rust. Na poziomie zasobów typy referencyjne Swift mogą wyciekać w dowolnym momencie i zawsze wymagają ludzkiej opieki. Kompilator nie może wykryć cyklicznych odwołań. Swift pozwala również na nieograniczone współdzielenie zmiennej pamięci między wątkami (z powodu braku współbieżności języka), co oznacza brak bezpieczeństwa w wyścigu danych.
W przeciwieństwie do tego, unikalna własność Rusta zapewnia w pełni statyczną gwarancję braku wycieku zasobów. Żaden wyścig danych również nie jest gwarantowany statycznie.
To, co czułem podczas używania Swift przez ostatnie kilka lat, to to, że język nie jest naprawdę bezpieczny, jeśli chodzi o zarządzanie zasobami i wyścig danych. A obowiązkowe obciążenie RC jest naprawdę dużym problemem w kodzie krytycznym dla wydajności. Swift ogłasza wydajność typów wartości, ale w rzeczywistości zawsze musisz użyć w nim niektórych typów referencyjnych, aby bezpiecznie alokować w stercie. Swift reklamuje inteligentną elizję RC kompilatora, ale opiera się na szczęściu, więc nieporównywalnie gwarantowany zerowy koszt Rust.
Dlaczego bezpieczeństwo ma znaczenie? Ponieważ nie możesz być produktywny na polu minowym. Aby być produktywnym, musisz ograniczyć to, na czym Ci zależy. W Swift zawsze musisz dbać o cykle, wyścig danych i koszty ogólne, aby nie zostać zabitym, ponieważ nikt nie dba o ciebie. W Rust kompilator może i robi to za Ciebie. Po prostu zapominasz o (wielu) bezpieczeństwie i podążasz za kompilatorem, cokolwiek narzeka, wtedy jesteś bezpieczny. Podobnie jak użytkownicy języka GC nie przejmują się wiszącymi wskaźnikami.
Również determinizm ma znaczenie. Śledzenie czasu życia obiektu jest rzadko wymagane, ale czasami jest bardzo ważne. Swift RC zapewnia synchronizację „deinit”, ale ponieważ jest to współwłasność, czas śmierci jest zwykle bardzo niejasny. Taka synchronizacja w unikatowej własności jest względnie o wiele jaśniejsza niż RC.
Unikalna własność pomaga również w utrzymaniu, dodając adnotacje do odpowiedzialnego właściciela. Moim zdaniem zarządzanie jednym właścicielem jest znacznie łatwiejsze niż zarządzanie wieloma właścicielami. Właściwie to, co zawsze robię w Swift, to po prostu określanie niejawnego unikalnego właściciela i śledzenie go ręcznie według jakiejś konwencji. Czy nie byłoby miło, gdyby kompilator zrobił to za Ciebie?
Swift 4 planuje wprowadzić kilka nowych funkcji, takich jak unikalna własność, semantyka przenoszenia, model aktora i obsługa międzyoperacyjna w języku C ++. Ale nie jestem pewien, jak mogą zagwarantować poziom bezpieczeństwa Rusta dzięki funkcjom obecnej semantyki języka. Więc nadal nie jestem zbyt pozytywnie nastawiony do poziomu bezpieczeństwa Swifta. C ++ inter-op może być dużym punktem sprzedaży. W każdym razie jest to prawie jedyny powód, dla którego myślę, że Swift 4 może być potencjalnym konkurentem Rusta na rynku C / C ++.
Swift ma również zalety. Takich jak rozsądniejsza (moim zdaniem) konwencja nazewnictwa i jasna składnia (moim zdaniem), dedykowane IDE, gwarantowany rozwój i trwałość przez najbogatszego światowego zwolennika (ale to też wprowadza polityczny problem obsługiwanej platformy). Ogólnie rzecz biorąc, ma lepszy UI / UX, ale nadal bardziej pociąga mnie bezpieczeństwo Rusta i koncepcyjne piękno…
P.S. W rzeczywistości możliwe było utworzenie wiszącego wskaźnika we wczesnej wersji Swift 2.x przy użyciu tylko bezpiecznej konstrukcji, takiej jak `deinit` i słaby ref. Ale nie jestem pewien na teraz i w przyszłości.
P.S. 2. Wygląda na to, że załatali lukę. W Swift 3, jeśli spróbujesz zrobić słabe odniesienie w `deinit`, pojawi się wyjątek w czasie wykonywania.
Odpowiedź
Ostatnio czytałem o swift-3.x, ale ja Jestem fanem Rusta od jakiegoś czasu i * naprawdę * chcę, aby Rust odniósł sukces jako język systemowy.
Odpowiedź na twoje pytanie będzie warunkowa: tak, dlaczego? Dzieje się tak, ponieważ język szybki nakłada się na znaczną przestrzeń z rdzą w zakresie programowania aplikacji natywnych.Istnieje wyraźny kontrast między językami pod względem filozofii projektowania i przypadków użycia w programowaniu systemów (i niektórych przypadków użycia w czasie rzeczywistym)
Rust został zaprojektowany w oparciu o filozofię C ++ dla większości części, co sprawia, że możliwe do wykonania obliczeń o bardzo wysokiej wydajności i niesamowicie optymalizowalnych kompilatorów (nisza, z którą nie konkuruje wiele współczesnych języków)
- „Zero kosztów abstrakcji”
- To jest szczególnie ważne, gdy piszesz jądra lub podstawowe narzędzia, ponieważ muszą być zoptymalizowane do maksymalnego możliwego poziomu, aby uzyskać ostatnią część wydajności.
- W szybkim tempie możesz prawdopodobnie wykonać większość optymalizacji, ale nie wszystkie. jest barierą językową dla ilości optymalizacji, którą można osiągnąć (na przykład zgaduję, że możemy bezpiecznie założyć, że większość zliczania referencji jest atomowa w szybkim tempie, ale w rdzeniu możesz wybierać między typami Rc i Arc, więc nie płać za czego nie używasz).
- „Model wskaźnika Rusta”
- Program Rust Są zaprojektowane tak, aby wyeliminować większość źródeł awarii z twojego kodu poprzez semantykę własności, wypożyczania i przenoszenia, dlatego też weryfikuje statycznie, że każdy zasób ma tylko jednego unikalnego właściciela w danym momencie. Ułatwia to również pracę w dwóch z poniższych przypadków użycia.
- Jak wyodrębnić części programu, które mogą ulec awarii (niebezpieczne).
- Jak zapewnić bezpieczną współbieżność podczas pisania kodu
- Swift jest znacznie bardziej podobny do C ++ pod tym względem, ponieważ po prostu udostępnia programiście silne (shared\_ptr), słabe (słabe\_ptr) i nieposiadane wskaźniki (intrusive\_ptr) i daje mu kontrolę nad (ab) użyciem ich w ich kod, więc zdecydowanie lepsza kontrola niż Java, ale z pewnością mniejsze bezpieczeństwo
- „Wyliczenia”
- Rust ma bogate wyliczenia, które są podobne do ADT w Haskell (choć nie tak potężne), ale mimo to włącz piękny projekt maszyn skończonych (FSM), jeśli myślisz o C, które ma bardzo słabe wsparcie dla pisania FSM.
- Swift ma również piękne wyliczenia podobne do Javy, które myślę, że jest znacznie potężniejsze, ponieważ możemy zdefiniować zachowanie dla wyliczeń.
- „Zamknięcia” – to jedyna cecha, która odróżnia wszystkie języki współczesne od języków archaicznych. Zamknięcia obsługujące zarówno Rust, jak i Swift, ale model rdzy umożliwia wnioskowanie o własności zmiennych „zamkniętych”, a tym samym zapewnia bezpieczeństwo. Z drugiej strony zamknięcia Swift mogą sprawić kilka niespodzianek nawet dla doświadczonych programistów.
- Problemy z Rustem
- Bardzo proste struktury danych, takie jak listy podwójnie połączone, nie mogą istnieć w rdzeniu tylko dlatego, że semantyki własności (jesteśmy zmuszeni używać Rc / Arc dla tej prostej struktury danych) to irytuje niektórych ludzi.
- Zgodnie z doświadczeniem programistycznym, gdy istnieje funkcja w popularnym języku, ludzie będą nadużywać ich, w Rust niebezpieczne bloki są zdecydowanie podatne na nadużycia dla ludzi, którzy nie chcą walczyć z narzędziem do sprawdzania wypożyczeń, co niestety stanowi duży procent
- Naruszenia niezmienności w standardowej bibliotece, jeśli nie trywialny kod musi być napisany w Rust, musimy mieć typy danych, takie jak Cell / RefCell, które mogłyby być technicznie używane jako backdoory przeciwko silnemu bezpieczeństwu, które wydaje się zapewniać język. Powiedziawszy, że biblioteka zapewnia wiele prymitywów bezpieczeństwa podczas korzystania z tych typów danych, więc nie strzelamy sobie w stopę.
- Wreszcie Rust wydaje się przyznać, że będąc bezpieczniejszym niż C ++, niektóre z znienawidzone funkcje C ++ również muszą zostać włączone, abyśmy mogli pozwolić na adopcję i umożliwić ludziom pisanie nietrywialnego kodu. To smutne, ale niestety też prawda.
- Problemy z Swift
- Wszechobecne używanie ARC wszędzie – co jest pogwałceniem zasady „nie płacisz za to, czego nie robisz użyj ”filozofii w C ++ (może być rozwiązana w swift 5.x (patrz [swift-evolution] RFC: Preventing Retain Cycles (Memory Ownership Model) )
- Brak bardzo łatwych w użyciu asynchronicznych prymitywów live async / await / coroutines (co jest punktem sprzedaży dla języków takich jak go), może być szybki. 5.x rozwiąże ten problem
- Czasami „class ”Deklaracje mogą niepotrzebnie zmusić Cię do korzystania z typów referencyjnych, w których faktycznie możesz preferować typ wartości (struct)
- Cechy w Rust jest technicznie (w większości przypadków) lepszym rozwiązaniem dla 3 różnych szybkich jednostek (rozszerzeń, protokołów i dziedziczenie)
Więc myślę, że jest zdecydowanie nisza dla szybkiego zajmowania się, ludzie, którzy są dobrymi programistami C ++, mogą szybko dostać się do Swift / Rust. Ale myślę, że Swift będzie zyskiwał większą przyczepność z programiści aplikacji i Rust z programistami systemowymi. Ich nisze będą nadal istnieć pomimo znacznego nakładania się.