Satherben az eljárások, függvények készítésére közös módszer áll rendelkezésre. A függvény olyan eljárás, amelynek van visszatérési értéke. Ezt a Saher a szignatúrában rögzíti (eleme a szignatúrának, ez is megkülönböztetési alap két eljárás között). Megjegyzés: a továbbiakban vegyesen használjuk ezt a két kifejezést.
Az eljárások argumentumait vesszővel elválasztott listában kell felsorolni. Az argumentumok láthatósága a teljes törzsre kiterjed, elfedi az osztály eljárásait és attribútumait. Ezen kívül minden argumentumnak állítható az átadási iránya is. Alapértelmezés szerint minden bemenő (in) argumentum, egyéb lehetséges értékei: inout, out, once. Az in, inout, out módok értelmezése a szokásos. Bemenő argumentumoknál az aktuális argumentum egy másolatát kapja meg az eljárás, így tehát érték szerinti átadás valósul meg. Az out és inout paraméterek felfoghatók visszatérési értékként is, így több értéket is visszaadhat egy eljárás. Érdekesség, hogy ilyenkor ezt nem csak az eljárás definiálásánál, hanem a meghívásánál is explicit módon jelölni kell. Például:
A once mód pedig csak speciális eljárásoknál, az iterátoroknál használható. Ekkor ezen paraméter kiértékelése csak az első híváskor történik meg.
A paraméterátadási módok jellemzőit az alábbi táblázatban foglalhatjuk össze:
in
Minden argumentum ‘in’ módú alapértelmezés szerint, ‘in’ kulcsszó nincs. Ilyenkor az aktuális paraméter egy másolata adódik át (érték szerinti paraméterátadás). Ha ez az érték egy referencia, akkor a referencia egy másolata adódik át, tehát a tényleges objektum nem másolódik le, ugyanazt látja a hívó és a hívott eljárás.
out
Egy ‘out’ argumentum esetén eredmény szerinti paraméterátadás valósul meg: az argumentum a hívott eljárástól adódik át a hívónak, amikor az eljárás befejeződik. A hívott eljárásban egy ‘out’ paraméter értékét csak azután használhatjuk, hogy értéket adtunk neki.
inout
Egy ‘inout’ argumentum esetén érték-eredmény szerinti paraméterátadás valósul meg: az aktuális paraméter átadódik a hívott eljárásnak (érték szerint, tehát lemásolódik), majd visszaadódik a hívónak amikor az eljárás befejeződik (eredmény szerint). A hívott eljárás által végzett módosítások addig nem lépnek érvénybe az aktuális paraméterre vonatkozóan, amíg az eljárás be nem fejeződik.
once
Csak iterátoroknál használható (részletesebben ld. az 5.3 részben). Egy ‘once’ módú argumentum pontosan egyszer értékelődik ki, amikor először meghívjuk az iterátort az aktuális ciklusban. Ettől eltekintve a ‘once’ argumentumok pontosan úgy viselkednek, mint az ‘in’ paraméterek, a hívás helyén ezt nem kell jelölni.
Írhatunk olyan rutinokat is, amelyeknek van hagyományos értelemben vett visszatérési értéke is. Például:
A Sather nyelvben adat és eljárás között a különbség nem is olyan nagy, mint elsőre tűnik. Könnyen adhatunk egy osztálynak olyan jellemzőt, amelyről kívülről nem eldönthető, hogy attribútum vagy eljárás. Minden attribútum definíció új mezőt ad objektum állapotaihoz és létrehoz egy olvasó és egy író műveletet azonos névvel (kivéve konstans attribútumok, melyekhez író eljárás nem készül). Tehát még az értékadás is valójában eljáráshívás. Ennek a szépsége az, hogy később eljárás-párokkal helyettesíthetünk egy attribútumot. (Megjegyzés: erre szükség inkább fejlesztés folyamán előjött implementációs változtatásoknál van, ekkor nem kell az összes hivatkozást is átírni – végül is biztonságosabb, mint a ‘find and replace’.)
Az iterátorok speciális eljárások, melyeket általában egy halmazt szoktak bejárni. Hasznos eszközök a felhasználói ciklikus léptetések elrejtésére, így sokkal tömörebb, érthetőbb és biztonságosabb kódot kaphatunk. minden osztály definiálhat többféle iterátort is, ezek részei az osztály-interfésznek. Az iterátorok egy objektum-gyűjtemény felett dolgoznak (például fa adatszerkezetre adhatunk pre-, in- és postorder bejáró iterátorokat).
Egy iterátor annyiban különbözik egy eljárástól, hogy egy hívás nem fejeződik be teljesen, újrahíváskor nem elölről indul, hanem folytatódik futása a ‘yield’ állításig, és a paraméterek nem veszítik el értéküket. Ezen kívül meg lehet adni, mely argumentumokat értékeljen ki minden híváskor és melyeket csak a legelső alkalommal. Vannak előre megvalósított iterátorok is: while!, until!, break!, upto!, times!, step!, step_upto!, stb., amelyeket elsősorban ciklusok megfogalmazásához használhatunk. Tekintsünk ezekre néhány példát.
A while! addig iterál, amíg a feltétel igaz, az until! pedig addig, amíg a feltétel igazzá nem válik (vagyis amíg hamis). Ezek minden iterációban kiértékelik a feltételt, és attól függően, hogy igaz vagy hamis, a yield vagy a quit részre futnak. (Egy iterációt a quit segítségével tudunk leállítani.) A break! iterátor pedig arra használható, hogy egy ciklust bármikor leállíthassunk.
Tekintsünk egy kissé összetettebb példát: a buborékrendezés egy olyan megvalósítását, amelyben a break! iterátorral állítjuk le a külső ciklust ha már végeztünk (persze ebben az esetben könnyen kiküszöbölhetnénk a break! használatát pl. until! iterátorral).
A times! iterátorral adott lépésszámú ciklust írhatunk:
Az upto! Iterátorral két egész érték között iterálhatunk végig:
A step! és a step_upto! iterátorok hasonlóak a times!-hoz, illetve az upto!-hoz, csak egytől különböző lépésköz beállítását is lehetővé teszik. Például az első 10 páratlan szám összege:
Ahogy már korábban is említettük, egy ciklus törzsében tetszőleges helyen és számban szerepelhetnek iterátor hívások. Erre lehet egy jó példa az alábbi kódrészlet:
Kérdés, hogy ez hányszor írja ki a „Hello” szöveget? Az első sor miatt legfeljebb 100-szor, a második miatt legfeljebb 50-szer, a harmadik miatt (tekintve, hogy az i egyesével lépked 1-től) csak 30-szor, a negyedik miatt (mivel a j 0-tól lépked 10-esével) csak 20-szor, azonban az elágazás miatt a 10-edik iterációban kilépünk a ciklusból, így a kiírást végző utasítás csak kilencszer fog lefutni.
Mi is definiálhatunk iterátorokat az eljárásokhoz hasonlóan, csak itt meg kell adnunk, hogy mikor és hogyan adódjon vissza a vezérlés a hívó pontra. Eljárás esetén erre csak a return biztosít lehetőséget, amely egyben az eljárás befejeződését is jelenti. Ezzel szemben iterátorok esetén két lehetőségünk is van:
Például az alábbi iterátor egy egész intervallum bejárását valósítja meg:
Továbbá nézzük meg például, hogy van megvalósítva az INT osztályban az upto! iterátor:
Itt látjuk, hogy milyen fontos, hogy csak egyszer értékelődik ki az i, és aztán mindig csak erre hivatkozunk. Ellenben a while! esetén ez semmiképpen nem lenne jó, mert akkor csak olyan ciklusokat tudnánk írni, amelyek vagy egyetlen iterációt sem tesznek meg, vagy végtelen ciklusok lesznek. Azonban itt a paraméter minden híváskor kiértékelődik, tehát az alábbi módon valósíthatnánk meg (ha nem lenne beépített):
Az until esetén csak annyit változtatunk az egészen, hogy a feltételt negáljuk az iterátor törzsében lévő if-ben, a break! pedig rögtön kilép (csak a quit-ból áll), ahogy meghívjuk.
Példa, hogy mennyire tömör kódot lehet írni ennek segítségével (a egy INT-ekből álló tömb):
Bár Satherben az eljárás nem típus, így eljárás típusú változónk sem lehet, de van valami nagyon hasonló: closure (bezárás vagy inkább lefedés). Egy closure egy rutint vagy egy iterátort zár magába, melynek némely paraméterét szabadon lehet hagyni (‘_’ jellel). Egy closure meghívásakor a nyílt paramétereknek kell csak konkrét értéket megadni
Eljárás closure-t ‘call’-lal, míg iterátor lezártat ‘call!’-lal hívhatunk meg. Meghíváskor az aktuális paraméterek a ‘_’ jelek helyére sorban helyettesítődnek.
Megjegyzés: out és inout paramétereket nyíltnak kell hagyni, mivel azok értéket adnak vissza.
Írhatunk ilyet is: