Funkce a metody v programovacím jazyku C3 (dokončení)

30. 10. 2025
Doba čtení: 40 minut

Sdílet

Programovací jazyk C3
Autor: Root.cz s využitím Zoner AI
Navážeme na článek, ve kterém jsme si popsali základní koncepty pro práci s funkcemi. Popíšeme si deklaraci typu „funkce“, zkrácený zápis funkcí, anonymní funkce, metody (vztažené k typu) a způsob využití ukazatelů na funkce.

Obsah

1. Funkce v programovacím jazyku C3 (dokončení)

2. Zkrácený zápis těl funkcí

3. Komplikovanější ukázky zkráceného zápisu těl funkcí

4. Anonymní funkce

5. Funkce typu reduce

6. Volání funkce reduce s předáním anonymní funkce v prvním parametru

7. Přímé zavolání právě definované anonymní funkce

8. Uzávěry v jazyce C3?

9. Ukazatele na funkce

10. Funkce vracející jinou funkci

11. Úplný zdrojový kód demonstračního příkladu: funkce vyššího řádu v jazyku C3

12. Volání nativních céčkovských funkcí

13. Volání nativní céčkové funkce ze staticky či dynamicky linkované knihovny

14. Datové typy používané při volání nativních céčkových funkcí

15. Demonstrační příklad – použití korektních datových typů pro volání nativní funkce

16. Volání nativní funkce, která akceptuje ukazatel na (první) prvek pole

17. Metody v jazyce C3

18. Druhý způsob volání metod

19. Repositář s demonstračními příklady

20. Odkazy na Internetu

1. Funkce v programovacím jazyku C3 (dokončení)

V předchozím článku o programovacím jazyku C3 jsme si ukázali, jakým způsobem se pracuje s funkcemi, které tvoří základní (a velmi pravděpodobně i nejdůležitější) úroveň abstrakce. Připomeňme si, že kromě běžných funkcí s pozičními argumenty podporuje jazyk C3 i specifikaci výchozích hodnot parametrů funkce, při volání funkce je možné explicitně uvést jména parametrů a podporovány jsou i funkce s proměnným počtem parametrů (s nimiž se pracuje jednodušeji, než s podobnými funkcemi v jazyku C). Ovšem v C3 lze pracovat i s hodnotami typu Optional a proto existuje speciální operátor používaný při volání funkcí vracejících tyto hodnoty. A nakonec jsme si popsali takzvané kontrakty a specifikaci, zda jsou hodnoty předávané ukazatelem určeny pouze pro čtení nebo i pro zápis.

Dnes popis použití funkcí v programovacím jazyku C3 dokončíme. Ukážeme si způsob zkráceného zápisu těla funkcí, definici a volání (či předání) anonymních funkcí, přesvědčíme se, že jazyk C3 nepodporuje uzávěry, popíšeme si způsob volání nativních céčkovských funkcí a nakonec si ukážeme volání takzvaných metod, což jsou funkce navázané na konkrétní datový typ.

2. Zkrácený zápis těl funkcí

Programovací jazyk C3 podporuje takzvaný zkrácený zápis funkcí, který se využije tehdy, pokud je možné funkci přepsat do podoby, kdy její tělo obsahuje pouze příkaz return (s libovolně složitým výrazem). Takové funkce se v praxi používají poměrně často a jejich „plný“ zápis může být zbytečně dlouhý. Příkladem může být funkce nazvaná add, v jejímž těle se skutečně nachází pouze jediný příkaz return:

module functions;
import std::io;
 
fn int add(int a, int b)
{
    return a+b;
}
 
fn void main()
{
    io::printf("%d+%d=%d\n", 1, 2, add(1, 2));
}

Funkci add můžeme zkrátit takovým způsobem, že její hlavička i tělo (tvořené jediným příkazem return) budou zapsány na jediném programovém řádku. Namísto běžného těla s příkazem return se zapíše šipka =>, za kterou následuje výraz. Po zavolání funkce bude tento výraz vyhodnocen a jeho výsledek bude současně i návratovou hodnotou volané funkce:

module functions;
import std::io;
 
fn int add(int a, int b) => a+b;
 
fn void main()
{
    io::printf("%d+%d=%d\n", 1, 2, add(1, 2));
}

3. Komplikovanější ukázky zkráceného zápisu těl funkcí

Podívejme se na další funkce, které jsou zapsány zkráceným způsobem. Vždy si nejdříve ukážeme původní zdrojový kód příkladu s běžně zapsanou funkcí a posléze zkrácený zápis funkce.

Funkce add s výchozí hodnotou svého druhého parametru:

module functions;
import std::io;
 
fn int add(int a, int b=0)
{
    return a+b;
}
 
fn void main()
{
    io::printf("%d+%d=%d\n", 1, 0, add(1));
    io::printf("%d+%d=%d\n", 1, 2, add(1, 2));
}

Zkrácený způsob zápisu funkce add:

module functions;
import std::io;
 
fn int add(int a, int b=0) => a+b;
 
fn void main()
{
    io::printf("%d+%d=%d\n", 1, 0, add(1));
    io::printf("%d+%d=%d\n", 1, 2, add(1, 2));
}

Funkce add, která má specifikovány výchozí hodnoty pro oba své parametry:

module functions;
import std::io;
 
fn int add(int a=0, int b=0)
{
    return a+b;
}
 
fn void main()
{
    io::printf("%d+%d=%d\n", 0, 0, add());
    io::printf("%d+%d=%d\n", 1, 0, add(1));
    io::printf("%d+%d=%d\n", 1, 2, add(1, 2));
}

Zkrácený způsob zápisu funkce add:

module functions;
import std::io;
 
fn int add(int a=0, int b=0) => a+b;
 
fn void main()
{
    io::printf("%d+%d=%d\n", 0, 0, add());
    io::printf("%d+%d=%d\n", 1, 0, add(1));
    io::printf("%d+%d=%d\n", 1, 2, add(1, 2));
}

Funkce div s běžnou dvojicí parametrů. Při volání funkce jsou explicitně uvedena jména parametrů:

module functions;
import std::io;
 
fn int div(int a, int b)
{
    return a/b;
}
 
fn void main()
{
    io::printf("%d/%d=%d\n", 10, 2, div(a:10, b:2));
    io::printf("%d/%d=%d\n", 10, 3, div(a:10, b:3));
}

Zkrácený způsob zápisu funkce div:

module functions;
import std::io;
 
fn int div(int a, int b) => a/b;
 
fn void main()
{
    io::printf("%d/%d=%d\n", 10, 2, div(a:10, b:2));
    io::printf("%d/%d=%d\n", 10, 3, div(a:10, b:3));
}

Funkce div s výchozí hodnotou parametrů a navíc vracející hodnotu typu Optional:

module functions;
import std::io;
 
faultdef ZERO_INPUT;
 
fn int? div(int a=1, int b=1)
{
    if (b==0) {
        return ZERO_INPUT?;
    }
    return a/b;
}
 
fn void main()
{
    (void)io::printf("%d/%d=%d\n", 1, 1, div());
    (void)io::printf("%d/%d=%d\n", 10, 1, div(a:10));
    (void)io::printf("%d/%d=%d\n", 10, 2, div(a:10, b:2));
    (void)io::printf("%d/%d=%d\n", 10, 3, div(a:10, b:3));
    (void)io::printf("%d/%d=%d\n", 10, 0, div(a:10, b:0));
}

Ve zkráceném zápisu takto upravené funkce div je nutné použít ternární operátor namísto programové konstrukce if-then-else:

module functions;
import std::io;
 
faultdef ZERO_INPUT;
 
fn int? div(int a=1, int b=1) => b==0 ? ZERO_INPUT? : a/b;
 
fn void main()
{
    (void)io::printf("%d/%d=%d\n", 1, 1, div());
    (void)io::printf("%d/%d=%d\n", 10, 1, div(a:10));
    (void)io::printf("%d/%d=%d\n", 10, 2, div(a:10, b:2));
    (void)io::printf("%d/%d=%d\n", 10, 3, div(a:10, b:3));
    (void)io::printf("%d/%d=%d\n", 10, 0, div(a:10, b:0));
}

Funkce first akceptující proměnný počet parametrů:

module functions;
import std::io;
 
fn int first(int... args)
{
    int f = args[0];
    return f;
}
 
fn void main()
{
    int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    io::printf("%d\n", first(1));
    io::printf("%d\n", first(1, 2));
    io::printf("%d\n", first(1, 2, 3));
    io::printf("%d\n", first(...values));
}

Zkrácený způsob zápisu funkce first:

module functions;
import std::io;
 
fn int first(int... args) => args[0];
 
fn void main()
{
    int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    io::printf("%d\n", first(1));
    io::printf("%d\n", first(1, 2));
    io::printf("%d\n", first(1, 2, 3));
    io::printf("%d\n", first(...values));
}

4. Anonymní funkce

Programovací jazyk C3 podporuje i zápis anonymních funkcí (anonymous functions), které se od „běžných“ funkcí liší tím, že v jejich definici není použito jméno definované funkce. Definice anonymní funkce může být uvedena v takových místech zdrojového kódu, ve kterém se očekává zápis parametru volané funkce, definice lokální hodnoty atd.

Nejdříve se podívejme na demonstrační příklad, ve kterém anonymní funkce nejsou použity. V příkladu je definována dvojice běžných (neanonymních) funkcí, které provedou součet (sumu) či součin (produkt) všech svých parametrů a vrátí výsledek tohoto výpočtu. Tyto funkce jsou volány z main:

module functions;
import std::io;
 
fn int reduce_add(int... args)
{
    int acc = 0;
    foreach (arg : args) {
        acc += arg;
    }
    return acc;
}
 
fn int reduce_mul(int... args)
{
    int acc = 1;
    foreach (arg : args) {
        acc *= arg;
    }
    return acc;
}
 
fn void main()
{
    int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    io::printf("%d\n", reduce_add(...values));
    io::printf("%d\n", reduce_mul(...values));
}

Tento příklad je sice plně funkční, ovšem opakuje se v něm prakticky stejná část kódu – konkrétně programová smyčka foreach. Bylo by tedy možná vhodné nahradit obě dvě logicky stejné funkce nějakou obecnější funkcí. A právě zde je možné použít anonymní funkce.

5. Funkce typu reduce

Demonstrační příklad z předchozí kapitoly je možné přepsat do obecnější podoby. Nejprve v něm definujeme nový datový typ „funkce“, konkrétně „funkce akceptující dva parametry typu int a vracející hodnotu typu int“:

alias ReduceOpp = fn int(int, int);

Následně můžeme napsat dosti obecnou funkci nazvanou reduce, která akceptuje tři parametry:

  1. Funkci typu ReduceOpp, která postupně zpracuje n vstupních hodnot (ano, funkci, resp. její adresu je možné předat do jiné funkce)
  2. Výchozí hodnotu uloženou do akumulátoru ještě před postupným zpracováním (redukcí) předaných hodnot
  3. Proměnný počet parametrů, které budou postupně zpracovány (redukovány) funkcí předanou v prvním parametru

Funkce reduce může vypadat následovně:

fn int reduce(ReduceOpp operation, int init, int... args)
{
    int acc = init;
    foreach (arg : args) {
        acc = operation(acc, arg);
    }
    return acc;
}

6. Volání funkce reduce s předáním anonymní funkce v prvním parametru

Výše uvedenou funkci reduce můžeme použít jako pro výpočet sumy, tak i pro vynásobení všech předaných hodnot. Pro výpočet sumy postačuje zavolat:

int vysledek = reduce(fn (int a, b) => a+b, 0, ...values);

Naopak vynásobení všech předaných hodnot lze realizovat takto:

int vysledek = reduce(fn (int a, b) => a*b, 1, ...values);
Poznámka: povšimněte si, že v obou případech v prvním parametru přímo předáváme definovanou anonymní funkci, tj. funkci, která nemá ve své definici uvedené své jméno.

Příklad použití:

module functions;
import std::io;
 
alias ReduceOpp = fn int(int, int);
 
fn int reduce(ReduceOpp operation, int init, int... args)
{
    int acc = init;
    foreach (arg : args) {
        acc = operation(acc, arg);
    }
    return acc;
}
 
fn void main()
{
    int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    io::printf("%d\n", reduce(fn (int a, b) => a+b, 0, ...values));
    io::printf("%d\n", reduce(fn (int a, b) => a*b, 1, ...values));
}

Ověřme si funkčnost tohoto programu:

$ c3c compile-run 33_anonymous.c3
 
Program linked to executable './functions'.
Launching ./functions
55
3628800

7. Přímé zavolání právě definované anonymní funkce

Zápis anonymní funkce pro překladač jazyka C3 znamená, že taková funkce bude přeložena do strojového kódu a bude ji tak možné ihned zavolat. To lze pochopitelně provést i v praxi. V následujícím demonstračním příkladu je (kromě dalších definic) definována i anonymní funkce, která vynásobí hodnotu předaného celočíselného parametru dvěma a vrátí výsledek tohoto součinu. Tato funkce je ihned (na stejném programovém řádku) zavolána – je jí předána hodnota proměnné x a výsledek je uložen do proměnné y. Povšimněte si zejména toho, jak je definice anonymní funkce umístěna do kulatých závorek:

module functions;
import std::io;
 
fn void main()
{
    int x = 10;
 
    int y = (fn int(int a) => a*2)(x);
 
    io::printf("%d\n", x);
    io::printf("%d\n", y);
}

Ověření funkcionality tohoto řešení:

$ c3c compile-run 34_anonymous.c3
 
Program linked to executable './functions'.
Launching ./functions
10
20

8. Uzávěry v jazyce C3?

Vzhledem k tomu, že překladač programovacího jazyka C3 akceptuje zkrácený zápis funkcí a současně i podporuje práci s anonymními funkcemi, by se mohlo zdát, že jsou podporovány i uzávěry (closures), tj. funkce, které mají přístup ke svému okolí (prostředí, environment). Ovšem ve skutečnosti tomu tak není, což si můžeme velmi snadno ověřit na následujícím příkladu, ve kterém se snažíme v těle anonymní funkce přistoupit (dokonce jen přečíst, nikoli modifikovat) k lokální proměnné b:

module functions;
import std::io;
 
fn void main()
{
    int x = 10;
    int b = 2;
 
    int y = (fn int(int a) => a*b)(x);
 
    io::printf("%d\n", x);
    io::printf("%d\n", y);
}

Při pokusu o překlad tohoto příkladu dojde k chybě při překladu, protože z těla anonymní funkce není proměnná b viditelná:

$ c3c compile-run 35_anonymous.c3
 
 6:     int x = 10;
 7:     int b = 2;
 8:
 9:     int y = (fn int(int a) => a*b)(x);
                                    ^
(/home/ptisnovs/src/c3-examples/c3-functions/35_anonymous.c3:9:33) Error: 'b' could not be found, did you spell it right?
Poznámka: jedná se sice o značné omezení, na druhou stranu však má překladač jazyka C3 a především jeho běhové prostředí mnohem jednodušší práci – není nutné sledovat životnost hodnot atd.

9. Ukazatele na funkce

V předchozích kapitolách jsme si ukázali zdrojový kód, ve kterém se do funkce reduce předávaly anonymní funkce:

    io::printf("%d\n", reduce(fn (int a, b) => a+b, 0, ...values));
    io::printf("%d\n", reduce(fn (int a, b) => a*b, 1, ...values));

Jak se ovšem takový příklad musí upravit ve chvíli, kdy budeme chtít předat běžné (pojmenované) funkce, například funkce add a mul?

fn int add(int a, int b)
{
    return a+b;
}
 
fn int mul(int a, int b)
{
    return a*b;
}

V tomto případě je nutné předat nikoli jméno funkce, ale ukazatel na funkci, tj. zápis musí vypadat takto:

    io::printf("%d\n", reduce(&add, 0, ...values));
    io::printf("%d\n", reduce(&mul, 1, ...values));
Poznámka: to znamená, že funkce se chovají podobně, jako jakékoli jiné hodnoty – i na ně lze získat ukazatel.

Chování jazyka C3 si otestujeme na takto upraveném demonstračním příkladu:

module functions;
import std::io;
 
alias ReduceOpp = fn int(int, int);
 
fn int add(int a, int b)
{
    return a+b;
}
 
fn int mul(int a, int b)
{
    return a*b;
}
 
fn int reduce(ReduceOpp operation, int init, int... args)
{
    int acc = init;
    foreach (arg : args) {
        acc = operation(acc, arg);
    }
    return acc;
}
 
fn void main()
{
    int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    io::printf("%d\n", reduce(&add, 0, ...values));
    io::printf("%d\n", reduce(&mul, 1, ...values));
}

Samozřejmě je i v tomto případě stále možné použít alternativní způsob definice funkcí add a mul s tělem obsahujícím jen příkaz return zapsaný krátkým způsobem:

module functions;
import std::io;
 
alias ReduceOpp = fn int(int, int);
 
fn int add(int a, int b) => a+b;
fn int mul(int a, int b) => a*b;
 
fn int reduce(ReduceOpp operation, int init, int... args)
{
    int acc = init;
    foreach (arg : args) {
        acc = operation(acc, arg);
    }
    return acc;
}
 
fn void main()
{
    int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    io::printf("%d\n", reduce(&add, 0, ...values));
    io::printf("%d\n", reduce(&mul, 1, ...values));
}

10. Funkce vracející jinou funkci

V rámci předchozích kapitol jsme si ukázali, jakým způsobem je možné předat do nějaké funkce jinou funkci (resp. ukazatel na ni). Podobně lze funkci z jiné funkce vrátit – funkce (interně ukazatel) jsou totiž v programovacím jazyku C3 považovány za plnohodnotný datový typ. Ukažme si to na příkladu funkce, která vrátí implementaci nějakého binárního aritmetického operátoru. Typ návratového hodnoty je definován následovně:

alias ReduceOpp = fn int(int, int);

Funkce nazvaná get_operation_implementation vrátí na základě předaného parametru (jeden znak s reprezentací binárního aritmetického operátoru) implementaci takového operátoru. Vracet budeme anonymní funkce:

fn ReduceOpp get_operation_implementation(char operator)
{
    switch (operator) {
        case '+':
            return fn (int a, b) => a+b;
        case '-':
            return fn (int a, b) => a-b;
        case '*':
            return fn (int a, b) => a*b;
        case '/':
            return fn (int a, b) => a/b;
        default:
            return fn (int a, b) => 0;
    }
}

Do funkce reduce, kterou již známe, budeme předávat právě hodnotu získanou voláním funkce get_operation_implementation:

    int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    io::printf("%d\n", reduce(get_operation_implementation('+'), 0, ...values));
    io::printf("%d\n", reduce(get_operation_implementation('-'), 0, ...values));
    io::printf("%d\n", reduce(get_operation_implementation('*'), 1, ...values));
    io::printf("%d\n", reduce(get_operation_implementation('/'), 1000000000, ...values));

S výsledky:

55
-55
3628800
275

11. Úplný zdrojový kód demonstračního příkladu: funkce vyššího řádu v jazyku C3

Ukažme si pro úplnost celý zdrojový kód takto naprogramovaného demonstračního příkladu:

module functions;
import std::io;
 
alias ReduceOpp = fn int(int, int);
 
fn ReduceOpp get_operation_implementation(char operator)
{
    switch (operator) {
        case '+':
            return fn (int a, b) => a+b;
        case '-':
            return fn (int a, b) => a-b;
        case '*':
            return fn (int a, b) => a*b;
        case '/':
            return fn (int a, b) => a/b;
        default:
            return fn (int a, b) => 0;
    }
}
 
fn int reduce(ReduceOpp operation, int init, int... args)
{
    int acc = init;
    foreach (arg : args) {
        acc = operation(acc, arg);
    }
    return acc;
}
 
fn void main()
{
    int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    io::printf("%d\n", reduce(get_operation_implementation('+'), 0, ...values));
    io::printf("%d\n", reduce(get_operation_implementation('-'), 0, ...values));
    io::printf("%d\n", reduce(get_operation_implementation('*'), 1, ...values));
    io::printf("%d\n", reduce(get_operation_implementation('/'), 1000000000, ...values));
}

12. Volání nativních céčkovských funkcí

Jednou z velkých předností programovacího jazyka C3 je jeho téměř bezproblémové rozhraní umožňující volání nativních funkcí, které jsou typicky naprogramovány v jazyku C. Ve zdrojovém kódu C3 je nutné uvést hlavičku volané nativní funkce. Následně je možné takovou funkci přímo volat a předávat jí nativní hodnoty spravované jazykem C3. Vzhledem k tomu, že oba programovací jazyky jsou od sebe v některých ohledech odlišné, není rozhraní C3 ↔ C zcela bezproblémové. Na některé nejdůležitější rozdíly se podíváme v dalších kapitolách.

Nejjednodušší je situace ve chvíli, kdy potřebujeme volat nějakou funkci ze standardní knihovny jazyka C. V takovém případě nemusíme upravovat způsob překladu programu; pouze uvedeme hlavičku volané funkce (zde puts) a následně ji můžeme volat naprosto stejným způsobem, jako jakoukoli jinou funkci definovanou přímo v jazyku C3:

module functions;
 
extern fn void puts(char*);
 
fn void main()
{
    puts("Hello, world!");
}

13. Volání nativní céčkové funkce ze staticky či dynamicky linkované knihovny

Vyzkoušejme si nyní zavolat nativní céčkovou funkci, která bude přeložena do staticky nebo dynamicky linkované knihovny. Definice takové funkce (v céčku) je triviální:

extern int add(int x, int y)
{
    return x+y;
}

Provedeme překlad této funkce do objektového kódu s vložením tohoto kódu do sdílené knihovny libadder.so:

gcc -Wall -ansi -c -fPIC adder.c -o adder.o
 
gcc -shared -Wl,-soname,libadder.so -o libadder.so adder.o

Volání takové funkce z jazyka C3 je snadné:

module functions;
import std::io;
 
extern fn int add(int a, int b);
 
fn void main()
{
    io::printf("%d\n", add(1, 2));
}

Při překladu tohoto příkladu je nutné překladači předat i jméno sdílené knihovny:

$ c3c compile -l libadder.so 40_call_c_function.c3
Program linked to executable './functions'.

Před spuštěním takto přeloženého programu si nastavte cestu ke sdíleným knihovnám:

$ export LD_LIBRARY_PATH=.

Ověření funkcionality:

$ ./functions
 
3

14. Datové typy používané při volání nativních céčkových funkcí

Při volání nativních céčkových funkcí je nutné si dát pozor na správné použití datových typů. Jazyk C3 programátorům nabízí běžnou „sadu“ celočíselných datových typů, a to jak typů se znaménkem, tak i bez znaménka. U všech těchto typů je definitoricky určena jejich velikost v bajtech i rozsah hodnot (minimální a maximální hodnota) – a to na všech platformách. V céčku je tomu však odlišně a proto nebývá vhodné používat v předběžné deklaraci externích (nativních) funkcí základní typy jazyka C3, ale typy, jejichž název začíná velkým C:

Typ v C3 Odpovídající typ v C
CChar char
CShort short int
CUShort unsigned short int
CInt int
CUInt unsigned int
CLong long int
CULong unsigned long int
CLongLong long long
CULongLong unsigned long long
CLongDouble long double

15. Demonstrační příklad – použití korektních datových typů pro volání nativní funkce

Podívejme se nyní na způsob použití datových typů uvedených v předchozí kapitole. Mějme céčkovskou funkci, která dokáže vynásobit dvojici hodnot typu long, přičemž výsledek bude taktéž typu long:

extern long multiply(long x, long y)
{
    return x*y;
}

Ovšem typ long v jazyku C nemusí být totožný s typem long v jazyku C3. Rozdíly budou viditelné například na 32bitových platformách. Proto musíme na straně C3 použít typ CLong a ponechat na překladači C3 typovou analýzu a popř. hlášení o nekompatibilních datových typech:

extern fn CLong multiply(CLong a, CLong b);

Celý zdrojový kód demonstračního příkladu, který bude volat nativní céčkovskou funkci multiply, může vypadat následovně:

module functions;
import std::io;
 
extern fn CLong multiply(CLong a, CLong b);
 
fn void main()
{
    long a = 6L;
    long b = 7L;
    io::printf("%d\n", multiply(a, b));
    io::printf("%d\n", a*b);
    io::printf("%b\n", a*b == multiply(a, b));
}

16. Volání nativní funkce, která akceptuje ukazatel na (první) prvek pole

V praxi se velmi často setkáme s nativními funkcemi, které jako svůj parametr akceptují pole. Příkladem může být céčkovská funkce, která sečte všech length prvků pole:

extern int sum(int values[], int length)
{
    int i;
    int acc = 0;
    for (i=0; i<length; i++) {
        acc += values[i];
    }
    return acc;
}

Alternativní způsob zápisu takové funkce naznačuje, že se pole ve skutečnosti předává odkazem, konkrétně jako ukazatel na první prvek pole:

extern int sum(int *values, int length)
{
    int i;
    int acc = 0;
    for (i=0; i<length; i++) {
        acc += values[i];
    }
    return acc;
}

Na straně jazyka C3 je nutné specifikovat, že se skutečně bude předávat ukazatel. To je nutné, protože zápis s prázdnými hranatými závorkami bude mít odlišný význam:

extern fn int sum(int *values, int length);

Příklad volání funkce sum z jazyka C3:

int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
io::printf("%d\n", sum(&values, 10));

Celý demonstrační příklad by mohl vypadat následovně:

module functions;
import std::io;
 
extern fn int sum(int *values, int length);
 
fn void main()
{
    int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    io::printf("%d\n", sum(&values, 10));
}

Výsledek:

55

Ovšem můžeme taktéž využít faktu, že jazyk C3 podporuje řezy a psát:

int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] slice = &values;
io::printf("%d\n", sum(slice, slice.len));

Upravený demonstrační příklad nyní bude vypadat následovně:

module functions;
import std::io;
 
extern fn int sum(int *values, int length);
 
fn void main()
{
    int[10] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int[] slice = &values;
    io::printf("%d\n", sum(slice, slice.len));
}

17. Metody v jazyce C3

V programovacím jazyce C3 lze definovat i metody. Jedná se vlastně o funkce vztažené k nějakému datovému typu. Metody je možné volat dvěma rozličnými způsoby, které si oba ukážeme.

Nejprve si zadefinujeme nějaký uživatelský datový typ. Pro jednoduchost se může jednat o reprezentaci vektoru v 3D prostoru pomocí tří složek:

struct Vector3d
{
    int x;
    int y;
    int z;
}

Pokud budeme chtít pro tento datový typ definovat metodu, například metodu pro součet dvou vektorů, může řešení vypadat následovně. Tato metoda mění (mutuje) první vektor, který je jí předán:

fn void Vector3d.add(Vector3d* first, Vector3d* second)
{
    first.x += second.x;
    first.y += second.y;
    first.z += second.z;
}
Poznámka: ve skutečnosti nemusí být druhý parametr předáván odkazem (přes ukazatel) ale přímo hodnotou.

Výše uvedenou metodu můžeme volat tak, jakoby se jednalo o funkci umístěnou ve jmenném prostoru Vector3d:

Vector3d v1 = {1, 2, 3};
Vector3d v2 = {10, 10, 10};
 
Vector3d.add(&v1, &v2);

Celý příklad s definicí metody i s jejím voláním může vypadat následovně:

module functions;
import std::io;
 
struct Vector3d
{
    int x;
    int y;
    int z;
}
 
fn void Vector3d.add(Vector3d* first, Vector3d* second)
{
    first.x += second.x;
    first.y += second.y;
    first.z += second.z;
}
 
fn void main()
{
    Vector3d v1 = {1, 2, 3};
    Vector3d v2 = {10, 10, 10};
 
    Vector3d.add(&v1, &v2);
 
    io::printf("[%d %d %d]\n", v1.x, v1.y, v1.z);
}

Otestování funkcionality tohoto demonstračního příkladu:

[11 12 13]

Varianta, ve které je druhý vektor předán hodnotou:

module functions;
import std::io;
 
struct Vector3d
{
    int x;
    int y;
    int z;
}
 
fn void Vector3d.add(Vector3d* first, Vector3d second)
{
    first.x += second.x;
    first.y += second.y;
    first.z += second.z;
}
 
fn void main()
{
    Vector3d v1 = {1, 2, 3};
    Vector3d v2 = {10, 10, 10};
 
    Vector3d.add(&v1, v2);
 
    io::printf("[%d %d %d]\n", v1.x, v1.y, v1.z);
}

Ovšem na druhou stranu další příklad již funkční nebude, resp. nebude modifikovat první vektor předaný do metody!

module functions;
import std::io;
 
struct Vector3d
{
    int x;
    int y;
    int z;
}
 
fn void Vector3d.add(Vector3d first, Vector3d second)
{
    first.x += second.x;
    first.y += second.y;
    first.z += second.z;
}
 
fn void main()
{
    Vector3d v1 = {1, 2, 3};
    Vector3d v2 = {10, 10, 10};
 
    Vector3d.add(v1, v2);
 
    io::printf("[%d %d %d]\n", v1.x, v1.y, v1.z);
}

18. Druhý způsob volání metod

Ve skutečnosti není výše uvedené volání metody:

    Vector3d.add(&v1, &v2);

v mnoha programovacích jazycích příliš idiomatické. Z tohoto důvodu nabízí programovací jazyk C3 i známější a dnes používanější způsob zápisu volání metody:

v1.add(&v2);
Poznámka: povšimněte si, že není nutné rozlišovat, jestli je první parametr metody (příjemce) předán hodnotou nebo odkazem (přes ukazatel).

Pro úplnost si uveďme úplný zdrojový kód demonstračního příkladu upraveného do podoby, ve které se používá idiomatičtější způsob zápisu volání metody:

module functions;
import std::io;
 
struct Vector3d
{
    int x;
    int y;
    int z;
}

fn void Vector3d.add(Vector3d* first, Vector3d* second)
{
    first.x += second.x;
    first.y += second.y;
    first.z += second.z;
}
 
fn void main()
{
    Vector3d v1 = {1, 2, 3};
    Vector3d v2 = {10, 10, 10};
 
    v1.add(&v2);
 
    io::printf("[%d %d %d]\n", v1.x, v1.y, v1.z);
}

Otestování funkcionality:

[11 12 13]

19. Repositář s demonstračními příklady

Demonstrační příklady vytvořené pro nejnovější verzi programovacího jazyka C3 byly uloženy do repositáře dostupného na adrese https://github.com/tisnik/c3-examples. Následují odkazy na jednotlivé příklady (či jejich nedokončené části).

Demonstrační příklady z prvního článku o programovacím jazyku C3:

# Příklad Stručný popis Adresa
1 factorial.c3 realizace výpočtu faktoriálu https://github.com/tisnik/c3-examples/blob/master/intro­duction/factorial.c3
2 factorial_macro.c3 výpočet faktoriálu konkrétní hodnoty implementovaný formou makra https://github.com/tisnik/c3-examples/blob/master/intro­duction/factorial_macro.c3
       
3 swap_macro.c3 makro realizující prohození dvou hodnot https://github.com/tisnik/c3-examples/blob/master/intro­duction/swap_macro.c3
       
4 renderer.c výpočet a vykreslení Juliovy množiny implementovaný v jazyku C https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer.c
5 renderer_v1.c3 definice datové struktury s rozměry rastrového obrázku a skeleton všech funkcí https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v1.c3
6 renderer_v2.c3 anotace parametrů funkcí typu ukazatel (pointer) https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v2.c3
7 renderer_v3.c3 statická kontrola, zda se nepředávají neinicializované ukazatele https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v3.c3
8 renderer_v4.c3 runtime kontrola, zda se nepředávají neinicializované ukazatele https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v4.c3
9 renderer_v5.c3 první (nekorektní) varianta funkce pro inicializaci barvové palety https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v5.c3
10 renderer_v6.c3 druhá (korektní) varianta funkce pro inicializaci barvové palety https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v6.c3
11 renderer_v7.c3 volání knihovní I/O funkce a volání nativní céčkovské funkce https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v7.c3
12 renderer_v8.c3 plně funkční program pro výpočet a vykreslení Juliovy množiny https://github.com/tisnik/c3-examples/blob/master/intro­duction/renderer_v8.c3

Demonstrační příklady ze druhého článku o jazyku C3:

# Příklad Stručný popis Adresa
13 01_just_main.c3 struktura nejjednoduššího programu obsahujícího pouze prázdnou funkci main https://github.com/tisnik/c3-examples/blob/master/c3-basics/01_just_main.c3
14 02_module_name.c3 struktura programu s uvedeným plným jménem modulu https://github.com/tisnik/c3-examples/blob/master/c3-basics/02_module_name.c3
15 03_hello_world.c3 klasický program typu „Hello, world!“ napsaný v jazyku C3 https://github.com/tisnik/c3-examples/blob/master/c3-basics/03_hello_world.c3
16 04_exit_value.c3 ukončení procesu s předáním návratového kódu zpět volajícímu programu https://github.com/tisnik/c3-examples/blob/master/c3-basics/04_exit_value.c3
17 05_c_function.c3 zavolání funkce definované v knihovně programovacího jazyka C https://github.com/tisnik/c3-examples/blob/master/c3-basics/05_c_function.c3
       
18 06_bool_type.c3 definice proměnných typu pravdivostní hodnota (bool) https://github.com/tisnik/c3-examples/blob/master/c3-basics/06_bool_type.c3
19 07_int_to_bool.c3 implicitní převod hodnoty typu int na pravdivostní hodnotu (nekorektní řešení) https://github.com/tisnik/c3-examples/blob/master/c3-basics/07_int_to_bool.c3
20 08_int_to_bool.c3 explicitní převod hodnoty typu int na pravdivostní hodnotu (korektní řešení) https://github.com/tisnik/c3-examples/blob/master/c3-basics/08_int_to_bool.c3
21 09_int_to_bool.c3 explicitní převod hodnoty typu int na pravdivostní hodnotu (nekorektní řešení) https://github.com/tisnik/c3-examples/blob/master/c3-basics/09_int_to_bool.c3
22 10_bool_sizeof.c3 zjištění velikosti paměti obsazené hodnotou typu bool https://github.com/tisnik/c3-examples/blob/master/c3-basics/10_bool_sizeof.c3
       
23 11_int_types.c3 definice proměnných typu celé číslo se znaménkem s různou bitovou šířkou https://github.com/tisnik/c3-examples/blob/master/c3-basics/11_int_types.c3
24 12_uint_types.c3 definice proměnných typu celé číslo bez znaménka s různou bitovou šířkou https://github.com/tisnik/c3-examples/blob/master/c3-basics/12_uint_types.c3
25 13_no_suffixes.c3 celočíselné konstanty bez uvedení suffixu (bitové šířky) https://github.com/tisnik/c3-examples/blob/master/c3-basics/13_no_suffixes.c3
26 14_suffixes.c3 celočíselné konstanty s uvedením sufficu (bitové šířky) https://github.com/tisnik/c3-examples/blob/master/c3-basics/14_suffixes.c3
27 15_int_sizeof.c3 zjištění velikosti paměti obsazené celočíselnými hodnotami se znaménkem https://github.com/tisnik/c3-examples/blob/master/c3-basics/15_int_sizeof.c3
28 16_uint_sizeof.c3 zjištění velikosti paměti obsazené celočíselnými hodnotami bez znaménka https://github.com/tisnik/c3-examples/blob/master/c3-basics/16_uint_sizeof.c3
29 17_int_conversions.c3 korektní převody mezi celočíselnými hodnotami s různou bitovou šířkou https://github.com/tisnik/c3-examples/blob/master/c3-basics/17_int_conversions.c3
30 18_int_conversions.c3 nekorektní převody mezi celočíselnými hodnotami s různou bitovou šířkou https://github.com/tisnik/c3-examples/blob/master/c3-basics/18_int_conversions.c3
31 19_int_conversions.c3 explicitní převody a přetečení hodnot https://github.com/tisnik/c3-examples/blob/master/c3-basics/19_int_conversions.c3
       
32 20_float_types.c3 definice proměnných typu numerická hodnota s plovoucí řádovou čárkou (tečkou) https://github.com/tisnik/c3-examples/blob/master/c3-basics/20_float_types.c3
       
33 21_vector_type.c3 definice vektoru obsahujícího celočíselné hodnoty https://github.com/tisnik/c3-examples/blob/master/c3-basics/21_vector_type.c3
34 22_vector_operations.c3 základní operace s celými vektory https://github.com/tisnik/c3-examples/blob/master/c3-basics/22_vector_operations.c3
35 23_vector_sizes.c3 zjištění a tisk velikosti vektorů (různé datové typy prvků vektorů, shodná délka) https://github.com/tisnik/c3-examples/blob/master/c3-basics/23_vector_sizes.c3
36 24_vector_sizes.c3 zjištění a tisk velikosti vektorů (stejné datové typy prvků vektorů, odlišná délka) https://github.com/tisnik/c3-examples/blob/master/c3-basics/24_vector_sizes.c3

Demonstrační příklady použité ve třetím článku o jazyku C3:

# Příklad Stručný popis Adresa
37 01_vector_type.c3 definice vektoru, modifikace prvků vektoru, tisk obsahu celého vektoru https://github.com/tisnik/c3-examples/blob/master/c3-containers/01_vector_type.c3
38 02_vector_parameter.c3 předání vektoru do funkce hodnotou https://github.com/tisnik/c3-examples/blob/master/c3-containers/02_vector_parameter.c3
39 03_vector_pointer.c3 předání vektoru do funkce odkazem (přes ukazatel) https://github.com/tisnik/c3-examples/blob/master/c3-containers/03_vector_pointer.c3
       
40 04_array_type.c3 definice pole, modifikace prvků pole, tisk obsahu celého pole https://github.com/tisnik/c3-examples/blob/master/c3-containers/04_array_type.c3
41 05_array_parameter.c3 předání pole do funkce hodnotou https://github.com/tisnik/c3-examples/blob/master/c3-containers/05_array_parameter.c3
42 06_array_pointer.c3 předání pole do funkce odkazem (přes ukazatel) https://github.com/tisnik/c3-examples/blob/master/c3-containers/06_array_pointer.c3
       
43 07_slice_type.c3 vytvoření (konstrukce) řezu (slice) https://github.com/tisnik/c3-examples/blob/master/c3-containers/07_slice_type.c3
44 08_slice_parameter.c3 předání řezu do funkce https://github.com/tisnik/c3-examples/blob/master/c3-containers/08_slice_parameter.c3
45 09_slice_slicing.c3 konstrukce řezu z pole stejně pojmenovanou operací (řez od..do) https://github.com/tisnik/c3-examples/blob/master/c3-containers/09_slice_slicing.c3
46 10_slice_slicing.c3 konstrukce řezu z pole stejně pojmenovanou operací (záporné indexy) https://github.com/tisnik/c3-examples/blob/master/c3-containers/10_slice_slicing.c3
47 11_slice_slicing.c3 konstrukce řezu z pole stejně pojmenovanou operací (určení délky řezu) https://github.com/tisnik/c3-examples/blob/master/c3-containers/11_slice_slicing.c3
48 12_slice_of_slice.c3 konstrukce řezu z jiného řezu https://github.com/tisnik/c3-examples/blob/master/c3-containers/12_slice_of_slice.c3
       
49 13_list_type.c3 vytvoření (konstrukce) seznamu https://github.com/tisnik/c3-examples/blob/master/c3-containers/13_list_type.c3
50 14_list_parameter.c3 předání seznamu do funkce https://github.com/tisnik/c3-examples/blob/master/c3-containers/14_list_parameter.c3
       
51 15_dynamic_array.c3 vytvoření (konstrukce) dynamicky alokovaného pole https://github.com/tisnik/c3-examples/blob/master/c3-containers/15_dynamic_array.c3
       
52 16_string_type.c3 základní typ řetězce string https://github.com/tisnik/c3-examples/blob/master/c3-containers/16_string_type.c3
53 17_string_unicode.c3 Unicode znaky v řetězci typu string https://github.com/tisnik/c3-examples/blob/master/c3-containers/17_string_unicode.c3
54 18_zstring_type.c3 řetězce ukončené nulou (C-string, ASCIIZ) https://github.com/tisnik/c3-examples/blob/master/c3-containers/18_zstring_type.c3
55 19_zstring_unicode.c3 Unicode znaky v řetězci typu zstring https://github.com/tisnik/c3-examples/blob/master/c3-containers/19_zstring_unicode.c3
56 20_string_comparison.c3 porovnávání obsahu řetězců https://github.com/tisnik/c3-examples/blob/master/c3-containers/20_string_comparison.c3

Demonstrační příklady ze čtvrtého o jazyku C3:

# Příklad Stručný popis Adresa
57 01_program_stub.c3 struktura programu s uvedeným plným jménem modulu https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/01_program_stub.c3
       
58 02_if.c3 nejjednodušší forma rozvětvení založené na konstrukci if https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/02_if.c3
59 03_if_else.c3 plné rozvětvení realizované konstrukcí if-else https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/03_if_else.c3
60 04_improper_if.c3 nekorektní způsob zápisu programové konstrukce if-else (porovnání s jazykem C) https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/04_improper_if.c3
61 05_improper_if.c3 nekorektní způsob zápisu programové konstrukce if-else (porovnání s jazykem C) https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/05_improper_if.c3
62 06_if_else_if.c3 složitější rozvětvení založené na programové konstrukci if-else if-else https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/06_if_else_if.c3
       
63 07_switch_basic.c3 základní forma vícenásobného rozvětvení založeného na konstrukci switch-case https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/07_switch_basic.c3
64 08_switch_basic.c3 větší množství podmínek a programová konstrukce switch-case https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/08_switch_basic.c3
65 09_switch_condition.c3 podmínky zapsané ve větvích programové konstrukci switch-case vyhodnocované v čase běhu procesu https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/09_switch_condition.c3
66 10_switch_true.c3 konstrukce switch-case bez uvedeného výrazu za klíčovým slovem switch https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/10_switch_true.c3
67 11_switch_break.c3 zápis prázdné větve default v programové konstrukci switch-case https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/11_switch_break.c3
68 12_switch_nextcase.c3 pokračování ve vykonávání konstrukce switch-case vynucené klíčovým slovem nextcase https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/12_switch_nextcase.c3
       
69 13_for_loop.c3 základní forma programové smyčky realizované klíčovým slovem for https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/13_for_loop.c3
70 14_foreach_loop.c3 základní forma programové smyčky typu for-each https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/14_foreach_loop.c3
71 15_foreach_loop.c3 programová smyčka for-each vracející index prvku i hodnotu prvku https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/15_foreach_loop.c3
72 16_foreach_loop.c3 modifikace obsahu pole v programové smyčce for-each https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/16_foreach_loop.c3
73 17_foreach_loop.c3 pokus o modifikaci obsahu procházeného pole https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/17_foreach_loop.c3
74 18_foreach_loop.c3 modifikace procházeného pole přes ukazatel na prvek https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/18_foreach_loop.c3
75 19_foreach_r_loop.c3 programová smyčka for-each, ve které se sekvencí prochází v opačném pořadí https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/19_foreach_r_loop.c3
       
76 20_while_loop.c3 základní forma programové smyčky typu while https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/20_while_loop.c3
77 21_while_loop2.c3 programová smyčka typu while s konstrukcí break https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/21_while_loop2.c3
78 22_nested_loops.c3 realizace vnořených programových smyček https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/22_nested_loops.c3
79 23_break.c3 vnořené programové smyčky a příkaz break: ukončení vnitřní smyčky https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/23_break.c3
80 24_break.c3 vnořené programové smyčky a příkaz break: ukončení vnější smyčky https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/24_break.c3
81 25_break.c3 vnořené programové smyčky a příkaz break, varianta se smyčkami typu while https://github.com/tisnik/c3-examples/blob/master/c3-control-flow/25_break.c3

Demonstrační příklady z pátého článku o jazyku C3:

# Příklad Stručný popis Adresa
82 01_regular_variable.c3 definice běžné proměnné typu int, přístup k hodnotě této proměnné https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/01_regular_variable.c3
83 02_optional_value.c3 definice proměnné typu Optional int, pokus o přímý přístup k hodnotě této proměnné (nekorektní varianta) https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/02_optional_value.c3
84 03_optional_value.c3 korektní čtení proměnné typu Optional int s detekcí chyby https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/03_optional_value.c3
85 04_optional_value.c3 korektní čtení proměnné typu Optional int s detekcí chyby https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/04_optional_value.c3
86 05_fault.c3 uživatelsky definovaný typ nesoucí informaci o chybě https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/05_fault.c3
87 06_fault.c3 uživatelsky definovaný typ nesoucí informaci o chybě https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/06_fault.c3
88 07_force_unwrap.c3 použití operátoru !! (force unwrap) https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/07_force_unwrap.c3
89 08_force_unwrap.c3 použití operátoru !! (force unwrap) https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/08_force_unwrap.c3
       
90 09_factorial.c3 běžný výpočet faktoriálu bez reakce na neplatný vstup https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/09_factorial.c3
91 10_factorial.c3 výpočet faktoriálu s reakcí na neplatný vstup – řešení bez kontroly návratové hodnoty https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/10_factorial.c3
92 11_factorial.c3 výpočet faktoriálu s reakcí na neplatný vstup – řešení s kontrolou návratové hodnoty https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/11_factorial.c3
       
93 12_defer_basic_usage.c3 konstrukce defer v programovacím jazyce C3 https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/12_defer_basic_usage.c3
94 13_more_defers.c3 pořadí provádění příkazů v blocích defer https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/13_more_defers.c3
95 14_defer_scope.c3 konstrukce defer definovaná ve vnitřních blocích v jazyce C3 https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/14_defer_scope.c3
96 15_defer_return.c3 konstrukce defer a return https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/15_defer_return.c3
       
97 16_init_finalize.c3 funkce označené jako @init a @finalizer https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/16_init_finalize.c3
       
98 defer.go konstrukce defer v programovacím jazyce Go https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/defer.go
99 defer_scope.go konstrukce defer definovaná ve vnitřních blocích v jazyce Go https://github.com/tisnik/c3-examples/blob/master/c3-errors-handling/defer_scope.go

Následují odkazy na demonstrační příklady z článku předchozího:

# Příklad Stručný popis Adresa
100 01_regular_function.c3 deklarace běžných funkcí v jazyku C3 https://github.com/tisnik/c3-examples/blob/master/c3-functions/01_regular_function.c3
101 02_check_arguments.c3 kontrola parametrů předávaných do funkce překladačem jazyka C3 https://github.com/tisnik/c3-examples/blob/master/c3-functions/02_check_arguments.c3
       
102 03_default_arguments.c3 funkce s jedním parametrem, který má nastavenou výchozí hodnotu a jedním běžným parametrem (korektní pořadí parametrů) https://github.com/tisnik/c3-examples/blob/master/c3-functions/03_default_arguments.c3
103 04_default_arguments.c3 funkce se všemi parametry s nastavenu výchozí hodnotou https://github.com/tisnik/c3-examples/blob/master/c3-functions/04_default_arguments.c3
104 05_default_arguments.c3 funkce s jedním parametrem, který má nastavenou výchozí hodnotu a jedním běžným parametrem (nekorektní pořadí parametrů) https://github.com/tisnik/c3-examples/blob/master/c3-functions/05_default_arguments.c3
       
105 06_named_arguments.c3 explicitní uvedení jmen parametrů při volání funkce https://github.com/tisnik/c3-examples/blob/master/c3-functions/06_named_arguments.c3
106 07_named_arguments.c3 explicitní uvedení jmen parametrů při volání funkce https://github.com/tisnik/c3-examples/blob/master/c3-functions/07_named_arguments.c3
107 08_named_default_arguments.c3 pojmenování parametrů s výchozí hodnotou při volání funkce https://github.com/tisnik/c3-examples/blob/master/c3-functions/08_named_default_ar­guments.c3
       
108 09_sum.c3 realizace funkce pro výpočet součtu všech předaných hodnot https://github.com/tisnik/c3-examples/blob/master/c3-functions/09_sum.c3
109 10_sum.c3 předání obsahu pole do funkce s proměnným počtem parametrů https://github.com/tisnik/c3-examples/blob/master/c3-functions/10_sum.c3
110 11_varargs.c3 pořadí předávání parametrů do funkce s proměnným počtem parametrů (nekorektní způsob použití) https://github.com/tisnik/c3-examples/blob/master/c3-functions/11_varargs.c3
111 12_varargs.c3 pořadí předávání parametrů do funkce s proměnným počtem parametrů (korektní způsob použití) https://github.com/tisnik/c3-examples/blob/master/c3-functions/12_varargs.c3
       
112 13_optional.c3 funkce vracející hodnotu typu Optional https://github.com/tisnik/c3-examples/blob/master/c3-functions/13_optional.c3
113 14_optional.c3 využití operátoru ?? https://github.com/tisnik/c3-examples/blob/master/c3-functions/14_optional.c3
       
114 15_contract.c3 kontrakty uvedené u funkcí https://github.com/tisnik/c3-examples/blob/master/c3-functions/15_contract.c3
115 16_contract.c3 kontrakty uvedené u funkcí https://github.com/tisnik/c3-examples/blob/master/c3-functions/16_contract.c3
       
116 17_c_declaration.c3 deklarace funkce bez parametrů „céčkovým způsobem“ (nekorektní zápis) https://github.com/tisnik/c3-examples/blob/master/c3-functions/17_c_declaration.c3
117 18_check_return_type.c3 kontrola návratové hodnoty překladačem jazyka C3 https://github.com/tisnik/c3-examples/blob/master/c3-functions/18_check_return_type.c3
118 19_check_return_value.c3 kontrola počtu návratových hodnot překladačem jazyka C3 https://github.com/tisnik/c3-examples/blob/master/c3-functions/19_check_return_value.c3
119 20_in_out_params.c3 předání ukazatelů do volané funkce https://github.com/tisnik/c3-examples/blob/master/c3-functions/20_in_out_params.c3
120 21_in_out_params.c3 označení ukazatelů kontrakty [in] a [out] https://github.com/tisnik/c3-examples/blob/master/c3-functions/21_in_out_params.c3
121 22_in_out_params.c3 označení ukazatelů kontrakty [in] a [out] https://github.com/tisnik/c3-examples/blob/master/c3-functions/22_in_out_params.c3
122 23_void_pointer.c3 předávání ukazatelů typu void * do volané funkce https://github.com/tisnik/c3-examples/blob/master/c3-functions/23_void_pointer.c3
123 24_contract.c3 kontrakt zapsaný před hlavičkou funkce https://github.com/tisnik/c3-examples/blob/master/c3-functions/24_contract.c4

A konečně následují odkazy na demonstrační příklady z článku dnešního:

# Příklad Stručný popis Adresa
124 25_function_type.c3 definice nového datového typu „funkce“ https://github.com/tisnik/c3-examples/blob/master/c3-functions/25_function_type.c3
       
125 26_short_function.c3 zkrácený způsob zápisu běžné funkce https://github.com/tisnik/c3-examples/blob/master/c3-functions/26_short_function.c3
126 27_short_default_argument.c3 zkrácený způsob zápisu funkce s výchozí hodnotou parametru https://github.com/tisnik/c3-examples/blob/master/c3-functions/27_short_default_argument.c3
127 28_short_default_argument.c3 zkrácený způsob zápisu funkce s výchozí hodnotou parametrů https://github.com/tisnik/c3-examples/blob/master/c3-functions/28_short_default_argument.c3
128 29_short_named_argument.c3 zkrácený způsob zápisu funkce, při jejím volání jsou explicitně uvedena jména parametrů https://github.com/tisnik/c3-examples/blob/master/c3-functions/29_short_named_argument.c3
129 30_short_first.c3 zkrácený způsob zápisu funkce akceptující proměnný počet parametrů https://github.com/tisnik/c3-examples/blob/master/c3-functions/30_short_first.c3
130 31_short_ternary.c3 zkrácený způsob zápisu funkce, která ve svém těle vyžaduje ternární operátor https://github.com/tisnik/c3-examples/blob/master/c3-functions/31_short_ternary.c3
       
131 32_anonymous.c3 příklad, v němž jsou definovány dvě logicky podobné funkce https://github.com/tisnik/c3-examples/blob/master/c3-functions/32_anonymous.c3
132 33_anonymous.c3 využití anonymních funkcí namísto dvojice logicky podobných funkcí https://github.com/tisnik/c3-examples/blob/master/c3-functions/33_anonymous.c3
133 34_anonymous.c3 definice a zavolání anonymní funkce provedené na jediném řádku zdrojového kódu https://github.com/tisnik/c3-examples/blob/master/c3-functions/34_anonymous.c3
134 35_anonymous.c3 pokus o definici uzávěru (closure) https://github.com/tisnik/c3-examples/blob/master/c3-functions/35_anonymous.c3
       
135 36_function_pointers.c3 předání ukazatele na funkce https://github.com/tisnik/c3-examples/blob/master/c3-functions/36_function_pointers.c3
136 37_function_pointers.c3 předání ukazatele na funkce (zkrácený zápis funkce) https://github.com/tisnik/c3-examples/blob/master/c3-functions/37_function_pointers.c3
137 38_return_function.c3 funkce vracející jinou funkci https://github.com/tisnik/c3-examples/blob/master/c3-functions/38_return_function.c3
       
138 39_call_c_function.c3 volání standardní céčkové funkce puts https://github.com/tisnik/c3-examples/blob/master/c3-functions/39_call_c_function.c3
139 40_call_c_function.c3 volání nativní céčkové funkce add https://github.com/tisnik/c3-examples/blob/master/c3-functions/40_call_c_function.c3
140 41_call_c_function.c3 volání nativní céčkové funkce multiply s korektními datovými typy https://github.com/tisnik/c3-examples/blob/master/c3-functions/41_call_c_function.c3
141 42_call_c_function.c3 volání nativní céčkové funkce akceptující pole (první způsob) https://github.com/tisnik/c3-examples/blob/master/c3-functions/42_call_c_function.c3
142 43_call_c_function.c3 volání nativní céčkové funkce akceptující pole (druhý způsob) https://github.com/tisnik/c3-examples/blob/master/c3-functions/43_call_c_function.c3
141 42_call_c_function.c3 volání nativní céčkové funkce akceptující pole (první způsob) https://github.com/tisnik/c3-examples/blob/master/c3-functions/42_call_c_function.c3
       
143 44_method.c3 zavolání metody (první způsob) https://github.com/tisnik/c3-examples/blob/master/c3-functions/44_method.c3
144 45_method.c3 zavolání metody (druhý způsob) https://github.com/tisnik/c3-examples/blob/master/c3-functions/45_method.c3

20. Odkazy na Internetu

  1. Programovací jazyk C3: evoluce, nikoli revoluce
    https://www.root.cz/clanky/pro­gramovaci-jazyk-c3-evoluce-nikoli-revoluce/
  2. Programovací jazyk C3: datové typy pro moderní architektury
    https://www.root.cz/clanky/pro­gramovaci-jazyk-c3-datove-typy-pro-moderni-architektury/
  3. Programovací jazyk C3: složené datové typy a kontejnery
    https://www.root.cz/clanky/pro­gramovaci-jazyk-c3-slozene-datove-typy-a-kontejnery/
  4. The C3 Programming Language
    https://c3-lang.org/
  5. C3 For C Programmers
    https://c3-lang.org/language-overview/primer/
  6. C3 is a C-like language trying to be an incremental improvement over C rather than a whole new language
    https://www.reddit.com/r/Pro­grammingLanguages/comments/o­ohij6/c3_is_a_clike_langu­age_trying_to_be_an/
  7. Tiobe index
    https://www.tiobe.com/tiobe-index/
  8. PYPL PopularitY of Programming Language
    https://pypl.github.io/PYPL.html
  9. C3 Tutorial
    https://learn-c3.org/
  10. History of programming languages
    https://devskiller.com/history-of-programming-languages/
  11. History of programming languages (Wikipedia)
    https://en.wikipedia.org/wi­ki/History_of_programming_lan­guages
  12. D language
    https://dlang.org/
  13. Zig programming language
    https://ziglang.org/
  14. V language
    https://vlang.io/
  15. D programming language
    https://en.wikipedia.org/wi­ki/D_(programming_language)
  16. Zig programming language (Wikipedia)
    https://en.wikipedia.org/wi­ki/Zig_(programming_langu­age)
  17. V programming language (Wikipedia)
    https://en.wikipedia.org/wi­ki/V_(programming_language)
  18. Syntax highlighting for C3's programming language
    https://github.com/Airbus5717/c3.vim
  19. Go factorial
    https://gist.github.com/e­simov/9622710
  20. Generational list of programming languages
    https://en.wikipedia.org/wi­ki/Generational_list_of_pro­gramming_languages
  21. The Language Tree: Almost Every Programming Language Ever Made
    https://github.com/Phileo­sopher/langmap
  22. List of C-family programming languages
    https://en.wikipedia.org/wi­ki/List_of_C-family_programming_languages
  23. Compatibility of C and C++
    https://en.wikipedia.org/wi­ki/Compatibility_of_C_and_C%2B%2B
  24. C++23: compatibility with C
    https://www.sandordargo.com/blog/2023/08/23/cpp­23-c-compatibility
  25. Can C++ Run C Code? Understanding Language Compatibility
    https://www.codewithc.com/can-c-run-c-code-understanding-language-compatibility/
  26. C3: Comparisons With Other Languages
    https://c3-lang.org/faq/compare-languages/
  27. C3 Programming Language Gains Traction as Modern C Alternative
    https://biggo.com/news/202504040125_C3_Pro­gramming_Language_Alterna­tive_to_C
  28. The case against a C alternative
    https://c3.handmade.networ­k/blog/p/8486-the_case_against_a_c_alternative
  29. C (programming language) Alternatives
    https://alternativeto.net/software/c-programming-language-/
  30. Seriál Programovací jazyk Go
    https://www.root.cz/seria­ly/programovaci-jazyk-go/
  31. Is C3 the Underdog That Will Overtake Zig and Odin?
    https://bitshifters.cc/2025/05/22/c3-c-tradition.html
  32. „Hello, World!“ program
    https://en.wikipedia.org/wi­ki/%22Hello%2C_World!%22_pro­gram
  33. The C Programming Language
    https://en.wikipedia.org/wi­ki/The_C_Programming_Langu­age
  34. Kontejner (abstraktní datový typ)
    https://cs.wikipedia.org/wi­ki/Kontejner_(abstraktn%C3%AD_da­tov%C3%BD_typ)
  35. Are arrays not considered containers because they are not based off of a class?
    https://stackoverflow.com/qu­estions/37710975/are-arrays-not-considered-containers-because-they-are-not-based-off-of-a-class
  36. Array declaration (C, C++)
    https://en.cppreference.com/w/cpp/lan­guage/array.html
  37. Understanding the Apple ‘goto fail;’ vulnerability
    https://www.blackduck.com/blog/un­derstanding-apple-goto-fail-vulnerability-2.html
  38. Branch (computer science)
    https://en.wikipedia.org/wi­ki/Branch_(computer_scien­ce)
  39. Conditional (computer programming)
    https://en.wikipedia.org/wi­ki/Conditional_(computer_pro­gramming)
  40. Dangling else
    https://en.wikipedia.org/wi­ki/Dangling_else
  41. Switch statement
    https://en.wikipedia.org/wi­ki/Switch_statement
  42. Compiler correctness
    https://en.wikipedia.org/wi­ki/Compiler_correctness
  43. Anonymous function
    https://en.wikipedia.org/wi­ki/Anonymous_function
  44. Closure (computer programming)
    https://en.wikipedia.org/wi­ki/Closure_(computer_program­ming)
  45. How to implement closures in C
    https://hokstad.com/how-to-implement-closures
Neutrální ikona do widgetu na odběr článků ze seriálů

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.


Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.