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 zerosutasítás és akkor később mi hozzárendelhetünk egy atomot x-hez hogy:
x = 7Ez 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 + 1helyette
mylongvarname += 1
galaxy[q_row][q_col][q_size] = galaxy[q_row][q_col][q_size] * 10helyette:
galaxy[q_row][q_col][q_size] *= 10
accounts[start..finish] = accounts[start..finish] / 10helyette:
accounts[start..finish] /= 10
Általában, valahányszor van egy értékadás a következő formában:
baloldal = baloldal operátor kifejezéshelyette:
baloldal operátor= kifejezésahol 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.
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.
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.
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.
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.
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
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.
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.
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() 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}
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.
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
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 Bahol 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 Bamikor 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 thenRö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 whileEbben 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 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.
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 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 whileez 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..