A lényeget tekintve ebben sem sokban tér el más PASCAL-szerű nyelvektől. Egyetlen kulcsszó, a PROCEDURE szolgál alprogramok definiálására. A függvényeket és az eljárásokat tehát csak a visszatérési érték létezése alapján különbözteti meg.
Egy eljárást csak egyszer definiálhatunk. Egy eljárástípust a következőképpen kell megadni:
ahol a sig egy szignatúrát jelöl, aminek így kell kinéznie:
A formális paraméterdeklaráció:
ahol
Mivel lehet paraméternek kezdőértéket adni, így az eljárás hívásakor elhagyható ez paraméter.
Az eljáráshívás általános formája:
procedure name(actual parameter1,... actual parametern)
Ha P a következőképpen deklarált:
akkor a következő hívások ekvivalensek:
P('a', 0) P('a') P(ch := 'a') P(n := 0, ch := 'a') P('a', n := 0)
P() illegális, mivel nem köti ch-t. A
További érdekesség az EVAL kulcsszó. Ezzel a paranccsal kiértékelhetünk egy függvényt olyankor, amikor a visszatérési érték nem érdekel minket, csak a függvény mellékhatásait szeretnénk érvényesíteni. Az EVAL tehát elnyeli a visszatérési értéket.
Itt kell megemlíteni azt is, hogy Modula-3-ban nincs lehetőség operátorok túlterhelésére.
A Modula-3 fordítási egységei a modulok és interfészek.
Egy modul olyan mint egy blokk, kivéve az azonosítók láthatóságát: Egy entitás látható egy blokkban, ha az adott blokkban, vagy valamely befoglaló blokkban deklarálták.
Egy entitás látható egy modulban, ha az adott modulban, vagy valamely a modul által importált vagy exportált interfészben deklarálták.
A program végrehajtása a moduljainak törzsének végrehajtását jelenti a következő szabályok alapján:
Azt a modul, melynek törzse utolsóként hajtódik végre, fő modulnak nevezzük. A nyelv implementációitól elvárt, hogy valamilyen eszközt adjanak a program fő moduljának explicit kijelölésére, ha ez a fenti szabályok alapján nem lenne egyértelmű. A nyelv definíciója szerint erre a javasolt az megoldás, hogy a fő modul az, amely a Main nevű interfészt exportálja, melynek tartalma implementációfüggő.
A program végrehajtása akkor fejeződik be, amikor a fő modul törzsének végrehajtása befejeződik, még akkor is, ha konkurens szálak még futnak.
Az IMPORT utasításnak két formája van. Minden import definíció (formájától függetlenül) szimultán értékelődik ki.
Az első forma:
IMPORT I AS J
amelynek hatására importálja az I interfészt, melyre a importáló modulon belül a továbbiakban J-vel hivatkozhatunk. Az I által deklarált entitások láthatóvá válnak a modulban, de az I által importáltak nem.
Ezek után az I interfészben N néven deklarált entitásra a J.N minősített névvel hivatkozhatunk.
Az IMPORT I
utasítás ekvivalens az IMPORT I AS I
utasítással.
Az második forma:
FROM I IMPORT N
amelynek hatására N lokális néven lesz elérhető az I interfészben deklarált N entitás. Egy lokális hivatkozás mindig nagyobb precedenciájú;, mint a globális, azaz pl.
IMPORT I AS J, J AS I; FROM I IMPORT N3/ hatására szimultán a következő lokális nevek keletkeznek: J, I, N sorrendben a következő globális névvel rendelkező entitásokhoz: I, J, J.N
Ugyanazt a lokális nevet nem szabad többször használni, azaz a következő import utasítás illegális, még akkor is, ha J és K ugyanaz:
IMPORT J AS I, K AS I;
Egy modult a következőképpen definiálhatunk:
MODULE <azonosító> EXPORTS <exportált interfészek listája>; <import utasítások>; <deklarációk>; <modul törzs - blokk> <azonosító>; Blokk = <deklarációk> BEGIN <Utasítások> ENDUtasítás is lehet blokk.
Ha nincs megadva EXPORTS, akkor alapértelmezésként <AZONOSÍTÓ>lesz az.
Ha M modul exportálja az I interfészt, akkor I entitásai minősítés nélkül elérhetőek M-ben.
Bármely eljárás, mely I-ben deklarált, megadható M-ben törzsével együtt. Az eljárás M-beli szignatúrának meg kell felelnie az I-ben lévőnek, azaz:
A paraméternevek és alapértelmezett paraméterértékek tekintetében az M-en belül az M-beli, mindenhol máshol az I-beli szignatúra használatos.