- 1 - Vad är si? si är amet på e av måga ibyggda fuktioer i Ada (och de återfis i paketet Ada.Numerics.Elemetary_Fuctios) si är deklarerad att ta emot e parameter (eller ett argumet) av typ Float (mätt i radiaer), och att leverera ett av typ Float. pi : costat Float := 3.141593; agle : Float; r : Float; r := si(agle) + 1.0; Put(si(2 * pi - agle), 5, 3, 0); Avädige av si (och adra fuktioer) kallar ma ett arop av si. Aropskostruktioe kräver ett aktuellt för sis parameter - e Float - iom ( ) efter amet. Aktuell parameter. Aropskostruktioe i sig själv är, eller represeterar, ett av type Float. Ett arop ka då aldrig fias som e ege sats, bara som (del av) ett uttryck (formel). Bakom amet si döljer sig förstås e bit programkod som utför beräkige. - 2 - Ega fuktioer Ma ka själv iföra ega fuktioer i sitt program. Det gör ma med e form av deklaratio. Mis: E deklaratio itroducerar ett ytt am samt ger amet e iebörd. Om jag själv vore tvuge att iföra si skulle deklaratioe i pricip se ut så här: fuktioes am fuctio si(arg : Float) -- utför beräkige utifrå arg retur t; parameters am iuti fuktioe parameters datatyp t som aropet ska leverera ts datatyp Och de deklaratioe fis i så fall där deklaratioer ormalt fis! OBS! Fuktioe utförs ite är de deklareras! Deklaratioe ager bara att de hädaefter är tillgäglig. - 3 - E ekel ege fuktio Jag vill ha e fuktio som ger y-koordiate för visst x på de räta lije y = 1,5 x - 0,75, och skriva ut åra pukter på lije: with Text_IO; use Text_IO; procedure fuc_ex package flio is ew Float_IO(Float); use flio; for cout i -50.. 50 loop x := 0.01 * Float(cout); Put(x, 5, 3, 0); Put(y_coeff(x), 8, 3, 0); ed fuc_ex; - 4 - Fuktioer - lite regler (1) Parameter (the_x i exemplet) är till för att fåga upp det ma skickar vid aropet, oavsett hur detta är kostruerat. Parameteramet är e slags geeraliserig av alla upptäkliga former på aropsparameter (aktuellt ): ext : Float; Alla följade kostruktioer är tillåta i rätt sammahag. OBS olika aktuella parametrar: y_coeff(2.3) y_coeff(x) y_coeff(ext) y_coeff(0.9 - x * x) y_coeff(si(ext / 2.0)) OBS! Det är först är fuktiosamet aväds (refereras) i ett arop som fuktioe utförs!
- 5 - Fuktioer - lite regler (2) Fuktioes parameter (the_x i exemplet) är dea fuktios ege privata egedom, och ige aa stas ä iuti fuktioe själv ka de avädas! Jämför for-satses styrvariabel. the_x kallas formell parameter. ext : Float; y := y_coeff(ext); - 6 - Fuktioer - lite regler (3) E fuktios parametrar fugerar dessutom som om de vore kostater! Det går bara att aväda dess i beräkigar, me det går ite att ge dem ågot ytt! Typiskt olagligt: fuctio Step(x : Iteger) retur Iteger is x := x + 1; Försök att tilldela x - Olagligt! retur x; På motsvarade sätt skulle förstås Get(x); vara olagligt iuti Step, liksom adra sätt att försöka ge parameter ett. ext := ext + the_x; -- Olagligt! Parameters livslägd: the_x skapas först är ett arop till y_coeff äger rum. De upphör att existera är the_x lämas. Det skapas med adra ord e y the_x för varje ytt arop! - 7 - Flera parametrar Fuktioer ka ha fler parametrar ä e, och dessa ka vara av ibördes olika datatyp. Me alla lyder uder samma regler. Öskas: E fuktio som ger de :te siffra ur ett heltal (bakifrå med start på 0). Både detta heltal och ska vara parametrar (och egetlige krävs det att är icke-egativt!): fuctio Digit(r : Iteger; : Iteger) retur Iteger is retur (r / ( ** 10)) mod 10; ed Digit; Vi kapar alltså först bort de siffror som följer efter de :te med geom att (heltals!)dividera med e potes av 10. Se plockar vi ut de då sista siffra geom att mod:a med 10. Notera att (aturligtvis) varke r eller ges ya här! - 8 - E ågot mer komplicerad fuktio (1) Det behövs e fuktio för att beräka :te rote ur e Float, där är e Iteger. Fuktioes specifikatio blir fuctio _root( : Iteger; x : Float) Notera: Ovaståede rad är tillräcklig kuskap för att kua aväda _root! Det är _roots specifikatio. Härledig av e formel: Uppgift: Hitta det a som iebär att a = x. Log a först: l a = l x l a = l x l x l a Exp a se: e = e l a där ju e = a Det iebär att t ka formuleras i Ada som Exp(Log(x) / Float())
- 9 - - 10 - E ågot mer komplicerad fuktio (2) Ett aber! Log(x) klarar aturligtvis ite av 0.0! Me för x = 0.0 ska t av _root alltid bli 0.0. Och om x är < 0.0 existerar e lösig om är udda: x = - x Me om x är < 0.0 existerar överhuvudtaget ige lösig om är jämt! Så vi låter fuktioe urskilja fyra fall grudade på x och, och som gör lite olika åtgärder: x är = 0.0 ge 0.0 tillbaka x är < 0.0, är jämt felutskrift, 0.0 x är < 0.0, är udda - formel x är > 0.0 formel Dessutom iför vi i _root e y variabel som lite stöd. E ågot mer komplicerad fuktio (3) fuctio _root( : Iteger; x : Float) sig : Float := 1.0; -- Tecket! if x = 0.0 the retur 0.0; elsif x < 0.0 the if Is_Eve() the -- Is_Eve? Put("Fel i root!"); retur 0.0; ed if; sig := -1.0; ed if; retur sig * Exp(Log(abs x) / Float()); ed _root; - 11 - - 12 - Lärdomar - utvidgigar E fuktio får iehålla vilka utförade satser som helst, i e hur låg följd som helst. retur ; måste förekomma mist e gåg. Flera förekomster är möjliga, och ofta ödvädigt, som i exemplet. Fuktioer ka också ha sia ega deklaratioer (variabel sig i exemplet). Äve här skrivs sådaa deklaratioer mella is och. Me sådaa deklaratioer (av vilket slag de ä är) existerar överhuvudtaget ite utaför fuktioe! De är liksom parametrara fuktioes privata egedom! Kosekveser, t ex: e fuktio fum ka iuti sig deklarera e aa fuktio sub. Me sub ka ite avädas av å aa del av programmet ä iifrå fum. Parametraras typ och type på t av e fuktio ka vara vilke som helst! E fuktio behöver faktiskt ite ha å parameter alls: fuctio Zero retur 0.0; ed Zero; fast just dea är gaska meigslös, de tillför iget! Om ams sylighet och livslägd procedure Mai is a : Float; x : Iteger; p : Boolea; fuctio foo(x : Float) z : Iteger; z := Iteger(x * a); fuctio fum(a, b : Iteger) x : Iteger; type Sex is (female, male); fuctio sub(a : Sex) p : Boolea; p := x > 1; p := x = 1; De am som existerar här eda är edast a, x, p, foo, fum frå Mai. titta ut ur och uppåt går alltid! titta ut ur och edåt går aldrig titta i i går aldrig
- 13 - Subrutier - procedurer Fuktioer är e form av subrutier. E aa form är procedurer. Till exempel är de ibyggda subrutie Put(x, w) (där x och w är Iteger-) e procedur. Procedurer och fuktioer har mycket gemesamt: de represeterar e bit programkod som fis å aa stas de bite kod har försetts med ett am de ka ha parametrar de utförs bara är ma gör ett arop vid aropet aväder ma amet och skickar med aktuella parametrar iom ( ) både procedurer och fuktioer ka göra ega, privata deklaratioer de ka iehålla e följd av godtyckliga satser programmerare ka själv deklarera ya procedurer och fuktioer feomee sylighet och livslägd gäller alla subrutier - 14 - Fuktioer och procedurer - ea skillade (1) Aropet av e fuktio är i sig ett, och får bara fias där ett förvätas! Aropet av e procedur är e sats (e order ), och får bara fias där e sats förvätas. Satser har ite. x, y : Float; Put(si(x - 0.5), 5, 4, 0); -- OK si(x - 0.5); -- FEL y := Put(x, 4, 4, 0); -- FEL Eftersom procedurer sakar och arope av dem ite ka igå i uttryck (formler) har deras uppgifter aa karaktär. Syftet med att aväda Put(x, w) är ju ite att skapa ågot ytt åt programmet, uta att skriva ut ett frå programmet till omvärlde! Därför ka ma aldrig es försöka deklarera e procedurs typ. Jämför följade specifikatioer: fuctio fu( : Iteger) procedure proc( : Iteger) is - 15 - - 16 - Fuktioer och procedurer - ea skillade (2) Relaterat till tidigare exempel Bctable : Utskrift av tabelles huvud där skulle mycket väl kua vara e särskild procedur: -- WriteHeader(max) skriver tabelles -- huvud med kolumera 0 - max: procedure WriteHeader(max : Iteger) is Put(" k ="); for UderValue i 0.. max loop Put(UderValue, 5); ed WriteHeader; Notera att det ite fis ågot retur blad de utförade satsera! Avslut och återhopp till aropsplatse sker automatiskt vid sista ed. Me satse retur; uta ågot bifogat ka avädas på varje plats där procedure skall avsluta sitt jobb. Fuktioer däremot måste ju ha mist e retur ; Fuktioer och procedurer - adra skillade (1) Iuti e fuktio fugerar parametrar som kostater! Det är på samma sätt med procedurer me dessa ka dessutom ha e aa form av parametrar! procedure GetPositiveIteger(x : i out Iteger) is loop Put( Ge ett heltal > 0: ); Get(x); exit whe x > 0; A, B : Iteger; GetPositiveIteger(A); GetPositiveIteger(B);
- 17 - Fuktioer och procedurer - adra skillade (2) Geom att i deklaratioe av e procedur age att e viss parameter skall vara i out talar ma om att i procedure ka det amet både avädas i ett uttryck och tilldelas ya (det är ite lägre e kostat) till de parameter måste ma vid aropet skicka med ett variabelam är procedure ger de parameter ett ytt kommer det att gälla också de medskickade (aktuella) variabel! Procedures parameteram blir alltså ett alias för det variabelam ma skickar med vid arop. Vi har att göra med två olika sk parametermodes: det ormala, där subruties parameter fugerar som e kostat, och som ka aropas med valfritt uttryck (kallas i-mode). Populistiskt: Skicka ett i out-mode, där procedures parameter fugerar som e valig variabel, och som måste aropas med ett variabelam. Populistiskt: Skicka e variabel fuktioer tillåter bara de ormala, procedurer båda formera - 18 - E jämförelse fuktio - procedur fuctio Roudig(x : Float) retur Float(Iteger(x)); procedure Roud(x : i out Float) is x := Float(Iteger(x)); De gör samma jobb me levererar resultatet på olika sätt. Därför aväds de också på olika sätt: f : Float; Put(Roudig(f), 4, 2, 0); Roud(f); Put(f, 4, 2, 0); Notera också amskillade som grudar sig på skillade mella hur de båda aväds: verbet Roud - ett kommado, e uppmaig substativet Roudig - ett objekt (= ) OBS - dea beskrivig är lite föreklad! - 19 - Värde kotra sats - e gåg till v := 1.0 - si (0.5 * pi ) ; am tilldeligssats Put(x / 2.0, 5, 3, 0) ; procedurarop, e sats Ett är alltså ett slags MÅTT - E sats säger vad som ska ske med! Sats = uppmaig eller kommado!