Az Euphoria Programozási nyelv (v2.3)

Utasítások, vezérlési szerkezetek

Értékadó utasítás

Egy értékadó utasítás egy kifejezés értékét rendeli egy változóhoz, vagy indexhez vagy változó szelethez. Pl.

        x = a + b



        y[i] = y[i] + 1



        y[i..j] = {1, 2, 3}

A előző változók, indexek, változó szeletek értékét elhagytuk. Pl. Feltételezve, hogy x egy 1000 elemű sorozat, akkor ezt inicializálhatta egy:

        object x



        x = repeat(0, 1000)  -- a sequence of 1000 zeros

utasítás és akkor később mi hozzárendelhetünk egy atomot x-hez hogy:
        x = 7

Ez megengedett mivel, x objektum típusú. X előző értéke, ami névleg egy 1000 elemű sorozat, egyszerűen eltűnik. Euphoria dinamikus tároló allokációjának következtében az 1000 elemű sorozat helye felszabadul.

Megjegyezzük, hogy az egyenlő szimbólum ’=’ használható mind összerendeléshez mind egyenlőség vizsgálathoz. Sosem lehet összetéveszteni ezeket, mivel az összerendelés egy utasítás, ami nem szerepelhet kifejezésben.

Összerendelés Operátorral

Euphoria biztosítja az értékadás utasításnak több formáját.

Azért, hogy kevesebbet kelljen gépelni, és a kód is elegánsabb legyen a következő operátorok összeköthetők az értékadással:
      +   -   /   *   &

Pl.

      mylongvarname = mylongvarname + 1

helyette
      mylongvarname += 1

 
      galaxy[q_row][q_col][q_size] = galaxy[q_row][q_col][q_size] * 10

helyette:
      galaxy[q_row][q_col][q_size] *= 10

 
      accounts[start..finish] = accounts[start..finish] / 10

helyette:
      accounts[start..finish] /= 10

Általában, valahányszor van egy értékadás a következő formában:

      baloldal = baloldal operátor kifejezés

helyette:
      baloldal operátor= kifejezés

ahol az operátor  lehet:    +   -   *   /   &

Amikor a baloldal tartalmaz összetett index/szelet, az op= forma általában gyorsabban fog végrehajtódni, mint a hosszú forma. Ezt használva a kód olvashatóbb, mert nem kell vizuálisan összehasonlítani a baloldalt a jobboldalon lévő másolatával.

 

Szekvencia

Pontosvessző nem használatos Euphoria-ban. Egy sorba annyi utasítás tehetsz amennyit csak szeretnél, vagy minden utasítást írhatsz új sorba.

 

Operátorok

Relációs Operátorok

A relációs operátorok  <   >   <=   >=   =   !=   mindegyikük előállít 1 (igaz) vagy 0 (hamis) eredményt (értéket).

        8.8 < 8.7   -- 8.8 less than 8.7 (false)

        -4.4 > -4.3 -- -4.4 greater than -4.3 (false)

        8 <= 7      -- 8 less than or equal to 7 (false)

        4 >= 4      -- 4 greater than or equal to 4 (true)

        1 = 10      -- 1 equal to 10 (false)

        8.7 != 8.8  -- 8.7 not equal to 8.8 (true)

Ezeket az operatorokat alkalmazhatjuk sorozatokon is.


Logikai Operátorok

A logikai operátorok az and, or, xor, és not meghatározzák egy a kifejezés igazságértékét. Pl:

        1 and 1     -- 1 (true)

        1 and 0     -- 0 (false)

        0 and 1     -- 0 (false)

        0 and 0     -- 0 (false)



        1 or  1     -- 1 (true)

        1 or  0     -- 1 (true)

        0 or  1     -- 1 (true)

        0 or  0     -- 0 (false)



        1 xor 1     -- 0 (false)

        1 xor 0     -- 1 (true)

        0 xor 1     -- 1 (true)

        0 xor 0     -- 0 (false)



        not 1       -- 0 (false)

        not 0       -- 1 (true)

Alkalmazhatjuk ezeket az operatorokat más számokon is (nemcsak 1 vagy 0). A szabály az, hogy nulla hamisat, a nem nulla igazat jelent. Pl:

        5 and -4    -- 1 (true)

        not 6       -- 0 (false)

Ezek az operátorok alkalmazhatok sorozatokra is.

Aritmetikai Operátorok

Az általános aritmetikai operátorok itt is megtalálhatóak: összeadás, kivonás, szorzás, osztás, egy-argumentumú kivonás, egy-argumentumú összeadás .

        3.5 + 3  -- 6.5

        3 - 5    -- -2

        6 * 2    -- 12

        7 / 2    -- 3.5

        -8.1     -- -8.1

        +8       -- +8

Ha számolásnál az eredmény túl nagy (kiesik a -1e300-+1e300 tartományból) az eredmény egy speciális atom lesz  +infinity + végtelen vagy-infinity - végtelen. Kiíratásnál inf vagy -inf formában jelenek meg. Lehetséges az is, hogy az eredmény  nan vagy -nan. "nan" azt jelenti, hogy "nem szám", azaz nem definiált érték (pl: inf osztva inf).  Ezek az értékek definiálva vannak az IEEE lebegőpontos szabványban. A program logikájában ezek a speciális értékek általában hibát jelentenek, bár az inf, egy közvetett eredmény lehet elfogadható néhány esetben. Pl: 1/inf az 0 lehet "helyes" válasz az algoritmusban.

Nullával való osztás, hibás paraméter a matematikai könyvtár eljárásaiban, pl: négyzetgyöke negatív számnak, logaritmusa nem pozitív számnak, stb. azonnali hiba üzenetet okoz és a program abortál.

Unáris plusz azért használható, hogy kiemelje a program olvasójának azt, hogy a szám pozitív. Az interpreter figyelmen kívül hagyja.

 

Precedencia Sorrend

Az operátorok precedenciája a kifejezésekben a következő: legmagasabb precedencia: function/type calls unary- unary+ not * / + - & < > <= >= = != and or xor legalacsonyabb precedencia:{ , , , } Ez alapján a 2+6*3 a 2+(6*3) jelenti és nem a (2+6)*3. Azonos vonalban levő operátorok precedenciája azonos és kiértékelve balról jobbra lesznek kiértékelve. Az egyenlő szimbólum, '=' hozzárendelő állításban használva nem operátor, csak a nyelv szintaxisának része.

Műveletek Sorozatokon

Mind a relációs, logikai és aritmetikai operátorok leírása megtalálható alább és mindegyik ugyanúgy alkalmazható sorozatokra, mint egyszerű számokra (atomokra).

Amikor unáris (egy operandusú) művelettel alkalmazzunk egy sorozatra, akkor a művelet minden egyes elemre a sorozatban alkalmazva lesz, az eredmény ugyanilyen hosszú sorozat. Ha a sorozat elemeiből valamelyik sorozat, akkor ugyanezt a szabály kell rekurzívan alkalmazni. Pl.

        x = -{1, 2, 3, {4, 5}}   -- x is {-1, -2, -3, {-4, -5}}

Ha bináris (két operandusú) műveletet alkalmazunk ahol mindkét argumentum sorozat, akkor a két sorozatnak egyforma hosszúnak kell lennie. A bináris művelet alkalmazzuk a sorozatok megfelelő elemein és az eredmény egy sorozat lesz. Pl.

        x = {5, 6, 7, 8} + {10, 10, 20, 100}

        -- x is {15, 16, 27, 108}

Ha a bináris operator egyik operandusa sorozat, a másik pedig egy egyszerű szám (atom), akkor az önálló szám valójában ismétlődik. A kifejezés értéke egy ugyan olyan hosszú sorozat lesz, mint a kezdeti sorozat. Pl.

        y = {4, 5, 6}



        w = 5 * y              -- w is {20, 25, 30}



        x = {1, 2, 3}



        z = x + y              -- z is {5, 7, 9}



        z = x < y              -- z is {1, 1, 1}



        w = {{1, 2}, {3, 4}, {5}}



        w = w * y              -- w is {{4, 8}, {15, 20}, {30}}



        w = {1, 0, 0, 1} and {1, 1, 1, 0}    -- {1, 0, 0, 0}



        w = not {1, 5, -2, 0, 0}     -- w is {0, 0, 0, 1, 1}



        w = {1, 2, 3} = {1, 2, 4}    -- w is {1, 1, 0}

        -- note that the first '=' is assignment, and the

        -- second '=' is a relational operator that tests

        -- equality 


 

Sorozatok Szeletelése

Egy sorozat egymást követő elemeit kiválaszthatjuk a kezdő és a befejező elem számának megadásával. Pl: ha x = {1, 1, 2, 2, 2, 1, 1, 1} akkor x[3..5] a {2, 2, 2}sorozat. x[3..3] a {2}sorozat is megengedett, ennek kiértékelése a nulla-hosszú {} sorozatot eredményezi. Ha y értéke: {"fred", "george", "mary"} akkor y[1..2] az {"fred", "george"}.

Sorozat vágását gyakran használjuk arra, hogy felülírjuk egy részét egy változónak. Az x[3..5] = {9, 9, 9} értékadás után az x {1, 1, 9, 9, 9, 1, 1, 1} lesz, a x[3..5] = 9 hasonló hatású. Ha y = {0, "Euphoria", 1, 1}, akkor  y[2][1..4] az "Euph". Ha azt írjuk, hogy y[2][1..4]="ABCD" akkor y {0, "ABCDoria", 1, 1} lesz.

Általában egy változó nevét követheti 0 által vagy több index, amit követhet a megfelelő sorrendben 0 vagy 1 szelet meghatározás. Csak változók lehetnek indexelve vagy szeletelve.

Az üres szelet definíciója: Tekintsük az s[i..j] szeletet, ahol s hossza n. A szelet i-től j-ig, ahol j=i-1 üres sorozatot ad, még akkor is ha i=n+1. Így üres szelet a 1..0 és n+1 és minden ami a kettő között a fenti szabály szerint értelmezhető. Az üres szelet hasznos néhány algoritmusban. Egy szelet i-től j-ig ahol j<i-1, azaz a "fordított" szelet mint s[5..3] nem megengedett.


Sorozatok és Atomok Konkatenációja - és az '&' Operátor

Két objektum összekapcsolható az & operátort használatával. A művelet eredménye egy sorozat, amely hossza egyenlő az összekapcsolandó objektumok hosszának összegével. (ahol az atomokat 1 hosszúnak tekintjük) pl.:

        {1, 2, 3} & 4              -- {1, 2, 3, 4}



        4 & 5                      -- {4, 5}



        {{1, 1}, 2, 3} & {4, 5}    -- {{1, 1}, 2, 3, 4, 5}



        x = {}

        y = {1, 2}

        y = y & x                  -- y is still {1, 2}

Egy sorozat i. elemét úgy is törölhetjük, hogy összefűzzük a sorozat i előtti és i utáni részét:

	s = s[1..i-1] & s[i+1..length(s)]

Ez akkor is lehetséges, amikor i egyenlő 1 vagy hossz(s), ekkor s[0..1] és s[length(s)+1.. length(s)] megengedett üres szelet.


További Operátorok Sorozatokon

Bemutatunk még néhány operátort, amit sorozatokon lehet használni, ezeknek angol nevük van speciális karakterek helyett. Ezek az operátorok részei az ex.exe/exw.exe/exu-nak, ezért ezek mindig elérhetőek, és gyorsak. Ezeket a műveleteket úgy hívhatjuk, mint az alprogramokat, bár sokkal hatékonyabban vannak implementálva mint azok.


length(s)

length() megadja az s sorozat hosszát, azaz elemek számát s-ben. Az s sorozatnak lehetnek olyan elemei, amelyek szintén sorozatok, de length csak a "felső" szinten számol. Hibát kapunk ha egy atomra alkalmazzuk a length-et. Pl.

        length({5,6,7})             -- 3

        length({1, {5,5,5}, 2, 3})  -- 4 (not 6!)

        length({})                  -- 0

        length(5)                   -- error!


repeat(elem, hány)

repeat() egy olyan sorozatot ad, amelyik tartalmazza az "elem"-et "hány" sokszor pl:

        repeat(0, 100)         -- {0,0,0,...,0}   i.e. 100 zeros

        repeat("Hello", 3)     -- {"Hello", "Hello", "Hello"}

        repeat(99,0)           -- {}

Az "elem" amit ismétlünk bármilyen atom vagy sorozat lehet.


append(s, elem) / prepend(s, elem)

append() egy új sorozatot készít az "elem"-et hozzáfűzve az s sorozat végéhez.  prepend() egy új sorozatot készít az "elem"-et az s sorozat elejéhez fűzi hozzá. Pl.

        append({1,2,3}, 4)         -- {1,2,3,4}

        prepend({1,2,3}, 4)        -- {4,1,2,3}



        append({1,2,3}, {5,5,5})   -- {1,2,3,{5,5,5}}

        prepend({}, 9)             -- {9}

        append({}, 9)              -- {9}

Az új sorozat hossza mindig 1-gyel nagyobb, mint az eredeti sorozat hossza. Az "elem" amit hozzáadhatunk a sorozathoz bármely atom vagy sorozat lehet.

Az append() és prepend(), beépített függvénynek van néhány hasonlóságuk az összefűző, & operátorral, de vannak jelentős különbségek is pl:

        -- appending a sequence is different

        append({1,2,3}, {5,5,5})   -- {1,2,3,{5,5,5}}

        {1,2,3} & {5,5,5}          -- {1,2,3,5,5,5}
        


        -- appending an atom is the same

        append({1,2,3}, 5)         -- {1,2,3,5}

        {1,2,3} & 5                -- {1,2,3,5}

Elágazás

Egy if utasítás először teszteli a feltételt, és végrehajtja a megfelelő változatát (részét) az utasításnak. Lehet elsif és else ág is:

        if a < b then

            x = 1

        end if





        if a = 9 and find(0, s) then

            x = 4

            y = 5

        else

            z = 8

        end if





        if char = 'a' then

            x = 1

        elsif char = 'b' or char = 'B' then

            x = 2

        elsif char = 'c' then

            x = 3

        else

            x = -1

        end if

Megjegyzés: az elsif egy összevonása else if-nek, de ez egyértelműbb, mivel nem követeli meg, hogy end if kövesse. Csak egy end if ehet a nyitó if utasítás végén, amikor sok elsif-et tartalmaz az utasítás.

Az if és elsif feltételek rövidzár módszerrel vannak kiértékelve.

Ciklus

A while utasítás teszteli a feltételt, és addig ismétli a ciklusmagot amíg a feltétel nem-nulla (igaz).

        while x > 0 do

            a = a * 2

            x = x - 1

        end while


Rövidzár Kiértékelés

Amikor if, elsif, vagy  while feltétel tartalmaz and vagy or operátort, akkor rövidzár kiértékelés lesz alkalmazva. Pl.

        if a < 0 and b > 0 then ...

Ha a < 0 hamis, akkor Euphoria nem vizsgálja, hogy b nagyobb mint 0. Mivel ekkor az eredmény biztosan hamis. Hasonlóan,
        if a < 0 or b > 0 then ...

ha a < 0 igaz, akkor Euphoria rögtön megadja az eredményt, hogy igaz, anélkül, hogy tesztelné b értékét.

Általában, valahányszor adott:

        A and B

ahol A és B valamilyen kifejezés, ha A hamis Euphoria rögtön megadja az eredményt, hogy hamis, anélkül, hogy megnézné a B kifejezést.

Hasonlóan:

        A or B

amikor A igaz, Euphoria kihagyja a B kifejezés kiértékelését és az eredmény igaz lesz.

Ha egy B kifejezés tartalmaz függvény hívást és a függvénynek lehet mellékhatása, akkor kapsz fordítási idejű figyelmeztetést. Régebbi verziói az Euphoria-nak nem használtak rövidzár kiértékelést, ezért lehet, hogy néhány régi kód nem hibátlan az új verzióban, habár az Euphoria arhívumban nem található ilyen program.

Ha van egy B kifejezés tartalmaz valamit, ami futás idejű hibát okozna normálisan, ha Euphoria kihagyja a B kiértékelését, a hiba nem jelenik meg. Pl.

        if x != 0 and 1/x > 10 then  -- divide by zero error avoided



        while 1 or {1,2,3,4,5} do    -- illegal sequence result avoided

Ezt lehet, úgy is értelmezni, mint felületes kódolás, de valójában gyakran egyszerűbb vagy olvashatóbb módon lehet valamit leírni. Pl.

        if atom(x) or length(x)=1 then

Rövidzár kiértékelés problémát okozna, ha x atom, mivel a egy atom hossza nem definiált. Rövidzár kiértékeléssel a length(x) csak akkor lesz ellenőrizve ha x egy sorozat. Hasonlóan:
        -- find 'a' or 'A' in s

        i = 1

        while i <= length(s) and s[i] != 'a' and s[i] != 'A' do

             i += 1

        end while

Ebben a ciklusban az i változó, a végső iterációban nagyobbá válik mint length(s). Rövidzár kiértékelés nélkül, az index határon kívül hiba fog bekövetkezni, de rövidzár kiértékelésnél, a ciklus terminálni fog amikor i<=length(s) hamissá válik. Euphoria nem fogja kiértékelni s[i]!=’a’-t és s[i]!=’A’-t sem, így nem fog index hiba fellépni.

Rövidzár kiértékelés csak and és or esetében és csak  if, elsif és while feltételekben történik. Más összefüggésben nincs alkalmazva. Pl az értékadó utasítás:

        x = 1 or {1,2,3,4,5}  -- x should be set to {1,1,1,1,1}

Ha itt rövidzár lenne használva, akkor beállítanánk x-t 1-nek, és nem néznénk még {1,2,3,4,5}-t. Ez rossz lenne. Rövidzár csak if, elsif, while feltételekben lehet alkalmazni, mert ott csak az eredmény igaz vagy hamis mivolta lényeges.

A for utasítás

A for utasítás egy speciális ciklus, ahol a ciklus változó fut kezdeti értéktől fel vagy le a végső értékig. Pl.

        for i = 1 to 10 do

            ? i   -- ? is a short form for print()

        end for



        -- fractional numbers allowed too

        for i = 10.0 to 20.5 by 0.3 do

            for j = 20 to 10 by -2 do    -- counting down

                ? {i, j}

            end for

        end for

A ciklus változó automatikusan deklarálva van és a ciklus végéig létezik. A cikluson kívül nincs érték és nem deklarált. Ha szükséges a ciklusváltozó végső értéke, akkor át kell másolni egy másik változóba, mielőtt kilépnénk a ciklusból. A ciklus változó értékét nem lehet megváltoztatni. Meg kell adni kezdeti érték, a végső értéket és növekedés mértékét. Ha nincs megadva a növekedés mértéke, akkor az +1 lesz.

Vezérlésátadó utasítások

A return utasítás

A return utasítás rögtön visszatér az alprogramból. Ha az alprogram egy függvény vagy típus akkor egy értéket vissza kell adni. Pl.

        return



        return {50, "FRED", {}}


Az exit utasítás

Az exit utasítás egy while-ciklus vagy for-cilkus egy utasítása lehet. Rögtön a ciklus terminálását eredményezi, a végrehajtás a ciklus utáni első utasításnál folytatódik. Pl.

        for i = 1 to 100 do

            if a[i] = x then

                location = i

                exit

            end if

        end for

Erre például ezért van szükség:

        constant TRUE = 1



        while TRUE do

            ...

            if some_condition then

                exit

            end if

            ...

        end while

ez egy "végtelen" while ciklus, ami valójában befejeződik egy exit utasítás hatására a ciklus törzsének tetszőleges pontján..