Swift okiem programisty C#

29

Stało się. Planowałem to od dawna: cały dzień w kodzie po baaardzo długiej przerwie. Bałem się, że się po prostu porzygam, potnę żyły, popłaczę, roztrzaskam komputer i tyle tego będzie. A tymczasem…

Background

Swoje programistyczne zęby zjadłem na platformie Microsoft .NET. Startowałem, gdy .NET się rodził i przez kilkanaście lat byliśmy swoimi najlepszymi przyjaciółmi. I najbardziej zagorzałymi wrogami.

Z Visual Studio – czyli dedykowanym dla .NET IDE od Microsoftu – podobnie. Raz czule kochałem, raz zajadle nienawidziłem. Z przewagą tego drugiego.

Po długiej przerwie od zarobkowego programowania – do którego zresztą wracać nie zamierzam – zaczęło mi się wreszcie… chcieć. Zatęskniłem. Wiedziałem jednak, że jeśli wskoczę do tej samej rzeki, to wrócą te same frustracje i wszystkie najgorsze wspomnienia. Musiało to być coś zupełnie innego, nowego.

Stanęło na IOS. Rok temu kupiłem iphone, kilka miesięcy później: maca. Czemu by nie pokodować na to? Nigdy nie robiłem nic mobilnego, nigdy nawet nie tknąłem Objective-C ani Swift. No to… siup, w nieznane!

Killing me SWIFTly with Xcode 😎

I tak oto teraz, po jednym dniu zabawy, chcę zaprezentować swoje dotychczasowe wrażenia. Niby jeden dzień to za mało, żeby mieć cokolwiek interesującego do powiedzenia. Może tak, może nie, może pprrff a kto to wie. Jedziemy.

Mój setup:

  • Swift 4
  • Xcode 9.2
  • MacOS High Sierra 10.13.3
  • MacBook Pro (Retina, 13-inch, Early 2015)
  • 2,9 GHz Intel Core i5

Uwaga: poniższe obserwacje mogą być niedokładne, a opinie: zdecydowanie subiektywne (jak to opinie). Sprostowania w komentarzach mile widziane. Punktem wyjścia był dla mnie oficjalny dokument na stronie Apple: Start Developing iOS Apps (Swift).

To jest pierwszy z – jeśli dobrze pójdzie – wieeelu postów. Dzisiaj skupię się tylko na pierwszych wrażeniach z języka. O narzędziach już nie dałem rady się rozpisać. Zapraszam do zapisania się na newsletter, żeby nie przegapić kolejnych odcinków!

Język Swift

Na pierwszy rzut oka – wygląda czytelnie, wygląda znajomo. Średniki są opcjonalne. Tak samo nawiasy w ifach i pętlach. Osobiście nie lubię, gdy coś jest opcjonalne – ale są gusta i guściki.

Ciekawi koncept braku, znanej wszak z wielu innych języków, funkcji Main(). Po prostu to, co napisane w global scope, zostaje wykonane. W sumie: fajny pomysł!

Zmienne

Mamy dwa rodzaje deklaracji zmiennych: var i let. Z tym, że let to nie zmienna, a… nie, nie stała. To “immutable value“, odpowiednik “readonly” z C#, czyli nie musimy nadawać wartości w momencie deklaracji. Możemy to zrobić w konstruktorze. Raz.

Dziwi nieco brak niejawnej konwersji (implicit conversion), ale z tego co czytałem, ma to być język “maksymalnie bezpieczny”. Więc: okej, approved, będziemy rzutować ręcznie. Może to i dobrze? W C# możliwość niejawnej konwersji, a szczególnie nadpisania jej operatorów, dawała pole do popisu programistycznej fantazji, ale… nieraz ugryzła w tyłek.

Jednak w przypadku braku niejawnej konwersji od razu pojawia się pytanie: a co z komponowaniem tekstu? Wszystko trzeba będzie z palca rzutować na stringi? Na szczęście: nie.

"tekst \(zmienna lub wyrażenie) dalszy tekst"

… i gra muzyka. Uff.

Tablice i słowniki

Standardowo można zadeklarować tablicę: [1,2,3].

Słownik: tak samo: [“key1”: “value1”, “key2”: “value2”]. Swift sam sobie wykona “type inference“.

Jeśli typ tablicy lub słownika można wydedukować z kontekstu, to wystarczy napisać [] albo [:], nie trzeba powtarzać nazw typów.

A pusta tablica? Proszę: [String](). Słownik? Proszę: [String:Int](). Easy peasy.

NULL vs NIL!

Chyba w .NET 2.0 pojawiło się Nullable. Od tej pory można było wstawić nulla nawet pod value type. W Swift dostajemy do dyspozycji “optional variable” – podobny koncept z taką samą składnią: znakiem zapytania po nazwie typu. Tyle że w Swift tyczy się to zarówno klas, jak i struktur.

Coś podobnego – czyli rozszerzenie koncepcji “ochrony przed nullem“, by walczyć z “billion-dollar mistake” – szykuje się w kolejnych wersjach C#. Więcej o “nullable referencje types” w C# można poczytać chociażby tutaj czy tutaj.

Swift daje możliwość zastosowania dodatkowo jednego ciekawego myku: wykrzyknika zamiast znaku zapytania. Wykrzyknik po nazwie typu oznacza: “implicitly unwrapped optional variable“. Ktoś z doświadczeniem w programowaniu od razu chwyci, o co chodzi, a jak to szkoły programowania tłumaczą totalnym świeżakom to… sam jestem bardzo ciekaw.

Podobnie jak w C#, tak i tutaj mamy do dyspozycji “coalesce operator” (składnia ta sama: dwa znaki zapytania).

Funkcje

Standard:

func name (arg_name1: arg_type1, arg_name2: arg_type2) -> return_type

i po krzyku.

Możemy mieć także zagnieżdżone funkcje. Możemy i anonimowe funkcje. Może funkcje tworzyć, zwracać, robić cuda wianki. I to wszystko bardzo ładnie, zwięźle wygląda.

func create_adder() -> ((Int, Int) -> Int){
    return { $0+$1 }
}
create_adder()(2,13)

W tym przypadku nie musimy nawet nazywać parametrów, odwołujemy się do nich po indeksach. Dla kilkulinijkowców: werynajs!

ALE!

Tutaj pojawia się moja pierwsza wątpliwość: tzw. argument labels. Gdy definiujemy funkcję, to nadajemy nazwy parametrom – naturalna sprawa:

func add(x: Int, y: Int) -> Int

Jednak domyślnie musimy powtórzyć tę nazwę podczas wywołania funkcji:

add(x: 1, y: 2)

To autor funkcji – a nie jej “klient” – decyduje o tym, czy nazwa parametru ma zostać powtórzona przy argumencie. Można tę konieczność wyłączyć właśnie w deklaracji funkcji, dodając znak _ przed parametrem:

func add(_ x: Int, _ y: Int) -> Int

Wtedy mógłbym wywołać funkcję tak:

add(1, 2)

Nie podoba mi się to. Ale to nie wszystko, bo parametrowi można nadać jeszcze jedną nazwę. Tę, która będzie użyta przy wywołaniu. Zobaczcie:

func add(arg1 x: Int, arg2 y: Int) -> Int

Wywołując funkcję, muszę posłużyć się tymi dodatkowymi nazwami:

func add(arg1: 1, arg2: 2)

Wątpliwości co do tego ficzera towarzyszyły mi przez cały dzień. I nie zostały rozwiane. Nawet po lekturze tego dedykowanego mu kawałka dokumentacji. Moim zdaniem taki lukier składniowy dobrze jest “móc włączyć”, a nie “musieć wyłączyć”.

I jeszcze o funkcjach, good news! W Swift funkcje domyślnie są wirtualne, jak w Javie! Więc można je nadpisywać! Nie trzeba ich dodatkowo oznaczać jako “virtual” jak w C#. A to jedna z moich najbardziej znielubianych cech C#. (Uwaga: nie wnikałem jeszcze w mechanizm method dispatch w Swift, więc określenie “wirtualne” może być na wyrost; chodzi o koncepcję, nie o konkretną implementację)

Ctor

Co się rzuciło w oczy: konstruktor nie nazywa się tak jak typ. Kontruktor nazywa się “init”. Ma to sens, bo niezależnie od nazwy typu, wszędzie wygląda tak samo.

Co mnie zdziwiło to destruktor nazwany “deinit“. Jakoś głupio to wygląda. Chociaż nie wiem, jak to nazwać inaczej.

“OnPropertyChanged” – pseudo

Property jak property – getter i setter, normalna sprawa. Ale jest coś naprawdę ciekawego: można w osobnych blokach dodać kod, który wykona się PRZED i PO zmianie wartości. Obadajcie:

class WillDidSet {
    var prop: Int {
        willSet {
            print ("WILL - before changing \(prop) to \(newValue)")
        }
        didSet{
            print ("DID - after changing \(oldValue) to \(prop)")
        }
    }
    
    init(){
        prop = 44
    }
}

Można ten sam efekt osiągnąć w C#, pisząc po prostu ciało settera, ale… cóż, tutaj z jakiegoś powodu zrobiono to w ten, a nie inny, sposób. Nie mam jeszcze opinii czy to fajne czy nie, ale na pewno interesujące.

Enumy

Wyglądają na bardziej rozbudowane, niż w C#. Choćby przez to, że mogą mieć metody! To ograniczenie w C# obchodziło się używając extension methods.

Dodatkowo w Swift enum ma property “rawValue”. W C# dobieraliśmy się do tego poprzez rzutowanie. I jeszcze jedna ciekawostka: enumy w Swift mogą… nie mieć typu! Wówczas nie będą też miały rawValue.

Nie ogarniam jeszcze konsekwencji takich możliwości, ale wygląda to bardzo interesująco.

W ogóle enumy w Swift to mechanizm “o wielu dnach” ;) i z chęcią będę kolejne tajemnice odkrywał.

Interfejsy

W Swift nazywają się Protocols – protokołami. Makes sense!

Są to takie same kontrakty jak w C#, tyle że… nie do końca takie same.

Pierwsza różnica: na dowolny parametr można nałożyć ograniczenie “musi implementować wiele interfejsów“. W C# w takiej sytuacji stworzyłoby się dodatkowy interfejs, implementujący wszystkie wymagane. A tutaj proszę bardzo:

func gimmeParamWith2Protocols(arg: FirstProtocol & AnotherProtocol)

Czy się przydaje? Ciężko powiedzieć. Ale zapada w pamięć.

A druga różnica, nawet ważniejsza: w swiftowym protokole można zadeklarować metody… opcjonalne! Nie wniknąłem jeszcze jak to działa, ale już w najprostszej aplikacji na ajfona natknąłem się na ten mechanizm. Czy gdzieś w protokole siedzi domyślna implementacja, czy jest to rozwiązywane przez extension methods, czy ma to jakieś korzenie w Objective-C… ciężko powiedzieć. Nie rozumiem też jeszcze sensu takiego mechanizmu – bo co to za kontrakt, który nie musi być do końca spełniony? – ale pewnie jakiś jest.

Extensions

Już kilka razy pojawiło się określenie “extension methods“. Good news: tak, tutaj też są. I implementuje się je podobnie jak w C#.

Bardzo dobrze, bo ten mechanizm przydaje się często i otwiera dużo ciekawych możliwości.

Wyjątki

Wyjątkiem jest wszystko, co implementuje protokół Error. Może to być klasa, struktura, albo… ten tajemniczy enum!

Jest to dla mnie temat do dalszego researchu: dlaczego rekomenduje się użycie enumów do impelementacji wyjątków, zamiast dla każdego nowego wyjątku, jak Bozia w Redmond nakazała, zrobić klaskę?

Powiew świeżości można poczuć patrząc na realizację koncepcji “checked exceptions” (jak w Javie). A raczej jej braku (jak w C#). A raczej… jeszcze inaczej!

Tutaj funkcja nie musi deklarować typów rzucanych wyjątków. Ale jeśli COŚ rzuca, to trzeba ją udekorować dodatkowym słowem kluczowym “throws“.

Interesująca jest też zmiana klasycznego zestawu try/catch/finally. Tutaj mam blok do{}, a po nim catch{}. I dopiero w bloku do, przy każdej instrukcji rzucającej potencjalnie wyjątek, dopisujemy try. Nie wiem jeszcze co to daje i dlaczego ma być lepsze od standardowego try/catch, ale rzuca się w oczy.

Defer

Po raz pierwszy zobaczyłem taki koncept w GO. Na czym polega? O, najlepiej będzie pokazać na przykładzie:

enum FileError: Error{
    case NotExists
}
 
func writeFile(_ fileName: String) throws {
    print("opening file \(fileName)")
    defer {
        print("closing file \(fileName)")
    }
    print ("writing to file \(fileName)")
    throw FileError.NotExists
}

Sekcja zamykająca plik wykona się na samym końcu funkcji… nawet jeśli poleci wyjątek. Możemy zatem ładnie, obok siebie, umieścić utworzenie i zwolnienie zasobów bez pamiętania, żeby je zwolnić na sam koniec i nawet w przypadku wyjątku.

Pomocne.

I jestem pewny, że – tak jak using i IDisposable w C# – można to jakoś fajnie NADuzyć i wykorzystać do ciekawych, niekoniecznie zgodnych w pierwotnym zamierzeniem, celów ;).

Generics

Są – a jakże! I wydaje się, że mają się dobrze. Bo i jak mają się mieć?

Poruszam ich temat tylko dlatego, że… enumy mogą być generyczne!! Jak wspominałem, nie do końca te enumy jeszcze ogarniam

C.D.N.

Planowałem rozpisać się dzisiaj jeszcze o wrażeniach z pracy z Xcode, wdrożeniem (udanym lub nie) swojej pierwszej aplikacji itede, ale… ale już nie dam rady.

Więc do przeczytania wkrótce!

Póki co – jestem bardzo zadowolony. Nie zniechęciłem się, wręcz przeciwnie. Po raz pierwszy od dawna cały dzień spędzony w kodzie dał mi naprawdę dużo radości. I chcę więcej.

Dev4life, piona!

Nie przegap kolejnych postów!

Dołącz do ponad 9000 programistów w devstyle newsletter!

Tym samym wyrażasz zgodę na otrzymanie informacji marketingowych z devstyle.pl (doh...). Powered by ConvertKit
Share.

About Author

Programista, trener, prelegent, pasjonat, blogger. Autor podcasta programistycznego: DevTalk.pl. Jeden z liderów Białostockiej Grupy .NET i współorganizator konferencji Programistok. Od 2008 Microsoft MVP w kategorii .NET. Więcej informacji znajdziesz na stronie O autorze. Napisz do mnie ze strony Kontakt. Dodatkowo: Twitter, Facebook, YouTube.

29 Comments

  1. Piotr Miron on

    Też niedawno zacząłem naukę Swifta – wspomagam się trochę kursem z Udemy, całkiem niezłym, swoją drogą. Mam też spostrzeżenie dotyczące budowania apki na własnym urządzeniu – limit darmowych buildów wynosi 10, potem trzeba:
    a) zdać się na emulator, który mocno obciąża procesor
    b) kupić konto deweloperskie Apple (100$/rok)
    c) stworzyć nowe konto iCloud (co 10 buildów)

    Nie wiem jakie uzasadnienie ma te ograniczenie.

  2. Nie ma limitów buildów jednej aplikacji na urządzeniu. Przy darmowym dev koncie jest tylko limit zainstalowanych aplikacji na jednym urządzeniu, wystarczy odinstalować niepotrzebne.

    • Piotr Miron on

      Rzeczywiście, wystarczy odinstalować apke :O spotkałem się ze ścianą i za szybko wyciągnąłem wnioski :)

  3. A czy Xcode radzi już sobie z refaktorem kodu swiftowego? Rok temu jak walczyłam przy ‘Daj się poznać’ nazwy zmiennych trzeba było dobrze przemyśleć albo korzystać z metody find and replace . Osobiście dla mnie najzabawniejszym odkryciem było brak operatora %. W swifcie trzeba się posiłkować baaaardzo długim truncatingRemainder .

    • No właśnie tej części nie dałem rady opisać. Niby może “wszystko”, ale w swift wygląda mi to po prostu na edytor tekstu. Nawet “rename” nie znalazłem… ale nie szukałem zbyt mocno.

      • Od wersji 9 dodano obsługę refaktoru kodu Swiftowego. Z własnego doświadczenia, jakoś to sobie radzi ;)

  4. UnwrappedOptional on

    Dobry wpis! Czekam na następne! Trochę grammar nazi, ale pisze się “Xcode” zamiast “XCode”

  5. Z tym nadpisywaniem funkcji to prawda w Swift i ObjC wszystko jest virutalne bo koncepcja jezyka jest jak w C# i JAVA czyli jest refleksja. Nie mozna jednak po prostu nadpisac trzeba uzyc slowka override albo method swizzlingu ;)

  6. Jak klasa implementuje 2 interfejsy to ok, ale jak funkcja wymaga implementacji dwóch interfejsów od klasy, to podejrzewałbym tą funkcję o naruszanie dobrych zasad (conajmniej SRP). Szczerze powiedziawszy potrafię sobie wyobrazić to tylko w funkcji agregującej wywołania innych funkcji.

  7. Swift wydaje się bardzo podobny do mojej ukochanej Scali, myślę że również się skuszę.

  8. Chciałbym poznać Twoją opinię na temat “czarnej strony IDE”… właściwie to czarnego tła i jasnej czcionki. Teraz wszyscy (przynajmniej mam takie wrażenie) używają ciemnego stylu i zaczęło mnie to dobijać. Czy ja jestem jakiś staroświecki czy co? Skończyłem studia 11 lat temu i od tamtego czasu zawsze używałem jasnego stylu, no może z wyjątkiem cmd. Jakiś 2 miesiące temu coś mnie tknęło i przełączyłem VS na ciemny styl.. BUM.. jakby mój mózg się wyłączył, nie umiałem się połapać we własnym kodzie. Ostatnio jednak, mój kumpel, który siedzi za mną, przełączył w NetBeansie styl na ciemny (jest trochę jaśniejszy niż w VS). Nie.. no.. nie będę gorszy, też przełączyłem na ciemny i od 2 tygodni też mam. Wydaje mi się że jest całkiem wporzo.
    Jakiego Ty stylu używasz i co o tym myślisz?
    Jak Ci się zechce to poopowiadaj na snapie albo we vlogu.

    • Ja bardzo lubię ciemne motywy i przez lata ich używałem. ALE! Z czasem musiałem się przyzwyczaić do częstych zmian sprzętu/środowisk/wirtualek/formatów. Wtedy postanowiłem że będę zawsze pracował na domyślnych ustawieniach wszystkiego, żeby nie konfigurować wszędzie wszystkiego od nowa. Wróciłem do jasnego szablonu i się okazało że tak naprawdę na dłuższą metę to nie ma znaczenia.
      Wyjątkiem jest kod na prezentacjach: tam moim zdaniem ZAWSZE powinno się używać jasnego theme.

  9. Pingback: Xcode. Pierwsze starcie. | devstyle.pl

  10. Pamiętaj, że mimo, że generics mogą wyglądać dobrze, to w protokołach masz jest w formie upośledzonej – protokoły (protocols – interfejsy z Javy, w C# nie wiem jak to się zwie) – associatedtype.

    Zajrzyj do “Associated Types” pod: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html#//apple_ref/doc/uid/TP40014097-CH26-ID179.

    Zgrzyt się zaczyna jak chcesz żenić associatedtypes z generics – wtedy możliwe, że będziesz musiał usuwać typy:
    https://medium.com/@NilStack/swift-world-type-erasure-5b720bc0318a

  11. Dzięki Maćku, że napisałeś tego posta. Dzięki niemu wiem już na 100%, że nie chcę się nawet ubabrać tym Swiftem czy Xcodem (to z kolei z drugiego postu).

    Moje komentarzeL
    – brak jawnej konwersji dyskusyjny, choć mógłbym łyknąć.
    – implicitly unwrapped optional variable – że kufaWhatDaFackCO ??? To chyba po to, żeby “Seniorzy” mogli się pastwić na juniorach. Complete BS! Walkę z NULLem absolutnie przyjmuję, a tu takie potworki…
    – argument labels – no bez jaj! Jeszcze labele dla nazwy funkcji/metody zróbmy. Bzdura.
    – willSet, didSet – ciekawe, nie powiem. Pilnuje, że faktycznie jest to setter, a nie dziwna funkcja.
    – Enumy bez typu – brzmi dziwnie, ale kto wie.
    – Metody opcjonalne w interfejsach/protokołach to nieporozumienie, chyba, że mowa o domyślnych implementacjach
    – defer – najgorsza z wymienionych rzeczy. Źródło masy błędów i nieczytelnego kodu. Powodzenia w debuggowaniu ;-)

    Jeśli to jest ten super język, który zastąpił beznadziejne ObjectiveC (bronione przez FanBojów do końca), to chyba podziękuję.

    C# jest bardzo dobrym językiem, który wyprzedził Javą już wiele lat temu. A dla tych, którym M$ nie pasi, pozostaje chyba wsiąść na Pythona. Nie jest do wszystkiego (jeszcze?) ale łatwy i dość przyjemny. Zastosowań rośnie z każdym miesiącem.

    • No niepoprzestawajmy tylko na pythonie. Z wysokopoziomowych języków pod JVM jest jeszcze Kotlin, Scala. Kotlin ma nawet oficjalne wsparcie od Google, bo można pisać aplikację pod Androida i w dodatku oba te języki ładnie integrują się z ekosystemem Javy.

      • Tak, słyszałem niezłe opinie o Kotlinie. Byłoby ciekawie gdyby zaczął wypierać Javę tak jak Swift wyparł ObjectiveC.

        O ile lubię języki funkcyjne i Scala jest ciekawa, to jednak nie zdobywa tak wielkiej popularności, bo jest to dość trudny paradygmat, zwłaszcza dla mniej doświadczonych. Osobiście wolę podejście dodawania do popularnego języka elementów programowania funkcyjnego, np. polimorfizm parametryczny, notacja lambda, inferencja typów, dopasowanie wzorców czy funkcje wyższych rzędów.

    • Dzięki Tomasz, że napisałeś tego posta. Dzięki niemu wiem już na 100%, że jesteś osobą, która lubi gadać o czymś o czym nie ma pojęcia. W końcu ile może wiedzieć ktoś kto nawet nie spróbował. Wygląda to jak pewnego trzymanie się swojego do końca i strach przed czymś nowym, ale cóż! Lepiej nie spróbować czegoś nowego i mieć klapki na oczach całe życie, a wydawać by się mogło, że programiści to ludzie z elastycznym umysłem.

      No, ale dobrze, wystarczy tej uszczypliwości, każdemu się zdarza coś za szybko ocenić, jako, że dyskusje są bardzo rozwijające, zwłaszcza z osobami co mają różne zdania, bo można do czegoś sensownego dojść myślę, że i ja napiszę coś od siebie o Swift, gdyż sobie od 2 lat już w nim piszę.

      Początki takie piękne były, gdy zobaczyłem te Optionale i to wszystko, pomyślałem What The Fuck, po co to komu, lubią utrudniać życie programistom. No cóż, brak doświadczenia z nullami zrobił swoje. Były też te strasznie implicitly unwrapped optional variables! No może nie takie straszne, bo po kilku odpaleniach Xcode’a już się sam dowiedziałem o co z tym chodzi. A seniorzy się pastwili nade mną tak strasznie… Powiedzieli mi, że używa się tego na zmiennych opcjonalnych, gdy mamy pewność, że nie będzie nullem w tym miejscu! Wow! Wielka filozofia. No niestety wielka, bo musiałem parę razy odpalić program i mi się wysypać bym zobaczył o co w tym chodzi.

      Były też jakieś śmieszne guardy, po co to komu jak są cudowne ify.

      A te argumenty w funkcjach? No po prostu po co tego tyle, jaki w tym jest cel.

      No cóż, niestety, a może i stety, bo jednak człowiek inteligentny raczej czegoś dotknie zanim oceni trochę czasu potrzeba było by zrozumieć po co niektóre rzeczy powstały.

      O tym dlaczego niejawnej konwersji nie ma to chyba filozofii wielkiej, zwyczajnie dla bezpieczeństwa. Jasne ktoś może powiedzieć, że łatwiej i wygodniej byłoby jakby była dopuszczona, no oczywiście, że wygodniej, niestety wygodnictwo nie zawsze jest dobre, bo tym sposobem możemy sobie wylądować w JavaScript i po co się przejmować jakimiś typami ;-)

      Co do implicitly unwrapped optional variable to człowiek po godzinie bawienia się załapie o co chodzi i zrozumie. Jasne świeżakom ciężko wytłumaczyć, nie dlatego, że jest to jakiś dziwny mechanizm, tylko bardziej dlatego, że początkujący nie mają pojęcia o nullach, sam zresztą tak miałem. A może nazwa taka przerażająca? Proszę w każdym języku jakaś taka perełka się znajdzie.

      Co do samego zastosowania, no cóż, po tych dwóch latach uważam, że są to bardzo skrajne przypadki, gdzie się to przydaje. Rzadko kiedy się daje wykrzykniki, bo bardzo łatwo o crash wtedy i dużo częściej się używa tzw Conditional Binding.

      Co do guardów też po dłuższym czasie zauważyłem, że naprawdę się przydają i lepiej się to czyta jak i w przeciwieństwie do ifów nie powodują zagnieżdżeń.

      Dla przykładu mamy funkcję z argumentem x typu Int, gdy x będzie zero to nie chcemy by się dalszy kod wywoływał, w przypadku ifa napiszemy if x == 0 { return }.

      W przypadku guarda napiszemy guard x != 0 else { return }

      Z mojego punktu widzenia dużo naturalniej się czyta, gdy mówimy jeśli x różny od 0 przejdź dalej niż gdy podajemy warunek zakończenia funkcji.

      Co do tych nieszczęsnych argumentów w funkcji to jest akurat to cudowne, gdy właściwie jest to coś za co najbardziej lubię Swift, a dla innych jest to czarna magia.

      Teksty typu “Jeszcze labele dla nazwy funkcji/metody zróbmy” uważam za słabe popadanie w skrajności, by tylko iść w upartym przekonaniu o swoje, że to jest złe, chore i niedobre.

      Cóż, jako, że programowanie skupia się teraz na czytelnym kodzie i by jak najbardziej przypominało to język naturalny to zostały wymyślone etykiety dla argumentów, bo moim zdaniem zdecydowanie lepiej się czyta funkcję createDirectory(at: url, withIntermediateDirectories: true), niż jakąś funkcję typu createDirectory(url, true).
      Oczywiście jak komuś nie przeszkadza to, że wywołuje funkcję x, która przyjmuje 4 boole i na pierwszy rzut oka nie wiadomo który za co jest odpowiedzialny to słabo, ale wiadomo Wy jesteście do tego przyzwyczajeni, ja też byłem, a później poznałem coś nowego, byłem negatywnie nastawiony, a czas pokazał jednak, że jest to lepsze. Teraz siadam przy innych językach i nie ukrywam, że trochę jest to niekomfortowe, gdy na pierwszy rzut oka, nie wiem dokładnie co niektóre argumenty funkcji oznaczają. Niby można się przed tym zabezpieczać, przypisać wartości do zmiennych i by to miało jakiś sens, tylko dlaczego ja mam walczyć z tym, by kod był czytelny, skoro sam język daje mi taką możliwość i dba o to?

      Ale nie będę się tak rozpisywał, myślę, że zostawię pole do popisu dla ewentualnej krytyki lub dalszych pytań czy wątpliwości ;-)

      • Panie Macieju! Jeśli chodzi o Pana post to oczywiście nie mam nic do zarzucenia, jest naprawdę dobrze napisany. Mój post odnosił się do Pana Tomasza, bo nie ukrywam, że ocieka w moim odczuciu trochę zamkniętym umysłem na coś nowego oraz ignorancją.

        Dziękuje bardzo za link i przepraszam jeśli mój post był nie odpowiedni lub za ostry.

  12. Pingback: "Swift okiem programisty C#" okiem programisty Swift | devstyle.pl

  13. Tak. Tak. Każdy kto wyraża swoje opinie niepozytywne o Swift to ignorant o zamkniętym umyśle. Popisałeś się :)

  14. Pingback: Raport Finansowy: marzec 2018 | devstyle.pl