Programovací jazyk Ada: procedury a funkce

4. 6. 2015
Doba čtení: 5 minut

Sdílet

Minulý díl seriálu byl věnován hlavně atributům a zobrazení výstupních veličin (včetně konverze typů a zaokrouhlování). Také jsme započali kapitolu o procedurách a funkcích. Dnes se zaměříme hlavně na procedury a funkce (deklarace i volání) a na závěr se podíváme na aktuální verzi vývojového prostředí Ada.

Jak bylo uvedeno v minulém dílu, budeme deklaraci a volání procedury a funkce demonstrovat na jednoduchém příkladu (včetně spuštění a zobrazení výsledků):

with Ada.Text_IO; use Ada.Text_IO;                        --1
        procedure Ada15 is                                --2

        f,p : Integer;                                    --3

        function add (a,b :Integer) return Integer is     --4
                begin                                     --5
                        return a+b;                       --6
                end add;                                  --7

    procedure mul (a,b : in Integer; c : out Integer) is  --8
                begin                                     --9
                        c := a*b;                         --10
                end mul;                                  --11

        begin                                             --12

                f := add(2,7);                            --13
                Put_Line("F = " & F'Img);                 --14

                mul(2,7,p);                               --15
                Put_Line("P = " & P'Img);                 --16

        end Ada15;                                        --17

./ada15
F =  9
P =  14
  • Na řádku 3 jsou definované dvě celočíselné proměnné
  • Na řádcích 4 – 7 pak funkce add. Ta má dva vstupní celočíselné parametry a a b a vrací hodnotu opět celočíselnou. V těle funkce je pak návratová hodnota nastavena na součet vstupních parametrů
  • Na řádku 13 je funkce pro zadané aktuální parametry přiřazena k deklarované proměnné a ta je na dalším řádku zobrazena
  • Na řádcích 8 – 11 je definovaná procedura mul (v rámci mateřské procedury Ada15). Ta má dva vstupní parametry a a b a jeden výstupní parametr c. Všechny parametry jsou celočíselné. V těle procedury je do výstupního parametru přiřazen součin vstupních parametrů
  • Na řádku 15 je pak volání procedury, kde musí být uvedeny všechny parametry – jsou tam zadané vstupní parametry a také proměnná, která představuje hodnotu výstupního parametru. Ta je pak na dalším řádku zobrazena.

Výsledný kód je v příloze ada15Pokud uděláme jednu malou změnu:

function add (a,b :Integer := 0) return Integer is

Na výsledku se nic nezmění. Touto změnou jsme zadali výchozí hodnotu obou vstupních parametrů. A nyní můžeme použít několik variant volání funkce:

  1. add (2,7);
    A = 2, B = 7, C = 9
  2. add (2);
    A = 2, B = 0, C = 2
  3. add;
    A = 0, B = 0, C = 0
  4. add (B => 7);
    A = 0, B = 7, C = 7
  5. add (2, B => 7);
    A = 2, B = 7, C = 9
  6. add (A => 2, B => 7);
    A = 2, B = 7, C = 9

Poslední tři varianty ukazují, jak je možné stanovit aktuální hodnoty parametrů velmi „čitelně“ a „průhledně“ s pomocí zadání jejich názvu. Ada umožňuje nejenom přímé zadání aktuálních parametrů uživatelských funkcí a procedur, ale také procedur ze standardních i nadstavbových knihoven, a to včetně „přejmenování“ parametrů. Ada dává k dispozici knihovnu se základní sadou numerických funkcí – jejich přehled např. zde: Numerické funkce Ada 2012

Jak je z přehledu patrné, prakticky všechny deklarované funkce mají na pozici formálních parametrů znaky X či Y. Tyto funkce je možné volat dvojím způsobem:

  1. fi := Arctan(A,B);
    Je to samozřejmě běžné a běžně používané volání a na první pohled na něm není vidět žádný problém nebo potenciální riziko
  2. fi := Arctan(Y =>A, X => B);
    Druhé volání je sice dost nezvyklé, ale na druhou stranu velmi jednoznačné tím, že jasně udává vztah mezi aktuálními a formálními parametry. To samozřejmě vede k lepší přehlednosti a čitelnosti kódu a působí preventivně proti chybám.

Jako jiné jazyky i Ada nabízí možnost volání funkcí rekurzivně, což si ukážeme na novém a oblíbeném příkladu výpočtu faktoriálu. Kód je zde:

with Ada.Text_IO; use Ada.Text_IO;
    procedure Ada16 is

    a,f : Integer;

    function Faktorial (N : Positive) return Positive is
        begin
            if N = 1 then
                return 1;
            else
                return (N * Faktorial (N - 1));
            end if;
    end Faktorial;

    begin

        a := 7;
        f := Faktorial(a);
        Put_Line("Faktorial " & A'Img & " = " & F'Img);

    end Ada16;

Uvedený kód asi ničím moc nepřekvapí. Jediné, na co by bylo vhodné upozornit, je deklarace parametru a typu funkce jako Positive. Touto deklarací se vlastně obejde nutnost uživatelsky kontrolovat rozsah zadávaných parametrů a nechat tuto „černou“ práci na systému překladače. Při normálním zadání vypadá výsledek asi takto:

./ada16
Faktorial  7 =  5040

Pokud bychom ale volali funkce s parametrem nula, bude to vypadat jinak už při pokusu o překlad:

gnatmake ada16.adb
gcc -c ada16.adb
ada16.adb:19:32: warning: value not in range of type "Standard.Positive"
ada16.adb:19:32: warning: "Constraint_Error" will be raised at run time
gnatbind -x ada16.ali
gnatlink ada16.ali

./ada16
raised CONSTRAINT_ERROR : ada16.adb:19 range check failed

Kompletní kód je v příloze ada16.

Bylo by asi vhodné se ještě jednou vrátit k typům parametrů procedur a blíže si ukázat, jak mohou fungovat parametry typu in out. Ty totiž nejsou úplně běžně používané, a tak by jeden malý příklad určitě neuškodil. Vytvoříme si tedy další jednoduchý kód, který snad vše objasní bez velkých komentářů:

with Ada.Text_IO; use Ada.Text_IO;
    procedure Ada17 is

    d,t,p : Integer := 4;

    procedure inout (Double, Triple, Power : in out Integer) is
        begin
            Double := Double *2;
            Triple := Triple *3;
            Power := Power**2;
        end inout;

    begin

        inout(d,t,p);
        Put_Line("Double = " & D'Img);
        Put_Line("Triple = " & T'Img);
        Put_Line("Power = " & P'Img);

    end Ada17;

./ada17
Double =  8
Triple =  12
Power =  16

Na jednoduchém příkladu je vidět, jak funguje kombinace vstupně-výstupních parametrů, kdy se zadá aktuální hodnota, v těle procedury se změní hodnota formálního parametru, která je opět jako výstupní předána do volání procedury. Kompletní kód je v příloze ada17.

ict ve školství 24

Ještě než se pustíme do samotného popisu a instalace nejnovější verze vývojových nástrojů, krátce se zaměříme na to, jak zjistit aktuálně instalovanou verzi. Je to samozřejmě možné provést několika způsoby, ale my si vybereme dva. Jedná se o následující dva příkazy:

# ~$ gnatmake --version

GNATMAKE 4.8.2
Copyright (C) 1995-2013, Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# ~$ gnatls -v

GNATLS 4.8.2
Copyright (C) 1997-2013, Free Software Foundation, Inc.

Source Search Path:
   <current_directory>
   /usr/lib64/gcc/x86_64-slackware-linux/4.8.2/adainclude/

Object Search Path:
   <current_directory>
   /usr/lib64/gcc/x86_64-slackware-linux/4.8.2/adalib/

Project Search Path:
   <current_directory>
   /usr/x86_64-slackware-linux/lib/gnat
   /usr/share/gpr
   /usr/lib/gnat

Tím ukončíme část seriálu, která se věnuje základním prvkům jazyka, které jsou nutné pro vytváření jednoduchých úloh. V příštím dílu se posuneme trochu dál a ukážeme si instalaci nejnovější verze překladače Ada včetně pomocných aplikací a zajímavého vývojového prostředí.

Autor článku