Swift (programozási nyelv)

A Wikipédiából, a szabad enciklopédiából

A Swift egy magas szintű, általános célú, többparadigmás rendszer- és alkalmazásprogramozási nyelv, amelyet az Apple cég fejleszt.

Az eleinte tulajdonolt (proprietary) szoftverként terjesztett, zárt forráskódú Swiftet elsősorban az iOS, OS X, watchOS és tvOS platformokra való alkalmazásfejlesztés céljából hozták létre. 2015. december 3. óta a Swift fordítóprogram (compiler), a Swift standard library, illetve néhány más kiegészítő program és könyvtár is szabad szoftverként terjeszthető, nyílt forráskódú, a fejlesztés a GitHub-on, nyilvánosan folyik.[1] A szabad szoftverré tétellel egyidőben az Apple kiadta a Swift fejlesztői környezet GNU/Linux disztribúciókon futtatható bináris csomagjait is.[2] Ez a kiadás természetesen nem tartalmazza az Xcode IDE-t és a Cocoa valamint Cocoa Touch API-kat, csak a parancssoros interfésszel (CLI) rendelkező fordítóprogramot, REPL-t és a standard könyvtárat.

A nyelv fejlődését, habár 2010 óta áll az Apple fejlesztése alatt, szabad szoftverré tétele óta jelentős részben befolyásolta a kialakuló fejlesztői közösség. Ezt a tendenciát az Apple aktívan támogatja, s a fejlesztői közösségnek a GitHub-on, levelezőlistákon és egyéb fórumokon nagymértékű beleszólást enged a nyelv jövőjébe.

Története[szerkesztés]

A Swift fejlesztését még 2010-ben kezdte el Chris Lattner, az LLVM projekt elsődleges szerzője és vezetője. A nyelv eleinte még Apple-ös mércével mérve is szinte teljes titokban készült. A Swiftet az Apple évente megrendezett fejlesztői konferenciáján, a WWDC-n mutatták be 2014 június 2-án. A nyelv bétaverzióját ekkor rögtön elérhetővé is tették a regisztrált fejlesztőknek, csakúgy, mint a hozzá tartozó bevezető leírást, amelynek a címe: "The Swift Programming Language" (A Swift programozási nyelv).

A Swift 1.0 verziója 2014. szeptember 9-én jelent meg, az Xcode fejlesztői környezet 6.0 GM kiadásával együtt. Ezt rövid idő múlva, 2014. október 22-én követte az 1.1 változat az Xcode 6.1 részeként, majd az 1.2, 2015. április 8-án, az Xcode 6.3 számú változatával együtt.

A Swift 2.0-t a 2015-ös WWDC-n jelentették be. 2015. december 3-án, a Swift szabad szoftverként való kiadásával együtt, az Apple közzétett egy tervezetet a Swift 3.0 verziójával kapcsolatban.

A Swift számos régi és modern programozási nyelvből merít ötleteket. Alapjául szolgált az ismert és népszerűbb nyelvek közül az Objective-C, a Haskell, a Rust, a Python, a Ruby és a C#, valamint néhány, a piacon nem kifejezetten sikeres, ám értékes elméleti újításokat hordozó programnyelv is, mint például a CLU.

Jellemzői[szerkesztés]

A Swift nyelv multiparadigmás: támogatja a procedurális-imperatív, strukturált, funkcionális és objektumorientált stílusú programozást is. A nyelv célja érezhetően a Cocoa API-val való egyszerű és fájdalommentes együttműködés, azonban ez korántsem az egyetlen tervezési szempont. A Swift három dologban is megpróbálja modernizálni a programozást: biztonságosságra, kényelmes fejlesztésre és jó futásidejű teljesítményre törekszik.[3] A múltban az egymást némileg kizárónak tartott három előnyös tulajdonságot tudatosan tervezett szintaxissal és szemantikával, kifejező típusrendszerrel, valamint agresszív magas- és alacsony szintű optimalizációkkal, statikus analízissel igyekszik közelebb hozni egymáshoz.

Szintaxis[szerkesztés]

A Swift mottója legelső bejelentésekor az volt: "Objective-C, a C nélkül". A nyelv az Objective-C üzenetküldési szintaxisát elhagyta, mert ez a Smalltalk-szerű, sok szögletes zárójelet igénylő forma sok kezdő programozó számára jelentett tanulási nehézséget. Swiftben a metódushívások a Simula-stílusú "pont és zárójel" szintaxist használják, amely sok C-családbeli nyelvben, valamint a C szintaxisát kölcsönző más nyelvekben is már jól megszokott és ismert.

A Swift emellett széleskörűen alkalmaz lokális típusinferenciát is. A Swift fordítóprogram inferenciát végző algoritmusa nagyban hasonlít a Hindley–Milner-típusrendszeren alkalmazott constraint alapú típusrekonstrukciós módszerekre, amelynek eredményeként az explicit típusannotációk az idiomatikus Swift kódban csak ritkán szükségesek. Ez is jelentősen javítja a kód olvashatóságát.

A nyelv számos gyakori programozásitechnikai konstrukciót szintaktikus cukorkával támogat. Beépített literálszintaxisa van többek között a tömböknek, hash tábláknak, stringeknek és opcionális típusoknak.

A blokkokat a C nyelvhez hasonlóan kapcsos zárókelek határolják. Az egyes kifejezések és statementek végére nem szükséges pontosvesszőt rakni, kivéve, ha egy sorba több kifejezést írunk.

A Swift támogatja a Unicode használatát a forrásszövegben is: konstans-, változó- és függvénynevekben is használhatunk nemzetközi karaktereket, új operátorokat definiálhatunk Unicode-szimbólumokból, valamint a stringliterálokban is használhatunk Unicode-ot.

Szemantika[szerkesztés]

A Swift egy statikusan (fordítási időben) és szigorúan típusozott (kevés implicit konverzióval rendelkező) nyelv. Típusrendszere széles körű, kiterjeszthető, és a nyelv paradigmáinak pragmatikusan megfelel. A procedurális-imperatív stílust nem-tiszta függvényekkel, írható változókkal és értékadással, ciklusokkal, blokk alapú láthatósági tartományokkal támogatja. A funkcionális programozáshoz elsőosztályú függvényekkel, lexikális lezártakkal, a változók alapértelmezett írásvédettségével, a standard könyvtárban implementált magasabb rendű függvényekkel, részleges függvényapplikációval és algebrai adattípusokkal nyújt segítséget. Az objektumorientált szemléletet osztályokkal, protokollokkal, egyszeres leszármazással, dinamikus kötésű (virtuális) metódushívásokkal, számított tulajdonságokkal (computed properties), továbbá privát és nyilvános láthatóságú adattagokkal és metódusokkal támogatja.

A Swift tartalmazza a procedurális nyelvekből ismert vezérlési szerkezeteket: kétirányú elágazást (if statement és feltételes kifejezés formájában), többirányú elágazást (switch-case statement-et), és ez utóbbit mintaillesztéssel egészíti ki. A nyelvben jelenleg kétféle elöltesztelő ciklus (while és C stílusú, háromtagú for), egy hátultesztelő ciklus (repeat-while) és egy általános, szekvenciákon működő ciklus (for-in) létezik, bár a C stílusú elöltesztelő for ciklust a nyelv egy következő iterációjában valószínűleg el fogják távolítani.

A Swift rendelkezik explicit kivételkezelési mechanizmussal is. A kivételek dobásának lehetősége a függvények típusának része, és a dobott kivételeket a programozónak valamilyen formában kötelező kezelnie, vagy jeleznie, hogy a kivétel dobása sohasem következhet be; ezt a feltételt a compiler fordítási időben, illetve az utóbbi esetben egy futásidejű ellenőrzés beillesztésével is kikényszeríti.

A nyelv típusrendszere támogatja a polimorfizmus több fajátáját: az altípusos polimorfizmust (osztályok öröklődése formájában), a paraméteres polimorfizmust megszorításokkal (generikus típusokon keresztül), valamint az ad hoc polimorfizmust (függvények és operátorok túlterhelése által).

A Swift automatikus memóriakezelést használ, amely azonban nem a legtöbb hasonló nyelvben megszokott referenciakövető szemétgyűjtés (tracing garbage collection). Az Objective-C objektumokhoz hasonlóan a dinamikusan allokált Swift objektumok is automatikus referenciaszámlálásnak (ARC) vannak alávetve.[4] A körkörös referenciák megszakítása a programozó feladata, amelyhez a nyelv beépített támogatást nyújt gyenge referenciák formájában. A gyakori referenciaszámlálás által okozott teljesítmény- és sebességproblémák kiküszöbölésére a Swift fordítóprogram tartalmaz egy ARC optimalizációs lépést.

Memóriakezelés tekintetében, a magas szemantikai szinten, a Swift megkülönböztet érték- és referenciatípusokat. Az értéktípusok az elvárt módon működnek: értékadásukkor, paraméterként való átvételükkör mély szemantikai másolat készül róluk. A referenciatípusok nem a C++ nyelv referenciáinak felelnek meg, sokkal inkább hasonlítanak pointerekre, amint azt például a C# vagy Java nyelvekben tapasztalhatjuk. A referenciatípusú példányokra hivatkozó változóknak való értékadás tehét magát a mutatott értéket nem, csupán a referencia "kötését" változtatja meg, míg az adattagok (példányváltozók) és tulajdonságok referencián keresztüli, indirekt módosítása magában a mutatott objektumban idéz elő változást.

Egy Swift programban az értékeket a fordítóprogram allokálja vagy automatikus, scope-hoz rendelt, fordítási időben ismert élettartammal (pongyola kifejezéssel élve "a stack-en"), vagy dinamikusan, fordítási időben nem ismert élettartammal ("a freestore-on" avagy "a heap-en"). Az allokáció helye és milyensége az implementáció belső, rejtett sajátsága, amelyet az érték használati helye és kontextusa (pl. szerepel-e egy lezárt szabad változói között), valamint a különböző magas szintű optimalizációk és a statikus analízis hatékonysága is befolyásolhat.

Az alacsony szintű optimalizációkat a fordítóprogram az általa back-endként használt LLVM infrastruktúrának delegálja. A magas szintű optimalizációk elvégzésére a compilernek egy, az LLVM IR-re hasonlító saját köztes reprezentációja van, a SIL (Swift Intermediate Language).[5]

Együttműködés más nyelvekkel[szerkesztés]

A Swift lehetőséget ad C típusokkal és függvényekkel, valamint Objective-C osztályokkal történő natív interoperációra. A C beépített típusainak (például egész és lebegőpontos számok, pointerek, függvények) megfelelő Swift típusok a standard könyvtárban találhatóak, az Objective-C osztályok pedig automatikusan együttműködnek a Swift kóddal, habár a típusok és a metódusok nagy része jelentős, ugyanakkor egyértelmű szintaktikai változásokon megy keresztül. A C és Objective-C típusok és függvények felismerését és importálását a Swift compiler a header (fejléc) fájlok alapján automatikusan elvégzi.

C nyelvű interfészek segítségével Swiftből meghívhatunk C++ kódot is (tehát az Objective-C++ nyújtotta előnyökről sem kell a nyelvet használó projektekben lemondanunk), valamint bármely olyan nyelven (jellemzően szkriptnyelveken) íródott programokat is, amelyek rendelkeznek C API-val.

A Swift runtime OS X, iOS, watchOS és tvOS rendszereken futó implementációja szoros kapcsolatban áll az Objective-C runtime-mal, és azzal állandó párbeszédet folytat például a Cocoa és Swift-natív collection típusok között való konvertáláskor.

Fejlesztőeszközök[szerkesztés]

A Swift toolchain teljeskörű parancssori interfésszel rendelkezik mind OS X, mind GNU/Linux rendszereken. A Swift compiler (swiftc) meghívható ahead-of-time fordítás céljából (ekkor a C, C++ és Objective-C nyelven való programozásban megszokotthoz hasonlóan kapunk egy futtatható fájlt vagy importálható bináris modult, dinamikus könyvtárat), de létezik egy interaktív interpreter, REPL is (swift), amely az LLDB debugger parancssorán keresztül, JIT-fordítás segítségével értékeli ki a beírt Swift kifejezéseket és statementeket.[6]

Az OS X operációs rendszerre elérhető Xcode IDE támogatja a Swift nyelvű fájlok szerkesztését és fordítását. Kifejezetten Swifthez készült az Xcode "Playground" funkciója. Ezek a "játszóterek" a REPL-höz hasonlóan segítik az interaktív kódolást, az azonnali kiértékelést, és bizonyos típusú kifejezések, értékek közvetlen grafikus megjelenítését. Egy Playground a kód mellett tartalmazhat közbeszúrt dokumentációt is (például Markdown formátumban), amely lehetővé teszi a literate programozást és a nyelv alapjainak kényelmes, gyors elsajátítását.

Példák[szerkesztés]

Hello World:

print("Hello World!")

Függvények, konstansok, változók deklarálása, alapvető kifejezések és operátorok:

// Függvény egy paraméterrel, egy visszatérési értékkel
func greet(name: String) -> String {
    return "Hello " + name
}

// paraméterből és visszatérési értékből is lehet több is
func reflectToOrigin(x: Double, y: Double) -> (Double, Double) {
    return (-x, -y)
}

// a konstansok a "let" kulcsszóval deklarálhatóak.
// a típusinferencia miatt az explicit típusannotáció elhagyható:
let PHI = (1.0 + sqrt(5)) / 2

// változókat a var kulcsszóval vezethetünk be:
var x = 1
x += 2

Vezérlési szerkezetek:

// if statement, érték nélküli
if true {
    print("this is printed")
} else {
    print("this is not printed")
}

// feltételes kifejezés, értékkel rendelkező
let three = 1 > 0 ? 3 : 4;

// többutas elágazás. Figyeljük meg, hogy biztonsági és defenzív programozástechnikai
// okokból az egyes esetek alapértelmezetten nem "esnek át".
switch three {
case 1:
    print("1")
case 3:
    print("3")
default:
    print("neither 1 or 3")
}

// iteráció collection szekvenciális típusokon.
// A "..<" operátor a szokásos félig zárt intervallumot, [0, 10)-et hozza létre.
for i in 0..<10 {
    print(i)
}

Típusok létrehozása – a struct és enum típusok képviselik az értékszemantikájú algebrai szorzat- és összegtípust, a class típusok pedig "referencia"- (pointer-)-szemantikájú osztálytípust hoznak létre.

struct Point {
    let x: Float
    let y: Float
}

let origin = Point(x: 0, y: 0)

enum Maybe<T> { 
    case Nothing 
    case Just(T)
}

let three = Maybe.Just(3)
let empty = Maybe<Int>.Nothing

class Unicorn {
    var hornLength: Float

    init(hornLength: Float) {
        self.hornLength = hornLength
    }

    func print() {
        // figyeljük meg az explicit formátumstringek nélküli string-interpolációt.
        Swift.print("Horn length = \(hornLength) UUs (Unicorn Units)")
    }
}

func doNotChangeUnicorn(var u: Unicorn) {
    u = Unicorn(hornLength: 2.718)
}

func changeUnicorn(u: Unicorn) {
    u.hornLength = 6.283
}

let u = Unicorn(hornLength: 3.142)
u.print() // 3.142
doNotChangeUnicorn(u)
u.print() // még mindig 3.142
changeUnicorn(u)
u.print() // 6.283

Kritika[szerkesztés]

A Swift folyamatos, gyors változáson megy keresztül. Az Apple a haladás érdekében és az esetleges hibák megkövesedése ellen való védekezés jegyében azt diktálja, hogy a helyes koncepcióknak a nyelvbe való integrálása, a programozási stílus javítása és az inkonzisztenciák megszüntetése szinte azonnal és feltétel nélkül megtörténjen. Ennek következményeképp nem ritka, hogy néhány hónap vagy akár hét eltelte alatt API- és ABI-inkompatibilis (breaking) változtatások történnek a nyelvben, amelyek egész kódbázisok átírását tehetik szükségessé. Az Apple igyekszik ezeknek a változtatásoknak, refaktorálásoknak a menetét megkönnyíteni az Xcode fejlesztőkörnyezetbe épített automatikus refaktorozó eszköz segítségével.

Jegyzetek[szerkesztés]